mirror of
https://github.com/armbian/build
synced 2025-09-24 19:47:06 +07:00
kernel: drop dead code & patches from long-disabled kernel-drivers.sh/drivers_network.sh stuff
- this has been dead code (never called) for some 6 months now - having it there makes it hard to find the actual/real callpoints of non-dead code
This commit is contained in:
@@ -16,7 +16,7 @@ function kernel_drivers_create_patches() {
|
|||||||
kernel_drivers_patch_file="undetermined" # outer scope
|
kernel_drivers_patch_file="undetermined" # outer scope
|
||||||
|
|
||||||
declare hash_files # any changes in these files will trigger a cache miss; also any changes in misc .patch with "wireless" at start or "wifi" anywhere in the name
|
declare hash_files # any changes in these files will trigger a cache miss; also any changes in misc .patch with "wireless" at start or "wifi" anywhere in the name
|
||||||
calculate_hash_for_files "${SRC}/lib/functions/compilation/patch/drivers_network.sh" "${SRC}/lib/functions/compilation/patch/drivers-harness.sh" "${SRC}"/patch/misc/wireless*.patch "${SRC}"/patch/misc/*wifi*.patch
|
calculate_hash_for_files "${SRC}/lib/functions/compilation/patch/drivers_network.sh" "${SRC}/lib/functions/compilation/patch/drivers-harness.sh" "${SRC}"/patch/misc/wireless*.patch
|
||||||
|
|
||||||
declare cache_key_base="${KERNEL_MAJOR_MINOR}_${LINUXFAMILY}"
|
declare cache_key_base="${KERNEL_MAJOR_MINOR}_${LINUXFAMILY}"
|
||||||
declare cache_key="${cache_key_base}_${hash_files}"
|
declare cache_key="${cache_key_base}_${hash_files}"
|
||||||
|
|||||||
@@ -688,28 +688,3 @@ driver_rtl8723cs() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
patch_drivers_network() {
|
|
||||||
display_alert "Patching network related drivers"
|
|
||||||
|
|
||||||
driver_generic_bring_back_ipx
|
|
||||||
driver_rtl8152_rtl8153
|
|
||||||
driver_rtl8189ES
|
|
||||||
driver_rtl8189FS
|
|
||||||
driver_rtl8192EU
|
|
||||||
driver_rtl8811_rtl8812_rtl8814_rtl8821
|
|
||||||
driver_xradio_xr819
|
|
||||||
driver_rtl8811CU_rtl8821C
|
|
||||||
driver_rtl8188EU_rtl8188ETV
|
|
||||||
driver_rtl88x2bu
|
|
||||||
driver_rtw88
|
|
||||||
driver_rtl88x2cs
|
|
||||||
driver_rtl8822cs_bt
|
|
||||||
driver_rtl8723DS
|
|
||||||
driver_rtl8723DU
|
|
||||||
driver_rtl8822BS
|
|
||||||
driver_uwe5622_allwinner
|
|
||||||
driver_rtl8723cs
|
|
||||||
|
|
||||||
display_alert "Network related drivers patched" "" "info"
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,288 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
#
|
|
||||||
# SPDX-License-Identifier: GPL-2.0
|
|
||||||
#
|
|
||||||
# Copyright (c) 2013-2023 Igor Pecovnik, igor@armbian.com
|
|
||||||
#
|
|
||||||
# This file is a part of the Armbian Build Framework
|
|
||||||
# https://github.com/armbian/build/
|
|
||||||
|
|
||||||
# @TODO: armbian-next: THIS IS DEAD CODE. no-one calls it. a JIRA for volunteers to fix it, or it will be removed.
|
|
||||||
|
|
||||||
function prepare_extra_kernel_drivers() {
|
|
||||||
|
|
||||||
source ${SRC}/lib/functions/compilation/patch/drivers_network.sh
|
|
||||||
|
|
||||||
# Packaging patch for modern kernels should be one for all.
|
|
||||||
# Currently we have it per kernel family since we can't have one
|
|
||||||
# Maintaining one from central location starting with 5.3+
|
|
||||||
# Temporally set for new "default->legacy,next->current" family naming
|
|
||||||
|
|
||||||
if linux-version compare "${version}" ge 5.10; then
|
|
||||||
if linux-version compare "${version}" le 5.11; then
|
|
||||||
# Patch python2 path for legacy kernels running on newer Debian Bulleys / Ubuntu Kinetic
|
|
||||||
# Debian has a deb package the symlinks /usr/bin/python3 to /usr/bin/python so better off to Patch older Kernels
|
|
||||||
display_alert "Patching" "python" "info"
|
|
||||||
process_patch_file "${SRC}/patch/misc/general-kernel-python2-5.10.y.patch" "applying"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test -d ${kerneldir}/debian; then
|
|
||||||
rm -rf ${kerneldir}/debian/*
|
|
||||||
fi
|
|
||||||
sed -i -e '
|
|
||||||
s/^KBUILD_IMAGE := \$(boot)\/Image\.gz$/KBUILD_IMAGE := \$(boot)\/Image/
|
|
||||||
' ${kerneldir}/arch/arm64/Makefile
|
|
||||||
|
|
||||||
rm -f ${kerneldir}/scripts/package/{builddeb,mkdebian}
|
|
||||||
|
|
||||||
cp ${SRC}/packages/armbian/builddeb ${kerneldir}/scripts/package/builddeb
|
|
||||||
cp ${SRC}/packages/armbian/mkdebian ${kerneldir}/scripts/package/mkdebian
|
|
||||||
|
|
||||||
chmod 755 ${kerneldir}/scripts/package/{builddeb,mkdebian}
|
|
||||||
|
|
||||||
elif linux-version compare "${version}" ge 5.8.17 &&
|
|
||||||
linux-version compare "${version}" le 5.9 ||
|
|
||||||
linux-version compare "${version}" ge 5.9.2; then
|
|
||||||
display_alert "Adjusting" "packaging" "info"
|
|
||||||
cd "$kerneldir" || exit
|
|
||||||
process_patch_file "${SRC}/patch/misc/general-packaging-5.8-9.y.patch" "applying"
|
|
||||||
elif linux-version compare "${version}" ge 5.6; then
|
|
||||||
display_alert "Adjusting" "packaging" "info"
|
|
||||||
cd "$kerneldir" || exit
|
|
||||||
process_patch_file "${SRC}/patch/misc/general-packaging-5.6.y.patch" "applying"
|
|
||||||
elif linux-version compare "${version}" ge 5.3; then
|
|
||||||
display_alert "Adjusting" "packaging" "info"
|
|
||||||
cd "$kerneldir" || exit
|
|
||||||
process_patch_file "${SRC}/patch/misc/general-packaging-5.3.y.patch" "applying"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ "${version}" == "4.19."* ]] && [[ "$LINUXFAMILY" == sunxi* || "$LINUXFAMILY" == meson64 ||
|
|
||||||
"$LINUXFAMILY" == mvebu64 || "$LINUXFAMILY" == mt7623 || "$LINUXFAMILY" == mvebu ]]; then
|
|
||||||
display_alert "Adjusting" "packaging" "info"
|
|
||||||
cd "$kerneldir" || exit
|
|
||||||
process_patch_file "${SRC}/patch/misc/general-packaging-4.19.y.patch" "applying"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ "${version}" == "4.19."* ]] && [[ "$LINUXFAMILY" == rk35xx ]]; then
|
|
||||||
display_alert "Adjusting" "packaging" "info"
|
|
||||||
cd "$kerneldir" || exit
|
|
||||||
process_patch_file "${SRC}/patch/misc/general-packaging-4.19.y-rk35xx.patch" "applying"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ "${version}" == "4.14."* ]] && [[ "$LINUXFAMILY" == s5p6818 || "$LINUXFAMILY" == mvebu64 ||
|
|
||||||
"$LINUXFAMILY" == imx7d || "$LINUXFAMILY" == odroidxu4 || "$LINUXFAMILY" == mvebu ]]; then
|
|
||||||
display_alert "Adjusting" "packaging" "info"
|
|
||||||
cd "$kerneldir" || exit
|
|
||||||
process_patch_file "${SRC}/patch/misc/general-packaging-4.14.y.patch" "applying"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ "${version}" == "4.4."* || "${version}" == "4.9."* ]] &&
|
|
||||||
[[ "$LINUXFAMILY" == rockpis || "$LINUXFAMILY" == rk3399 ]]; then
|
|
||||||
display_alert "Adjusting" "packaging" "info"
|
|
||||||
cd "$kerneldir" || exit
|
|
||||||
process_patch_file "${SRC}/patch/misc/general-packaging-4.4.y-rk3399.patch" "applying"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ "${version}" == "4.4."* ]] &&
|
|
||||||
[[ "$LINUXFAMILY" == rockchip64 || "$LINUXFAMILY" == media* ]]; then
|
|
||||||
display_alert "Adjusting" "packaging" "info"
|
|
||||||
cd "$kerneldir" || exit
|
|
||||||
if [[ $BOARD == nanopct4 ]]; then
|
|
||||||
process_patch_file "${SRC}/patch/misc/general-packaging-4.4.y-rk3399.patch" "applying"
|
|
||||||
else
|
|
||||||
process_patch_file "${SRC}/patch/misc/general-packaging-4.4.y-rockchip64.patch" "applying"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ "${version}" == "4.4."* ]] && [[ "$LINUXFAMILY" == rockchip || "$LINUXFAMILY" == rk322x ]]; then
|
|
||||||
display_alert "Adjusting" "packaging" "info"
|
|
||||||
cd "$kerneldir" || exit
|
|
||||||
process_patch_file "${SRC}/patch/misc/general-packaging-4.4.y.patch" "applying"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ "${version}" == "4.9."* ]] && [[ "$LINUXFAMILY" == meson64 || "$LINUXFAMILY" == odroidc4 ]]; then
|
|
||||||
display_alert "Adjusting" "packaging" "info"
|
|
||||||
cd "$kerneldir" || exit
|
|
||||||
process_patch_file "${SRC}/patch/misc/general-packaging-4.9.y.patch" "applying"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# After the patches have been applied,
|
|
||||||
# check and add debian package compression if required.
|
|
||||||
#
|
|
||||||
if [ "$(awk '/dpkg --build/{print $1}' $kerneldir/scripts/package/builddeb)" == "dpkg" ]; then
|
|
||||||
sed -i -e '
|
|
||||||
s/dpkg --build/dpkg-deb \${KDEB_COMPRESS:+-Z\$KDEB_COMPRESS} --build/
|
|
||||||
' "$kerneldir"/scripts/package/builddeb
|
|
||||||
fi
|
|
||||||
|
|
||||||
#
|
|
||||||
# Linux splash file (legacy)
|
|
||||||
#
|
|
||||||
|
|
||||||
# since plymouth introduction, boot scripts are not supporting this method anymore.
|
|
||||||
# In order to enable it, you need to use this: setenv consoleargs "bootsplash.bootfile=bootsplash.armbian ${consoleargs}"
|
|
||||||
|
|
||||||
if linux-version compare "${version}" ge 5.15 && linux-version compare "${version}" lt 6.1 && [ "${SKIP_BOOTSPLASH}" != yes ]; then
|
|
||||||
|
|
||||||
display_alert "Adding" "Kernel splash file" "info"
|
|
||||||
|
|
||||||
if linux-version compare "${version}" ge 5.19.6 ||
|
|
||||||
(linux-version compare "${version}" ge 5.15.64 && linux-version compare "${version}" lt 5.16); then
|
|
||||||
process_patch_file "${SRC}/patch/misc/bootsplash-5.19.y-Revert-fbdev-fbcon-release-buffer-when-fbcon_do_set.patch" "applying"
|
|
||||||
process_patch_file "${SRC}/patch/misc/bootsplash-5.19.y-Revert-fbdev-fbcon-Properly-revert-changes-when-vc_r.patch" "applying"
|
|
||||||
fi
|
|
||||||
|
|
||||||
process_patch_file "${SRC}/patch/misc/bootsplash-5.16.y-0000-Revert-fbcon-Avoid-cap-set-but-not-used-warning.patch" "applying"
|
|
||||||
process_patch_file "${SRC}/patch/misc/bootsplash-5.16.y-Revert-fbcon-Fix-accelerated-fbdev-scrolling-while-logo-is-still-shown.patch" "applying"
|
|
||||||
process_patch_file "${SRC}/patch/misc/bootsplash-5.16.y-0001-Revert-fbcon-Add-option-to-enable-legacy-hardware-ac.patch" "applying"
|
|
||||||
process_patch_file "${SRC}/patch/misc/bootsplash-5.16.y-0002-Revert-vgacon-drop-unused-vga_init_done.patch" "applying"
|
|
||||||
process_patch_file "${SRC}/patch/misc/bootsplash-5.16.y-0003-Revert-vgacon-remove-software-scrollback-support.patch" "applying"
|
|
||||||
process_patch_file "${SRC}/patch/misc/bootsplash-5.16.y-0004-Revert-drivers-video-fbcon-fix-NULL-dereference-in-f.patch" "applying"
|
|
||||||
process_patch_file "${SRC}/patch/misc/bootsplash-5.16.y-0005-Revert-fbcon-remove-no-op-fbcon_set_origin.patch" "applying"
|
|
||||||
process_patch_file "${SRC}/patch/misc/bootsplash-5.16.y-0006-Revert-fbcon-remove-now-unusued-softback_lines-curso.patch" "applying"
|
|
||||||
process_patch_file "${SRC}/patch/misc/bootsplash-5.16.y-0007-Revert-fbcon-remove-soft-scrollback-code.patch" "applying"
|
|
||||||
|
|
||||||
process_patch_file "${SRC}/patch/misc/0001-bootsplash.patch" "applying"
|
|
||||||
process_patch_file "${SRC}/patch/misc/0002-bootsplash.patch" "applying"
|
|
||||||
process_patch_file "${SRC}/patch/misc/0003-bootsplash.patch" "applying"
|
|
||||||
process_patch_file "${SRC}/patch/misc/0004-bootsplash.patch" "applying"
|
|
||||||
process_patch_file "${SRC}/patch/misc/0005-bootsplash.patch" "applying"
|
|
||||||
process_patch_file "${SRC}/patch/misc/0006-bootsplash.patch" "applying"
|
|
||||||
process_patch_file "${SRC}/patch/misc/0007-bootsplash.patch" "applying"
|
|
||||||
process_patch_file "${SRC}/patch/misc/0008-bootsplash.patch" "applying"
|
|
||||||
process_patch_file "${SRC}/patch/misc/0009-bootsplash.patch" "applying"
|
|
||||||
process_patch_file "${SRC}/patch/misc/0010-bootsplash.patch" "applying"
|
|
||||||
process_patch_file "${SRC}/patch/misc/0011-bootsplash.patch" "applying"
|
|
||||||
process_patch_file "${SRC}/patch/misc/0012-bootsplash.patch" "applying"
|
|
||||||
|
|
||||||
fi
|
|
||||||
|
|
||||||
#
|
|
||||||
# mac80211 wireless driver injection features from Kali Linux
|
|
||||||
#
|
|
||||||
|
|
||||||
if linux-version compare "${version}" ge 5.4 && [ $EXTRAWIFI == yes ]; then
|
|
||||||
|
|
||||||
display_alert "Adding" "Wireless package injections for mac80211 compatible chipsets" "info"
|
|
||||||
if linux-version compare "${version}" ge 5.9; then
|
|
||||||
process_patch_file "${SRC}/patch/misc/kali-wifi-injection-1-v5.9-post.patch" "applying"
|
|
||||||
else
|
|
||||||
process_patch_file "${SRC}/patch/misc/kali-wifi-injection-1-pre-v5.9.patch" "applying"
|
|
||||||
fi
|
|
||||||
process_patch_file "${SRC}/patch/misc/kali-wifi-injection-2.patch" "applying"
|
|
||||||
process_patch_file "${SRC}/patch/misc/kali-wifi-injection-3.patch" "applying"
|
|
||||||
|
|
||||||
fi
|
|
||||||
|
|
||||||
# AUFS - advanced multi layered unification filesystem for Kernel > 5.1
|
|
||||||
#
|
|
||||||
# Older versions have AUFS support with a patch
|
|
||||||
|
|
||||||
if linux-version compare "${version}" gt 5.11 && linux-version compare "${version}" lt 6.2 && [ "$AUFS" == yes ]; then
|
|
||||||
|
|
||||||
# attach to specifics tag or branch
|
|
||||||
local aufstag
|
|
||||||
aufstag=$(echo "${version}" | cut -f 1-2 -d ".")
|
|
||||||
aufsmajor=$(echo "${aufstag}" | cut -f 1 -d ".")
|
|
||||||
|
|
||||||
# manual overrides
|
|
||||||
if linux-version compare "${version}" ge 5.10.82 && linux-version compare "${version}" le 5.11; then aufstag="5.10.82"; fi
|
|
||||||
if linux-version compare "${version}" ge 5.15.41 && linux-version compare "${version}" le 5.16; then aufstag="5.15.41"; fi
|
|
||||||
if linux-version compare "${version}" ge 5.17.3 && linux-version compare "${version}" le 5.18; then aufstag="5.17.3"; fi
|
|
||||||
|
|
||||||
# check if Mr. Okajima already made a branch for this version
|
|
||||||
improved_git ls-remote --exit-code --heads $GITHUB_SOURCE/sfjro/aufs5-standalone "aufs${aufstag}" > /dev/null
|
|
||||||
|
|
||||||
if [ "$?" -ne "0" ]; then
|
|
||||||
# then use rc branch
|
|
||||||
aufstag="5.x-rcN"
|
|
||||||
improved_git ls-remote --exit-code --heads $GITHUB_SOURCE/sfjro/aufs5-standalone "aufs${aufstag}" > /dev/null
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$?" -eq "0" ]; then
|
|
||||||
|
|
||||||
display_alert "Adding" "AUFS ${aufstag}" "info"
|
|
||||||
local aufsver="branch:aufs${aufstag}"
|
|
||||||
fetch_from_repo "$GITHUB_SOURCE/sfjro/aufs5-standalone" "aufs5" "branch:${aufsver}" "yes"
|
|
||||||
cd "$kerneldir" || exit
|
|
||||||
process_patch_file "${SRC}/cache/sources/aufs5/${aufsver#*:}/aufs${aufsmajor}-kbuild.patch" "applying"
|
|
||||||
process_patch_file "${SRC}/cache/sources/aufs5/${aufsver#*:}/aufs${aufsmajor}-base.patch" "applying"
|
|
||||||
process_patch_file "${SRC}/cache/sources/aufs5/${aufsver#*:}/aufs${aufsmajor}-mmap.patch" "applying"
|
|
||||||
process_patch_file "${SRC}/cache/sources/aufs5/${aufsver#*:}/aufs${aufsmajor}-standalone.patch" "applying"
|
|
||||||
cp -R "${SRC}/cache/sources/aufs5/${aufsver#*:}"/{Documentation,fs} .
|
|
||||||
cp "${SRC}/cache/sources/aufs5/${aufsver#*:}"/include/uapi/linux/aufs_type.h include/uapi/linux/
|
|
||||||
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# WireGuard VPN for Linux 3.10 - 5.5
|
|
||||||
if linux-version compare "${version}" ge 3.10 && linux-version compare "${version}" le 5.5 && [ "${WIREGUARD}" == yes ]; then
|
|
||||||
|
|
||||||
# attach to specifics tag or branch
|
|
||||||
local wirever="branch:master"
|
|
||||||
|
|
||||||
display_alert "Adding" "WireGuard VPN for Linux 3.10 - 5.5 ${wirever} " "info"
|
|
||||||
fetch_from_repo "https://git.zx2c4.com/wireguard-linux-compat" "wireguard" "${wirever}" "yes"
|
|
||||||
|
|
||||||
cd "$kerneldir" || exit
|
|
||||||
rm -rf "$kerneldir/net/wireguard"
|
|
||||||
cp -R "${SRC}/cache/sources/wireguard/${wirever#*:}/src/" "$kerneldir/net/wireguard"
|
|
||||||
sed -i "/^obj-\\\$(CONFIG_NETFILTER).*+=/a obj-\$(CONFIG_WIREGUARD) += wireguard/" \
|
|
||||||
"$kerneldir/net/Makefile"
|
|
||||||
sed -i "/^if INET\$/a source \"net/wireguard/Kconfig\"" \
|
|
||||||
"$kerneldir/net/Kconfig"
|
|
||||||
# remove duplicates
|
|
||||||
[[ $(grep -c wireguard "$kerneldir/net/Makefile") -gt 1 ]] &&
|
|
||||||
sed -i '0,/wireguard/{/wireguard/d;}' "$kerneldir/net/Makefile"
|
|
||||||
[[ $(grep -c wireguard "$kerneldir/net/Kconfig") -gt 1 ]] &&
|
|
||||||
sed -i '0,/wireguard/{/wireguard/d;}' "$kerneldir/net/Kconfig"
|
|
||||||
# headers workaround
|
|
||||||
display_alert "Patching WireGuard" "Applying workaround for headers compilation" "info"
|
|
||||||
sed -i '/mkdir -p "$destdir"/a mkdir -p "$destdir"/net/wireguard; \
|
|
||||||
touch "$destdir"/net/wireguard/{Kconfig,Makefile} # workaround for Wireguard' \
|
|
||||||
"$kerneldir/scripts/package/builddeb"
|
|
||||||
|
|
||||||
fi
|
|
||||||
|
|
||||||
patch_drivers_network
|
|
||||||
|
|
||||||
# Exfat driver
|
|
||||||
|
|
||||||
if linux-version compare "${version}" ge 4.9 && linux-version compare "${version}" le 5.4; then
|
|
||||||
|
|
||||||
# attach to specifics tag or branch
|
|
||||||
display_alert "Adding" "exfat driver ${exfatsver}" "info"
|
|
||||||
|
|
||||||
local exfatsver="branch:master"
|
|
||||||
fetch_from_repo "$GITHUB_SOURCE/arter97/exfat-linux" "exfat" "${exfatsver}" "yes"
|
|
||||||
cd "$kerneldir" || exit
|
|
||||||
mkdir -p $kerneldir/fs/exfat/
|
|
||||||
cp -R "${SRC}/cache/sources/exfat/${exfatsver#*:}"/{*.c,*.h} \
|
|
||||||
$kerneldir/fs/exfat/
|
|
||||||
|
|
||||||
# Add to section Makefile
|
|
||||||
echo "obj-\$(CONFIG_EXFAT_FS) += exfat/" >> $kerneldir/fs/Makefile
|
|
||||||
|
|
||||||
# Makefile
|
|
||||||
cat <<- EOF > "$kerneldir/fs/exfat/Makefile"
|
|
||||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
#
|
|
||||||
# Makefile for the linux exFAT filesystem support.
|
|
||||||
#
|
|
||||||
obj-\$(CONFIG_EXFAT_FS) += exfat.o
|
|
||||||
exfat-y := inode.o namei.o dir.o super.o fatent.o cache.o nls.o misc.o file.o balloc.o xattr.o
|
|
||||||
EOF
|
|
||||||
|
|
||||||
# Kconfig
|
|
||||||
sed -i '$i\source "fs\/exfat\/Kconfig"' $kerneldir/fs/Kconfig
|
|
||||||
cp "${SRC}/cache/sources/exfat/${exfatsver#*:}/Kconfig" \
|
|
||||||
"$kerneldir/fs/exfat/Kconfig"
|
|
||||||
|
|
||||||
fi
|
|
||||||
|
|
||||||
if linux-version compare $version ge 4.4 && linux-version compare $version lt 5.8; then
|
|
||||||
display_alert "Adjusting" "Framebuffer driver for ST7789 IPS display" "info"
|
|
||||||
process_patch_file "${SRC}/patch/misc/fbtft-st7789v-invert-color.patch" "applying"
|
|
||||||
fi
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -478,15 +478,6 @@ set -o errexit ## set -e : exit the script if any statement returns a non-true
|
|||||||
# shellcheck source=lib/functions/compilation/patch/drivers_network.sh
|
# shellcheck source=lib/functions/compilation/patch/drivers_network.sh
|
||||||
source "${SRC}"/lib/functions/compilation/patch/drivers_network.sh
|
source "${SRC}"/lib/functions/compilation/patch/drivers_network.sh
|
||||||
|
|
||||||
# no errors tolerated. invoked before each sourced file to make sure.
|
|
||||||
#set -o pipefail # trace ERR through pipes - will be enabled "soon"
|
|
||||||
#set -o nounset ## set -u : exit the script if you try to use an uninitialised variable - one day will be enabled
|
|
||||||
set -o errtrace # trace ERR through - enabled
|
|
||||||
set -o errexit ## set -e : exit the script if any statement returns a non-true return value - enabled
|
|
||||||
### lib/functions/compilation/patch/kernel-drivers.sh
|
|
||||||
# shellcheck source=lib/functions/compilation/patch/kernel-drivers.sh
|
|
||||||
source "${SRC}"/lib/functions/compilation/patch/kernel-drivers.sh
|
|
||||||
|
|
||||||
# no errors tolerated. invoked before each sourced file to make sure.
|
# no errors tolerated. invoked before each sourced file to make sure.
|
||||||
#set -o pipefail # trace ERR through pipes - will be enabled "soon"
|
#set -o pipefail # trace ERR through pipes - will be enabled "soon"
|
||||||
#set -o nounset ## set -u : exit the script if you try to use an uninitialised variable - one day will be enabled
|
#set -o nounset ## set -u : exit the script if you try to use an uninitialised variable - one day will be enabled
|
||||||
|
|||||||
@@ -1,727 +0,0 @@
|
|||||||
diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
|
|
||||||
index 7f1f1fbcef9e..f3ff976266fe 100644
|
|
||||||
--- a/drivers/video/console/Kconfig
|
|
||||||
+++ b/drivers/video/console/Kconfig
|
|
||||||
@@ -151,6 +151,30 @@ config FRAMEBUFFER_CONSOLE_ROTATION
|
|
||||||
such that other users of the framebuffer will remain normally
|
|
||||||
oriented.
|
|
||||||
|
|
||||||
+config BOOTSPLASH
|
|
||||||
+ bool "Bootup splash screen"
|
|
||||||
+ depends on FRAMEBUFFER_CONSOLE
|
|
||||||
+ help
|
|
||||||
+ This option enables the Linux bootsplash screen.
|
|
||||||
+
|
|
||||||
+ The bootsplash is a full-screen logo or animation indicating a
|
|
||||||
+ booting system. It replaces the classic scrolling text with a
|
|
||||||
+ graphical alternative, similar to other systems.
|
|
||||||
+
|
|
||||||
+ Since this is technically implemented as a hook on top of fbcon,
|
|
||||||
+ it can only work if the FRAMEBUFFER_CONSOLE is enabled and a
|
|
||||||
+ framebuffer driver is active. Thus, to get a text-free boot,
|
|
||||||
+ the system needs to boot with vesafb, efifb, or similar.
|
|
||||||
+
|
|
||||||
+ Once built into the kernel, the bootsplash needs to be enabled
|
|
||||||
+ with bootsplash.enabled=1 and a splash file needs to be supplied.
|
|
||||||
+
|
|
||||||
+ Further documentation can be found in:
|
|
||||||
+ Documentation/fb/bootsplash.txt
|
|
||||||
+
|
|
||||||
+ If unsure, say N.
|
|
||||||
+ This is typically used by distributors and system integrators.
|
|
||||||
+
|
|
||||||
config STI_CONSOLE
|
|
||||||
bool "STI text console"
|
|
||||||
depends on PARISC
|
|
||||||
diff --git a/drivers/video/fbdev/core/Makefile b/drivers/video/fbdev/core/Makefile
|
|
||||||
index 73493bbd7a15..66895321928e 100644
|
|
||||||
--- a/drivers/video/fbdev/core/Makefile
|
|
||||||
+++ b/drivers/video/fbdev/core/Makefile
|
|
||||||
@@ -29,3 +29,6 @@ obj-$(CONFIG_FB_SYS_IMAGEBLIT) += sysimgblt.o
|
|
||||||
obj-$(CONFIG_FB_SYS_FOPS) += fb_sys_fops.o
|
|
||||||
obj-$(CONFIG_FB_SVGALIB) += svgalib.o
|
|
||||||
obj-$(CONFIG_FB_DDC) += fb_ddc.o
|
|
||||||
+
|
|
||||||
+obj-$(CONFIG_BOOTSPLASH) += bootsplash.o bootsplash_render.o \
|
|
||||||
+ dummyblit.o
|
|
||||||
diff --git a/drivers/video/fbdev/core/bootsplash.c b/drivers/video/fbdev/core/bootsplash.c
|
|
||||||
new file mode 100644
|
|
||||||
index 000000000000..e449755af268
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/drivers/video/fbdev/core/bootsplash.c
|
|
||||||
@@ -0,0 +1,294 @@
|
|
||||||
+/*
|
|
||||||
+ * Kernel based bootsplash.
|
|
||||||
+ *
|
|
||||||
+ * (Main file: Glue code, workers, timer, PM, kernel and userland API)
|
|
||||||
+ *
|
|
||||||
+ * Authors:
|
|
||||||
+ * Max Staudt <mstaudt@suse.de>
|
|
||||||
+ *
|
|
||||||
+ * SPDX-License-Identifier: GPL-2.0
|
|
||||||
+ */
|
|
||||||
+
|
|
||||||
+#define pr_fmt(fmt) "bootsplash: " fmt
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+#include <linux/atomic.h>
|
|
||||||
+#include <linux/bootsplash.h>
|
|
||||||
+#include <linux/console.h>
|
|
||||||
+#include <linux/device.h> /* dev_warn() */
|
|
||||||
+#include <linux/fb.h>
|
|
||||||
+#include <linux/fs.h>
|
|
||||||
+#include <linux/kernel.h>
|
|
||||||
+#include <linux/jiffies.h>
|
|
||||||
+#include <linux/module.h>
|
|
||||||
+#include <linux/mutex.h>
|
|
||||||
+#include <linux/platform_device.h>
|
|
||||||
+#include <linux/printk.h>
|
|
||||||
+#include <linux/selection.h> /* console_blanked */
|
|
||||||
+#include <linux/stringify.h>
|
|
||||||
+#include <linux/types.h>
|
|
||||||
+#include <linux/vmalloc.h>
|
|
||||||
+#include <linux/vt_kern.h>
|
|
||||||
+#include <linux/workqueue.h>
|
|
||||||
+
|
|
||||||
+#include "bootsplash_internal.h"
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+/*
|
|
||||||
+ * We only have one splash screen, so let's keep a single
|
|
||||||
+ * instance of the internal state.
|
|
||||||
+ */
|
|
||||||
+static struct splash_priv splash_state;
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+static void splash_callback_redraw_vc(struct work_struct *ignored)
|
|
||||||
+{
|
|
||||||
+ if (console_blanked)
|
|
||||||
+ return;
|
|
||||||
+
|
|
||||||
+ console_lock();
|
|
||||||
+ if (vc_cons[fg_console].d)
|
|
||||||
+ update_screen(vc_cons[fg_console].d);
|
|
||||||
+ console_unlock();
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+static bool is_fb_compatible(const struct fb_info *info)
|
|
||||||
+{
|
|
||||||
+ if (!(info->flags & FBINFO_BE_MATH)
|
|
||||||
+ != !fb_be_math((struct fb_info *)info)) {
|
|
||||||
+ dev_warn(info->device,
|
|
||||||
+ "Can't draw on foreign endianness framebuffer.\n");
|
|
||||||
+
|
|
||||||
+ return false;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (info->flags & FBINFO_MISC_TILEBLITTING) {
|
|
||||||
+ dev_warn(info->device,
|
|
||||||
+ "Can't draw splash on tiling framebuffer.\n");
|
|
||||||
+
|
|
||||||
+ return false;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (info->fix.type != FB_TYPE_PACKED_PIXELS
|
|
||||||
+ || (info->fix.visual != FB_VISUAL_TRUECOLOR
|
|
||||||
+ && info->fix.visual != FB_VISUAL_DIRECTCOLOR)) {
|
|
||||||
+ dev_warn(info->device,
|
|
||||||
+ "Can't draw splash on non-packed or non-truecolor framebuffer.\n");
|
|
||||||
+
|
|
||||||
+ dev_warn(info->device,
|
|
||||||
+ " type: %u visual: %u\n",
|
|
||||||
+ info->fix.type, info->fix.visual);
|
|
||||||
+
|
|
||||||
+ return false;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (info->var.bits_per_pixel != 16
|
|
||||||
+ && info->var.bits_per_pixel != 24
|
|
||||||
+ && info->var.bits_per_pixel != 32) {
|
|
||||||
+ dev_warn(info->device,
|
|
||||||
+ "We only support drawing on framebuffers with 16, 24, or 32 bpp, not %d.\n",
|
|
||||||
+ info->var.bits_per_pixel);
|
|
||||||
+
|
|
||||||
+ return false;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return true;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+/*
|
|
||||||
+ * Called by fbcon_switch() when an instance is activated or refreshed.
|
|
||||||
+ */
|
|
||||||
+void bootsplash_render_full(struct fb_info *info)
|
|
||||||
+{
|
|
||||||
+ if (!is_fb_compatible(info))
|
|
||||||
+ return;
|
|
||||||
+
|
|
||||||
+ bootsplash_do_render_background(info);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+/*
|
|
||||||
+ * External status enquiry and on/off switch
|
|
||||||
+ */
|
|
||||||
+bool bootsplash_would_render_now(void)
|
|
||||||
+{
|
|
||||||
+ return !oops_in_progress
|
|
||||||
+ && !console_blanked
|
|
||||||
+ && bootsplash_is_enabled();
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+bool bootsplash_is_enabled(void)
|
|
||||||
+{
|
|
||||||
+ bool was_enabled;
|
|
||||||
+
|
|
||||||
+ /* Make sure we have the newest state */
|
|
||||||
+ smp_rmb();
|
|
||||||
+
|
|
||||||
+ was_enabled = test_bit(0, &splash_state.enabled);
|
|
||||||
+
|
|
||||||
+ return was_enabled;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+void bootsplash_disable(void)
|
|
||||||
+{
|
|
||||||
+ int was_enabled;
|
|
||||||
+
|
|
||||||
+ was_enabled = test_and_clear_bit(0, &splash_state.enabled);
|
|
||||||
+
|
|
||||||
+ if (was_enabled) {
|
|
||||||
+ if (oops_in_progress) {
|
|
||||||
+ /* Redraw screen now so we can see a panic */
|
|
||||||
+ if (vc_cons[fg_console].d)
|
|
||||||
+ update_screen(vc_cons[fg_console].d);
|
|
||||||
+ } else {
|
|
||||||
+ /* No urgency, redraw at next opportunity */
|
|
||||||
+ schedule_work(&splash_state.work_redraw_vc);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+void bootsplash_enable(void)
|
|
||||||
+{
|
|
||||||
+ bool was_enabled;
|
|
||||||
+
|
|
||||||
+ if (oops_in_progress)
|
|
||||||
+ return;
|
|
||||||
+
|
|
||||||
+ was_enabled = test_and_set_bit(0, &splash_state.enabled);
|
|
||||||
+
|
|
||||||
+ if (!was_enabled)
|
|
||||||
+ schedule_work(&splash_state.work_redraw_vc);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+/*
|
|
||||||
+ * Userland API via platform device in sysfs
|
|
||||||
+ */
|
|
||||||
+static ssize_t splash_show_enabled(struct device *dev,
|
|
||||||
+ struct device_attribute *attr, char *buf)
|
|
||||||
+{
|
|
||||||
+ return sprintf(buf, "%d\n", bootsplash_is_enabled());
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static ssize_t splash_store_enabled(struct device *device,
|
|
||||||
+ struct device_attribute *attr,
|
|
||||||
+ const char *buf, size_t count)
|
|
||||||
+{
|
|
||||||
+ bool enable;
|
|
||||||
+ int err;
|
|
||||||
+
|
|
||||||
+ if (!buf || !count)
|
|
||||||
+ return -EFAULT;
|
|
||||||
+
|
|
||||||
+ err = kstrtobool(buf, &enable);
|
|
||||||
+ if (err)
|
|
||||||
+ return err;
|
|
||||||
+
|
|
||||||
+ if (enable)
|
|
||||||
+ bootsplash_enable();
|
|
||||||
+ else
|
|
||||||
+ bootsplash_disable();
|
|
||||||
+
|
|
||||||
+ return count;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static DEVICE_ATTR(enabled, 0644, splash_show_enabled, splash_store_enabled);
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+static struct attribute *splash_dev_attrs[] = {
|
|
||||||
+ &dev_attr_enabled.attr,
|
|
||||||
+ NULL
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+ATTRIBUTE_GROUPS(splash_dev);
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+/*
|
|
||||||
+ * Power management fixup via platform device
|
|
||||||
+ *
|
|
||||||
+ * When the system is woken from sleep or restored after hibernating, we
|
|
||||||
+ * cannot expect the screen contents to still be present in video RAM.
|
|
||||||
+ * Thus, we have to redraw the splash if we're currently active.
|
|
||||||
+ */
|
|
||||||
+static int splash_resume(struct device *device)
|
|
||||||
+{
|
|
||||||
+ if (bootsplash_would_render_now())
|
|
||||||
+ schedule_work(&splash_state.work_redraw_vc);
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int splash_suspend(struct device *device)
|
|
||||||
+{
|
|
||||||
+ cancel_work_sync(&splash_state.work_redraw_vc);
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+static const struct dev_pm_ops splash_pm_ops = {
|
|
||||||
+ .thaw = splash_resume,
|
|
||||||
+ .restore = splash_resume,
|
|
||||||
+ .resume = splash_resume,
|
|
||||||
+ .suspend = splash_suspend,
|
|
||||||
+ .freeze = splash_suspend,
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+static struct platform_driver splash_driver = {
|
|
||||||
+ .driver = {
|
|
||||||
+ .name = "bootsplash",
|
|
||||||
+ .pm = &splash_pm_ops,
|
|
||||||
+ },
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+/*
|
|
||||||
+ * Main init
|
|
||||||
+ */
|
|
||||||
+void bootsplash_init(void)
|
|
||||||
+{
|
|
||||||
+ int ret;
|
|
||||||
+
|
|
||||||
+ /* Initialized already? */
|
|
||||||
+ if (splash_state.splash_device)
|
|
||||||
+ return;
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+ /* Register platform device to export user API */
|
|
||||||
+ ret = platform_driver_register(&splash_driver);
|
|
||||||
+ if (ret) {
|
|
||||||
+ pr_err("platform_driver_register() failed: %d\n", ret);
|
|
||||||
+ goto err;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ splash_state.splash_device
|
|
||||||
+ = platform_device_alloc("bootsplash", 0);
|
|
||||||
+
|
|
||||||
+ if (!splash_state.splash_device)
|
|
||||||
+ goto err_driver;
|
|
||||||
+
|
|
||||||
+ splash_state.splash_device->dev.groups = splash_dev_groups;
|
|
||||||
+
|
|
||||||
+ ret = platform_device_add(splash_state.splash_device);
|
|
||||||
+ if (ret) {
|
|
||||||
+ pr_err("platform_device_add() failed: %d\n", ret);
|
|
||||||
+ goto err_device;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+ INIT_WORK(&splash_state.work_redraw_vc, splash_callback_redraw_vc);
|
|
||||||
+
|
|
||||||
+ return;
|
|
||||||
+
|
|
||||||
+err_device:
|
|
||||||
+ platform_device_put(splash_state.splash_device);
|
|
||||||
+ splash_state.splash_device = NULL;
|
|
||||||
+err_driver:
|
|
||||||
+ platform_driver_unregister(&splash_driver);
|
|
||||||
+err:
|
|
||||||
+ pr_err("Failed to initialize.\n");
|
|
||||||
+}
|
|
||||||
diff --git a/drivers/video/fbdev/core/bootsplash_internal.h b/drivers/video/fbdev/core/bootsplash_internal.h
|
|
||||||
new file mode 100644
|
|
||||||
index 000000000000..b11da5cb90bf
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/drivers/video/fbdev/core/bootsplash_internal.h
|
|
||||||
@@ -0,0 +1,55 @@
|
|
||||||
+/*
|
|
||||||
+ * Kernel based bootsplash.
|
|
||||||
+ *
|
|
||||||
+ * (Internal data structures used at runtime)
|
|
||||||
+ *
|
|
||||||
+ * Authors:
|
|
||||||
+ * Max Staudt <mstaudt@suse.de>
|
|
||||||
+ *
|
|
||||||
+ * SPDX-License-Identifier: GPL-2.0
|
|
||||||
+ */
|
|
||||||
+
|
|
||||||
+#ifndef __BOOTSPLASH_INTERNAL_H
|
|
||||||
+#define __BOOTSPLASH_INTERNAL_H
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+#include <linux/types.h>
|
|
||||||
+#include <linux/fb.h>
|
|
||||||
+#include <linux/kernel.h>
|
|
||||||
+#include <linux/mutex.h>
|
|
||||||
+#include <linux/spinlock.h>
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+/*
|
|
||||||
+ * Runtime types
|
|
||||||
+ */
|
|
||||||
+struct splash_priv {
|
|
||||||
+ /*
|
|
||||||
+ * Enabled/disabled state, to be used with atomic bit operations.
|
|
||||||
+ * Bit 0: 0 = Splash hidden
|
|
||||||
+ * 1 = Splash shown
|
|
||||||
+ *
|
|
||||||
+ * Note: fbcon.c uses this twice, by calling
|
|
||||||
+ * bootsplash_would_render_now() in set_blitting_type() and
|
|
||||||
+ * in fbcon_switch().
|
|
||||||
+ * This is racy, but eventually consistent: Turning the
|
|
||||||
+ * splash on/off will cause a redraw, which calls
|
|
||||||
+ * fbcon_switch(), which calls set_blitting_type().
|
|
||||||
+ * So the last on/off toggle will make things consistent.
|
|
||||||
+ */
|
|
||||||
+ unsigned long enabled;
|
|
||||||
+
|
|
||||||
+ /* Our gateway to userland via sysfs */
|
|
||||||
+ struct platform_device *splash_device;
|
|
||||||
+
|
|
||||||
+ struct work_struct work_redraw_vc;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+/*
|
|
||||||
+ * Rendering functions
|
|
||||||
+ */
|
|
||||||
+void bootsplash_do_render_background(struct fb_info *info);
|
|
||||||
+
|
|
||||||
+#endif
|
|
||||||
diff --git a/drivers/video/fbdev/core/bootsplash_render.c b/drivers/video/fbdev/core/bootsplash_render.c
|
|
||||||
new file mode 100644
|
|
||||||
index 000000000000..4d7e0117f653
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/drivers/video/fbdev/core/bootsplash_render.c
|
|
||||||
@@ -0,0 +1,93 @@
|
|
||||||
+/*
|
|
||||||
+ * Kernel based bootsplash.
|
|
||||||
+ *
|
|
||||||
+ * (Rendering functions)
|
|
||||||
+ *
|
|
||||||
+ * Authors:
|
|
||||||
+ * Max Staudt <mstaudt@suse.de>
|
|
||||||
+ *
|
|
||||||
+ * SPDX-License-Identifier: GPL-2.0
|
|
||||||
+ */
|
|
||||||
+
|
|
||||||
+#define pr_fmt(fmt) "bootsplash: " fmt
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+#include <linux/bootsplash.h>
|
|
||||||
+#include <linux/fb.h>
|
|
||||||
+#include <linux/kernel.h>
|
|
||||||
+#include <linux/printk.h>
|
|
||||||
+#include <linux/types.h>
|
|
||||||
+
|
|
||||||
+#include "bootsplash_internal.h"
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+/*
|
|
||||||
+ * Rendering: Internal drawing routines
|
|
||||||
+ */
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+/*
|
|
||||||
+ * Pack pixel into target format and do Big/Little Endian handling.
|
|
||||||
+ * This would be a good place to handle endianness conversion if necessary.
|
|
||||||
+ */
|
|
||||||
+static inline u32 pack_pixel(const struct fb_var_screeninfo *dst_var,
|
|
||||||
+ u8 red, u8 green, u8 blue)
|
|
||||||
+{
|
|
||||||
+ u32 dstpix;
|
|
||||||
+
|
|
||||||
+ /* Quantize pixel */
|
|
||||||
+ red = red >> (8 - dst_var->red.length);
|
|
||||||
+ green = green >> (8 - dst_var->green.length);
|
|
||||||
+ blue = blue >> (8 - dst_var->blue.length);
|
|
||||||
+
|
|
||||||
+ /* Pack pixel */
|
|
||||||
+ dstpix = red << (dst_var->red.offset)
|
|
||||||
+ | green << (dst_var->green.offset)
|
|
||||||
+ | blue << (dst_var->blue.offset);
|
|
||||||
+
|
|
||||||
+ /*
|
|
||||||
+ * Move packed pixel to the beginning of the memory cell,
|
|
||||||
+ * so we can memcpy() it out easily
|
|
||||||
+ */
|
|
||||||
+#ifdef __BIG_ENDIAN
|
|
||||||
+ switch (dst_var->bits_per_pixel) {
|
|
||||||
+ case 16:
|
|
||||||
+ dstpix <<= 16;
|
|
||||||
+ break;
|
|
||||||
+ case 24:
|
|
||||||
+ dstpix <<= 8;
|
|
||||||
+ break;
|
|
||||||
+ case 32:
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
+#else
|
|
||||||
+ /* This is intrinsically unnecessary on Little Endian */
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
+ return dstpix;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+void bootsplash_do_render_background(struct fb_info *info)
|
|
||||||
+{
|
|
||||||
+ unsigned int x, y;
|
|
||||||
+ u32 dstpix;
|
|
||||||
+ u32 dst_octpp = info->var.bits_per_pixel / 8;
|
|
||||||
+
|
|
||||||
+ dstpix = pack_pixel(&info->var,
|
|
||||||
+ 0,
|
|
||||||
+ 0,
|
|
||||||
+ 0);
|
|
||||||
+
|
|
||||||
+ for (y = 0; y < info->var.yres_virtual; y++) {
|
|
||||||
+ u8 *dstline = info->screen_buffer + (y * info->fix.line_length);
|
|
||||||
+
|
|
||||||
+ for (x = 0; x < info->var.xres_virtual; x++) {
|
|
||||||
+ memcpy(dstline, &dstpix, dst_octpp);
|
|
||||||
+
|
|
||||||
+ dstline += dst_octpp;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
diff --git a/drivers/video/fbdev/core/dummyblit.c b/drivers/video/fbdev/core/dummyblit.c
|
|
||||||
new file mode 100644
|
|
||||||
index 000000000000..8c22ff92ce24
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/drivers/video/fbdev/core/dummyblit.c
|
|
||||||
@@ -0,0 +1,89 @@
|
|
||||||
+/*
|
|
||||||
+ * linux/drivers/video/fbdev/core/dummyblit.c -- Dummy Blitting Operation
|
|
||||||
+ *
|
|
||||||
+ * Authors:
|
|
||||||
+ * Max Staudt <mstaudt@suse.de>
|
|
||||||
+ *
|
|
||||||
+ * These functions are used in place of blitblit/tileblit to suppress
|
|
||||||
+ * fbcon's text output while a splash is shown.
|
|
||||||
+ *
|
|
||||||
+ * Only suppressing actual rendering keeps the text buffer in the VC layer
|
|
||||||
+ * intact and makes it easy to switch back from the bootsplash to a full
|
|
||||||
+ * text console with a simple redraw (with the original functions in place).
|
|
||||||
+ *
|
|
||||||
+ * Based on linux/drivers/video/fbdev/core/bitblit.c
|
|
||||||
+ * and linux/drivers/video/fbdev/core/tileblit.c
|
|
||||||
+ *
|
|
||||||
+ * SPDX-License-Identifier: GPL-2.0
|
|
||||||
+ */
|
|
||||||
+
|
|
||||||
+#include <linux/module.h>
|
|
||||||
+#include <linux/fb.h>
|
|
||||||
+#include <linux/vt_kern.h>
|
|
||||||
+#include <linux/console.h>
|
|
||||||
+#include <asm/types.h>
|
|
||||||
+#include "fbcon.h"
|
|
||||||
+
|
|
||||||
+static void dummy_bmove(struct vc_data *vc, struct fb_info *info, int sy,
|
|
||||||
+ int sx, int dy, int dx, int height, int width)
|
|
||||||
+{
|
|
||||||
+ ;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void dummy_clear(struct vc_data *vc, struct fb_info *info, int sy,
|
|
||||||
+ int sx, int height, int width)
|
|
||||||
+{
|
|
||||||
+ ;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void dummy_putcs(struct vc_data *vc, struct fb_info *info,
|
|
||||||
+ const unsigned short *s, int count, int yy, int xx,
|
|
||||||
+ int fg, int bg)
|
|
||||||
+{
|
|
||||||
+ ;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void dummy_clear_margins(struct vc_data *vc, struct fb_info *info,
|
|
||||||
+ int color, int bottom_only)
|
|
||||||
+{
|
|
||||||
+ ;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void dummy_cursor(struct vc_data *vc, struct fb_info *info, int mode,
|
|
||||||
+ int softback_lines, int fg, int bg)
|
|
||||||
+{
|
|
||||||
+ ;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int dummy_update_start(struct fb_info *info)
|
|
||||||
+{
|
|
||||||
+ /*
|
|
||||||
+ * Copied from bitblit.c and tileblit.c
|
|
||||||
+ *
|
|
||||||
+ * As of Linux 4.12, nobody seems to care about our return value.
|
|
||||||
+ */
|
|
||||||
+ struct fbcon_ops *ops = info->fbcon_par;
|
|
||||||
+ int err;
|
|
||||||
+
|
|
||||||
+ err = fb_pan_display(info, &ops->var);
|
|
||||||
+ ops->var.xoffset = info->var.xoffset;
|
|
||||||
+ ops->var.yoffset = info->var.yoffset;
|
|
||||||
+ ops->var.vmode = info->var.vmode;
|
|
||||||
+ return err;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+void fbcon_set_dummyops(struct fbcon_ops *ops)
|
|
||||||
+{
|
|
||||||
+ ops->bmove = dummy_bmove;
|
|
||||||
+ ops->clear = dummy_clear;
|
|
||||||
+ ops->putcs = dummy_putcs;
|
|
||||||
+ ops->clear_margins = dummy_clear_margins;
|
|
||||||
+ ops->cursor = dummy_cursor;
|
|
||||||
+ ops->update_start = dummy_update_start;
|
|
||||||
+ ops->rotate_font = NULL;
|
|
||||||
+}
|
|
||||||
+EXPORT_SYMBOL_GPL(fbcon_set_dummyops);
|
|
||||||
+
|
|
||||||
+MODULE_AUTHOR("Max Staudt <mstaudt@suse.de>");
|
|
||||||
+MODULE_DESCRIPTION("Dummy Blitting Operation");
|
|
||||||
+MODULE_LICENSE("GPL");
|
|
||||||
diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
|
|
||||||
index 04612f938bab..9a39a6fcfe98 100644
|
|
||||||
--- a/drivers/video/fbdev/core/fbcon.c
|
|
||||||
+++ b/drivers/video/fbdev/core/fbcon.c
|
|
||||||
@@ -80,6 +80,7 @@
|
|
||||||
#include <asm/irq.h>
|
|
||||||
|
|
||||||
#include "fbcon.h"
|
|
||||||
+#include <linux/bootsplash.h>
|
|
||||||
|
|
||||||
#ifdef FBCONDEBUG
|
|
||||||
# define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __func__ , ## args)
|
|
||||||
@@ -542,6 +543,8 @@ static int do_fbcon_takeover(int show_logo)
|
|
||||||
for (i = first_fb_vc; i <= last_fb_vc; i++)
|
|
||||||
con2fb_map[i] = info_idx;
|
|
||||||
|
|
||||||
+ bootsplash_init();
|
|
||||||
+
|
|
||||||
err = do_take_over_console(&fb_con, first_fb_vc, last_fb_vc,
|
|
||||||
fbcon_is_default);
|
|
||||||
|
|
||||||
@@ -661,6 +664,9 @@ static void set_blitting_type(struct vc_data *vc, struct fb_info *info)
|
|
||||||
else {
|
|
||||||
fbcon_set_rotation(info);
|
|
||||||
fbcon_set_bitops(ops);
|
|
||||||
+
|
|
||||||
+ if (bootsplash_would_render_now())
|
|
||||||
+ fbcon_set_dummyops(ops);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -683,6 +689,19 @@ static void set_blitting_type(struct vc_data *vc, struct fb_info *info)
|
|
||||||
ops->p = &fb_display[vc->vc_num];
|
|
||||||
fbcon_set_rotation(info);
|
|
||||||
fbcon_set_bitops(ops);
|
|
||||||
+
|
|
||||||
+ /*
|
|
||||||
+ * Note:
|
|
||||||
+ * This is *eventually correct*.
|
|
||||||
+ * Setting the fbcon operations and drawing the splash happen at
|
|
||||||
+ * different points in time. If the splash is enabled/disabled
|
|
||||||
+ * in between, then bootsplash_{en,dis}able will schedule a
|
|
||||||
+ * redraw, which will again render the splash (or not) and set
|
|
||||||
+ * the correct fbcon ops.
|
|
||||||
+ * The last run will then be the right one.
|
|
||||||
+ */
|
|
||||||
+ if (bootsplash_would_render_now())
|
|
||||||
+ fbcon_set_dummyops(ops);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int fbcon_invalid_charcount(struct fb_info *info, unsigned charcount)
|
|
||||||
@@ -2184,6 +2203,9 @@ static int fbcon_switch(struct vc_data *vc)
|
|
||||||
info = registered_fb[con2fb_map[vc->vc_num]];
|
|
||||||
ops = info->fbcon_par;
|
|
||||||
|
|
||||||
+ if (bootsplash_would_render_now())
|
|
||||||
+ bootsplash_render_full(info);
|
|
||||||
+
|
|
||||||
if (softback_top) {
|
|
||||||
if (softback_lines)
|
|
||||||
fbcon_set_origin(vc);
|
|
||||||
diff --git a/drivers/video/fbdev/core/fbcon.h b/drivers/video/fbdev/core/fbcon.h
|
|
||||||
index 18f3ac144237..45f94347fe5e 100644
|
|
||||||
--- a/drivers/video/fbdev/core/fbcon.h
|
|
||||||
+++ b/drivers/video/fbdev/core/fbcon.h
|
|
||||||
@@ -214,6 +214,11 @@ static inline int attr_col_ec(int shift, struct vc_data *vc,
|
|
||||||
#define SCROLL_REDRAW 0x004
|
|
||||||
#define SCROLL_PAN_REDRAW 0x005
|
|
||||||
|
|
||||||
+#ifdef CONFIG_BOOTSPLASH
|
|
||||||
+extern void fbcon_set_dummyops(struct fbcon_ops *ops);
|
|
||||||
+#else /* CONFIG_BOOTSPLASH */
|
|
||||||
+#define fbcon_set_dummyops(x)
|
|
||||||
+#endif /* CONFIG_BOOTSPLASH */
|
|
||||||
#ifdef CONFIG_FB_TILEBLITTING
|
|
||||||
extern void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info);
|
|
||||||
#endif
|
|
||||||
diff --git a/include/linux/bootsplash.h b/include/linux/bootsplash.h
|
|
||||||
new file mode 100644
|
|
||||||
index 000000000000..c6dd0b43180d
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/include/linux/bootsplash.h
|
|
||||||
@@ -0,0 +1,43 @@
|
|
||||||
+/*
|
|
||||||
+ * Kernel based bootsplash.
|
|
||||||
+ *
|
|
||||||
+ * Authors:
|
|
||||||
+ * Max Staudt <mstaudt@suse.de>
|
|
||||||
+ *
|
|
||||||
+ * SPDX-License-Identifier: GPL-2.0
|
|
||||||
+ */
|
|
||||||
+
|
|
||||||
+#ifndef __LINUX_BOOTSPLASH_H
|
|
||||||
+#define __LINUX_BOOTSPLASH_H
|
|
||||||
+
|
|
||||||
+#include <linux/fb.h>
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+#ifdef CONFIG_BOOTSPLASH
|
|
||||||
+
|
|
||||||
+extern void bootsplash_render_full(struct fb_info *info);
|
|
||||||
+
|
|
||||||
+extern bool bootsplash_would_render_now(void);
|
|
||||||
+
|
|
||||||
+extern bool bootsplash_is_enabled(void);
|
|
||||||
+extern void bootsplash_disable(void);
|
|
||||||
+extern void bootsplash_enable(void);
|
|
||||||
+
|
|
||||||
+extern void bootsplash_init(void);
|
|
||||||
+
|
|
||||||
+#else /* CONFIG_BOOTSPLASH */
|
|
||||||
+
|
|
||||||
+#define bootsplash_render_full(x)
|
|
||||||
+
|
|
||||||
+#define bootsplash_would_render_now() (false)
|
|
||||||
+
|
|
||||||
+#define bootsplash_is_enabled() (false)
|
|
||||||
+#define bootsplash_disable()
|
|
||||||
+#define bootsplash_enable()
|
|
||||||
+
|
|
||||||
+#define bootsplash_init()
|
|
||||||
+
|
|
||||||
+#endif /* CONFIG_BOOTSPLASH */
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+#endif
|
|
||||||
@@ -1,657 +0,0 @@
|
|||||||
diff --git a/drivers/video/fbdev/core/Makefile b/drivers/video/fbdev/core/Makefile
|
|
||||||
index 66895321928e..6a8d1bab8a01 100644
|
|
||||||
--- a/drivers/video/fbdev/core/Makefile
|
|
||||||
+++ b/drivers/video/fbdev/core/Makefile
|
|
||||||
@@ -31,4 +31,4 @@ obj-$(CONFIG_FB_SVGALIB) += svgalib.o
|
|
||||||
obj-$(CONFIG_FB_DDC) += fb_ddc.o
|
|
||||||
|
|
||||||
obj-$(CONFIG_BOOTSPLASH) += bootsplash.o bootsplash_render.o \
|
|
||||||
- dummyblit.o
|
|
||||||
+ bootsplash_load.o dummyblit.o
|
|
||||||
diff --git a/drivers/video/fbdev/core/bootsplash.c b/drivers/video/fbdev/core/bootsplash.c
|
|
||||||
index e449755af268..843c5400fefc 100644
|
|
||||||
--- a/drivers/video/fbdev/core/bootsplash.c
|
|
||||||
+++ b/drivers/video/fbdev/core/bootsplash.c
|
|
||||||
@@ -32,6 +32,7 @@
|
|
||||||
#include <linux/workqueue.h>
|
|
||||||
|
|
||||||
#include "bootsplash_internal.h"
|
|
||||||
+#include "uapi/linux/bootsplash_file.h"
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
@@ -102,10 +103,17 @@ static bool is_fb_compatible(const struct fb_info *info)
|
|
||||||
*/
|
|
||||||
void bootsplash_render_full(struct fb_info *info)
|
|
||||||
{
|
|
||||||
+ mutex_lock(&splash_state.data_lock);
|
|
||||||
+
|
|
||||||
if (!is_fb_compatible(info))
|
|
||||||
- return;
|
|
||||||
+ goto out;
|
|
||||||
+
|
|
||||||
+ bootsplash_do_render_background(info, splash_state.file);
|
|
||||||
+
|
|
||||||
+ bootsplash_do_render_pictures(info, splash_state.file);
|
|
||||||
|
|
||||||
- bootsplash_do_render_background(info);
|
|
||||||
+out:
|
|
||||||
+ mutex_unlock(&splash_state.data_lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@@ -116,6 +124,7 @@ bool bootsplash_would_render_now(void)
|
|
||||||
{
|
|
||||||
return !oops_in_progress
|
|
||||||
&& !console_blanked
|
|
||||||
+ && splash_state.file
|
|
||||||
&& bootsplash_is_enabled();
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -252,6 +261,7 @@ static struct platform_driver splash_driver = {
|
|
||||||
void bootsplash_init(void)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
+ struct splash_file_priv *fp;
|
|
||||||
|
|
||||||
/* Initialized already? */
|
|
||||||
if (splash_state.splash_device)
|
|
||||||
@@ -280,8 +290,26 @@ void bootsplash_init(void)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
+ mutex_init(&splash_state.data_lock);
|
|
||||||
+ set_bit(0, &splash_state.enabled);
|
|
||||||
+
|
|
||||||
INIT_WORK(&splash_state.work_redraw_vc, splash_callback_redraw_vc);
|
|
||||||
|
|
||||||
+
|
|
||||||
+ if (!splash_state.bootfile || !strlen(splash_state.bootfile))
|
|
||||||
+ return;
|
|
||||||
+
|
|
||||||
+ fp = bootsplash_load_firmware(&splash_state.splash_device->dev,
|
|
||||||
+ splash_state.bootfile);
|
|
||||||
+
|
|
||||||
+ if (!fp)
|
|
||||||
+ goto err;
|
|
||||||
+
|
|
||||||
+ mutex_lock(&splash_state.data_lock);
|
|
||||||
+ splash_state.splash_fb = NULL;
|
|
||||||
+ splash_state.file = fp;
|
|
||||||
+ mutex_unlock(&splash_state.data_lock);
|
|
||||||
+
|
|
||||||
return;
|
|
||||||
|
|
||||||
err_device:
|
|
||||||
@@ -292,3 +320,7 @@ void bootsplash_init(void)
|
|
||||||
err:
|
|
||||||
pr_err("Failed to initialize.\n");
|
|
||||||
}
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+module_param_named(bootfile, splash_state.bootfile, charp, 0444);
|
|
||||||
+MODULE_PARM_DESC(bootfile, "Bootsplash file to load on boot");
|
|
||||||
diff --git a/drivers/video/fbdev/core/bootsplash_internal.h b/drivers/video/fbdev/core/bootsplash_internal.h
|
|
||||||
index b11da5cb90bf..71e2a27ac0b8 100644
|
|
||||||
--- a/drivers/video/fbdev/core/bootsplash_internal.h
|
|
||||||
+++ b/drivers/video/fbdev/core/bootsplash_internal.h
|
|
||||||
@@ -15,15 +15,43 @@
|
|
||||||
|
|
||||||
#include <linux/types.h>
|
|
||||||
#include <linux/fb.h>
|
|
||||||
+#include <linux/firmware.h>
|
|
||||||
#include <linux/kernel.h>
|
|
||||||
#include <linux/mutex.h>
|
|
||||||
#include <linux/spinlock.h>
|
|
||||||
|
|
||||||
+#include "uapi/linux/bootsplash_file.h"
|
|
||||||
+
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Runtime types
|
|
||||||
*/
|
|
||||||
+struct splash_blob_priv {
|
|
||||||
+ struct splash_blob_header *blob_header;
|
|
||||||
+ const void *data;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+struct splash_pic_priv {
|
|
||||||
+ const struct splash_pic_header *pic_header;
|
|
||||||
+
|
|
||||||
+ struct splash_blob_priv *blobs;
|
|
||||||
+ u16 blobs_loaded;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+struct splash_file_priv {
|
|
||||||
+ const struct firmware *fw;
|
|
||||||
+ const struct splash_file_header *header;
|
|
||||||
+
|
|
||||||
+ struct splash_pic_priv *pics;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+
|
|
||||||
struct splash_priv {
|
|
||||||
+ /* Bootup and runtime state */
|
|
||||||
+ char *bootfile;
|
|
||||||
+
|
|
||||||
/*
|
|
||||||
* Enabled/disabled state, to be used with atomic bit operations.
|
|
||||||
* Bit 0: 0 = Splash hidden
|
|
||||||
@@ -43,6 +71,13 @@ struct splash_priv {
|
|
||||||
struct platform_device *splash_device;
|
|
||||||
|
|
||||||
struct work_struct work_redraw_vc;
|
|
||||||
+
|
|
||||||
+ /* Splash data structures including lock for everything below */
|
|
||||||
+ struct mutex data_lock;
|
|
||||||
+
|
|
||||||
+ struct fb_info *splash_fb;
|
|
||||||
+
|
|
||||||
+ struct splash_file_priv *file;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
@@ -50,6 +85,14 @@ struct splash_priv {
|
|
||||||
/*
|
|
||||||
* Rendering functions
|
|
||||||
*/
|
|
||||||
-void bootsplash_do_render_background(struct fb_info *info);
|
|
||||||
+void bootsplash_do_render_background(struct fb_info *info,
|
|
||||||
+ const struct splash_file_priv *fp);
|
|
||||||
+void bootsplash_do_render_pictures(struct fb_info *info,
|
|
||||||
+ const struct splash_file_priv *fp);
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+void bootsplash_free_file(struct splash_file_priv *fp);
|
|
||||||
+struct splash_file_priv *bootsplash_load_firmware(struct device *device,
|
|
||||||
+ const char *path);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
diff --git a/drivers/video/fbdev/core/bootsplash_load.c b/drivers/video/fbdev/core/bootsplash_load.c
|
|
||||||
new file mode 100644
|
|
||||||
index 000000000000..fd807571ab7d
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/drivers/video/fbdev/core/bootsplash_load.c
|
|
||||||
@@ -0,0 +1,225 @@
|
|
||||||
+/*
|
|
||||||
+ * Kernel based bootsplash.
|
|
||||||
+ *
|
|
||||||
+ * (Loading and freeing functions)
|
|
||||||
+ *
|
|
||||||
+ * Authors:
|
|
||||||
+ * Max Staudt <mstaudt@suse.de>
|
|
||||||
+ *
|
|
||||||
+ * SPDX-License-Identifier: GPL-2.0
|
|
||||||
+ */
|
|
||||||
+
|
|
||||||
+#define pr_fmt(fmt) "bootsplash: " fmt
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+#include <linux/bootsplash.h>
|
|
||||||
+#include <linux/fb.h>
|
|
||||||
+#include <linux/firmware.h>
|
|
||||||
+#include <linux/kernel.h>
|
|
||||||
+#include <linux/mutex.h>
|
|
||||||
+#include <linux/printk.h>
|
|
||||||
+#include <linux/types.h>
|
|
||||||
+#include <linux/vmalloc.h>
|
|
||||||
+
|
|
||||||
+#include "bootsplash_internal.h"
|
|
||||||
+#include "uapi/linux/bootsplash_file.h"
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+/*
|
|
||||||
+ * Free all vmalloc()'d resources describing a splash file.
|
|
||||||
+ */
|
|
||||||
+void bootsplash_free_file(struct splash_file_priv *fp)
|
|
||||||
+{
|
|
||||||
+ if (!fp)
|
|
||||||
+ return;
|
|
||||||
+
|
|
||||||
+ if (fp->pics) {
|
|
||||||
+ unsigned int i;
|
|
||||||
+
|
|
||||||
+ for (i = 0; i < fp->header->num_pics; i++) {
|
|
||||||
+ struct splash_pic_priv *pp = &fp->pics[i];
|
|
||||||
+
|
|
||||||
+ if (pp->blobs)
|
|
||||||
+ vfree(pp->blobs);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ vfree(fp->pics);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ release_firmware(fp->fw);
|
|
||||||
+ vfree(fp);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+/*
|
|
||||||
+ * Load a splash screen from a "firmware" file.
|
|
||||||
+ *
|
|
||||||
+ * Parsing, and sanity checks.
|
|
||||||
+ */
|
|
||||||
+#ifdef __BIG_ENDIAN
|
|
||||||
+ #define BOOTSPLASH_MAGIC BOOTSPLASH_MAGIC_BE
|
|
||||||
+#else
|
|
||||||
+ #define BOOTSPLASH_MAGIC BOOTSPLASH_MAGIC_LE
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
+struct splash_file_priv *bootsplash_load_firmware(struct device *device,
|
|
||||||
+ const char *path)
|
|
||||||
+{
|
|
||||||
+ const struct firmware *fw;
|
|
||||||
+ struct splash_file_priv *fp;
|
|
||||||
+ unsigned int i;
|
|
||||||
+ const u8 *walker;
|
|
||||||
+
|
|
||||||
+ if (request_firmware(&fw, path, device))
|
|
||||||
+ return NULL;
|
|
||||||
+
|
|
||||||
+ if (fw->size < sizeof(struct splash_file_header)
|
|
||||||
+ || memcmp(fw->data, BOOTSPLASH_MAGIC, sizeof(fp->header->id))) {
|
|
||||||
+ pr_err("Not a bootsplash file.\n");
|
|
||||||
+
|
|
||||||
+ release_firmware(fw);
|
|
||||||
+ return NULL;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ fp = vzalloc(sizeof(struct splash_file_priv));
|
|
||||||
+ if (!fp) {
|
|
||||||
+ release_firmware(fw);
|
|
||||||
+ return NULL;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ pr_info("Loading splash file (%li bytes)\n", fw->size);
|
|
||||||
+
|
|
||||||
+ fp->fw = fw;
|
|
||||||
+ fp->header = (struct splash_file_header *)fw->data;
|
|
||||||
+
|
|
||||||
+ /* Sanity checks */
|
|
||||||
+ if (fp->header->version != BOOTSPLASH_VERSION) {
|
|
||||||
+ pr_err("Loaded v%d file, but we only support version %d\n",
|
|
||||||
+ fp->header->version,
|
|
||||||
+ BOOTSPLASH_VERSION);
|
|
||||||
+
|
|
||||||
+ goto err;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (fw->size < sizeof(struct splash_file_header)
|
|
||||||
+ + fp->header->num_pics
|
|
||||||
+ * sizeof(struct splash_pic_header)
|
|
||||||
+ + fp->header->num_blobs
|
|
||||||
+ * sizeof(struct splash_blob_header)) {
|
|
||||||
+ pr_err("File incomplete.\n");
|
|
||||||
+
|
|
||||||
+ goto err;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ /* Read picture headers */
|
|
||||||
+ if (fp->header->num_pics) {
|
|
||||||
+ fp->pics = vzalloc(fp->header->num_pics
|
|
||||||
+ * sizeof(struct splash_pic_priv));
|
|
||||||
+ if (!fp->pics)
|
|
||||||
+ goto err;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ walker = fw->data + sizeof(struct splash_file_header);
|
|
||||||
+ for (i = 0; i < fp->header->num_pics; i++) {
|
|
||||||
+ struct splash_pic_priv *pp = &fp->pics[i];
|
|
||||||
+ struct splash_pic_header *ph = (void *)walker;
|
|
||||||
+
|
|
||||||
+ pr_debug("Picture %u: Size %ux%u\n", i, ph->width, ph->height);
|
|
||||||
+
|
|
||||||
+ if (ph->num_blobs < 1) {
|
|
||||||
+ pr_err("Picture %u: Zero blobs? Aborting load.\n", i);
|
|
||||||
+ goto err;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ pp->pic_header = ph;
|
|
||||||
+ pp->blobs = vzalloc(ph->num_blobs
|
|
||||||
+ * sizeof(struct splash_blob_priv));
|
|
||||||
+ if (!pp->blobs)
|
|
||||||
+ goto err;
|
|
||||||
+
|
|
||||||
+ walker += sizeof(struct splash_pic_header);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ /* Read blob headers */
|
|
||||||
+ for (i = 0; i < fp->header->num_blobs; i++) {
|
|
||||||
+ struct splash_blob_header *bh = (void *)walker;
|
|
||||||
+ struct splash_pic_priv *pp;
|
|
||||||
+
|
|
||||||
+ if (walker + sizeof(struct splash_blob_header)
|
|
||||||
+ > fw->data + fw->size)
|
|
||||||
+ goto err;
|
|
||||||
+
|
|
||||||
+ walker += sizeof(struct splash_blob_header);
|
|
||||||
+
|
|
||||||
+ if (walker + bh->length > fw->data + fw->size)
|
|
||||||
+ goto err;
|
|
||||||
+
|
|
||||||
+ if (bh->picture_id >= fp->header->num_pics)
|
|
||||||
+ goto nextblob;
|
|
||||||
+
|
|
||||||
+ pp = &fp->pics[bh->picture_id];
|
|
||||||
+
|
|
||||||
+ pr_debug("Blob %u, pic %u, blobs_loaded %u, num_blobs %u.\n",
|
|
||||||
+ i, bh->picture_id,
|
|
||||||
+ pp->blobs_loaded, pp->pic_header->num_blobs);
|
|
||||||
+
|
|
||||||
+ if (pp->blobs_loaded >= pp->pic_header->num_blobs)
|
|
||||||
+ goto nextblob;
|
|
||||||
+
|
|
||||||
+ switch (bh->type) {
|
|
||||||
+ case 0:
|
|
||||||
+ /* Raw 24-bit packed pixels */
|
|
||||||
+ if (bh->length != pp->pic_header->width
|
|
||||||
+ * pp->pic_header->height * 3) {
|
|
||||||
+ pr_err("Blob %u, type 1: Length doesn't match picture.\n",
|
|
||||||
+ i);
|
|
||||||
+
|
|
||||||
+ goto err;
|
|
||||||
+ }
|
|
||||||
+ break;
|
|
||||||
+ default:
|
|
||||||
+ pr_warn("Blob %u, unknown type %u.\n", i, bh->type);
|
|
||||||
+ goto nextblob;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ pp->blobs[pp->blobs_loaded].blob_header = bh;
|
|
||||||
+ pp->blobs[pp->blobs_loaded].data = walker;
|
|
||||||
+ pp->blobs_loaded++;
|
|
||||||
+
|
|
||||||
+nextblob:
|
|
||||||
+ walker += bh->length;
|
|
||||||
+ if (bh->length % 16)
|
|
||||||
+ walker += 16 - (bh->length % 16);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (walker != fw->data + fw->size)
|
|
||||||
+ pr_warn("Trailing data in splash file.\n");
|
|
||||||
+
|
|
||||||
+ /* Walk over pictures and ensure all blob slots are filled */
|
|
||||||
+ for (i = 0; i < fp->header->num_pics; i++) {
|
|
||||||
+ struct splash_pic_priv *pp = &fp->pics[i];
|
|
||||||
+
|
|
||||||
+ if (pp->blobs_loaded != pp->pic_header->num_blobs) {
|
|
||||||
+ pr_err("Picture %u doesn't have all blob slots filled.\n",
|
|
||||||
+ i);
|
|
||||||
+
|
|
||||||
+ goto err;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ pr_info("Loaded (%ld bytes, %u pics, %u blobs).\n",
|
|
||||||
+ fw->size,
|
|
||||||
+ fp->header->num_pics,
|
|
||||||
+ fp->header->num_blobs);
|
|
||||||
+
|
|
||||||
+ return fp;
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+err:
|
|
||||||
+ bootsplash_free_file(fp);
|
|
||||||
+ return NULL;
|
|
||||||
+}
|
|
||||||
diff --git a/drivers/video/fbdev/core/bootsplash_render.c b/drivers/video/fbdev/core/bootsplash_render.c
|
|
||||||
index 4d7e0117f653..2ae36949d0e3 100644
|
|
||||||
--- a/drivers/video/fbdev/core/bootsplash_render.c
|
|
||||||
+++ b/drivers/video/fbdev/core/bootsplash_render.c
|
|
||||||
@@ -19,6 +19,7 @@
|
|
||||||
#include <linux/types.h>
|
|
||||||
|
|
||||||
#include "bootsplash_internal.h"
|
|
||||||
+#include "uapi/linux/bootsplash_file.h"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -70,16 +71,69 @@ static inline u32 pack_pixel(const struct fb_var_screeninfo *dst_var,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
-void bootsplash_do_render_background(struct fb_info *info)
|
|
||||||
+/*
|
|
||||||
+ * Copy from source and blend into the destination picture.
|
|
||||||
+ * Currently assumes that the source picture is 24bpp.
|
|
||||||
+ * Currently assumes that the destination is <= 32bpp.
|
|
||||||
+ */
|
|
||||||
+static int splash_convert_to_fb(u8 *dst,
|
|
||||||
+ const struct fb_var_screeninfo *dst_var,
|
|
||||||
+ unsigned int dst_stride,
|
|
||||||
+ unsigned int dst_xoff,
|
|
||||||
+ unsigned int dst_yoff,
|
|
||||||
+ const u8 *src,
|
|
||||||
+ unsigned int src_width,
|
|
||||||
+ unsigned int src_height)
|
|
||||||
+{
|
|
||||||
+ unsigned int x, y;
|
|
||||||
+ unsigned int src_stride = 3 * src_width; /* Assume 24bpp packed */
|
|
||||||
+ u32 dst_octpp = dst_var->bits_per_pixel / 8;
|
|
||||||
+
|
|
||||||
+ dst_xoff += dst_var->xoffset;
|
|
||||||
+ dst_yoff += dst_var->yoffset;
|
|
||||||
+
|
|
||||||
+ /* Copy with stride and pixel size adjustment */
|
|
||||||
+ for (y = 0;
|
|
||||||
+ y < src_height && y + dst_yoff < dst_var->yres_virtual;
|
|
||||||
+ y++) {
|
|
||||||
+ const u8 *srcline = src + (y * src_stride);
|
|
||||||
+ u8 *dstline = dst + ((y + dst_yoff) * dst_stride)
|
|
||||||
+ + (dst_xoff * dst_octpp);
|
|
||||||
+
|
|
||||||
+ for (x = 0;
|
|
||||||
+ x < src_width && x + dst_xoff < dst_var->xres_virtual;
|
|
||||||
+ x++) {
|
|
||||||
+ u8 red, green, blue;
|
|
||||||
+ u32 dstpix;
|
|
||||||
+
|
|
||||||
+ /* Read pixel */
|
|
||||||
+ red = *srcline++;
|
|
||||||
+ green = *srcline++;
|
|
||||||
+ blue = *srcline++;
|
|
||||||
+
|
|
||||||
+ /* Write pixel */
|
|
||||||
+ dstpix = pack_pixel(dst_var, red, green, blue);
|
|
||||||
+ memcpy(dstline, &dstpix, dst_octpp);
|
|
||||||
+
|
|
||||||
+ dstline += dst_octpp;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+void bootsplash_do_render_background(struct fb_info *info,
|
|
||||||
+ const struct splash_file_priv *fp)
|
|
||||||
{
|
|
||||||
unsigned int x, y;
|
|
||||||
u32 dstpix;
|
|
||||||
u32 dst_octpp = info->var.bits_per_pixel / 8;
|
|
||||||
|
|
||||||
dstpix = pack_pixel(&info->var,
|
|
||||||
- 0,
|
|
||||||
- 0,
|
|
||||||
- 0);
|
|
||||||
+ fp->header->bg_red,
|
|
||||||
+ fp->header->bg_green,
|
|
||||||
+ fp->header->bg_blue);
|
|
||||||
|
|
||||||
for (y = 0; y < info->var.yres_virtual; y++) {
|
|
||||||
u8 *dstline = info->screen_buffer + (y * info->fix.line_length);
|
|
||||||
@@ -91,3 +145,44 @@ void bootsplash_do_render_background(struct fb_info *info)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+void bootsplash_do_render_pictures(struct fb_info *info,
|
|
||||||
+ const struct splash_file_priv *fp)
|
|
||||||
+{
|
|
||||||
+ unsigned int i;
|
|
||||||
+
|
|
||||||
+ for (i = 0; i < fp->header->num_pics; i++) {
|
|
||||||
+ struct splash_blob_priv *bp;
|
|
||||||
+ struct splash_pic_priv *pp = &fp->pics[i];
|
|
||||||
+ long dst_xoff, dst_yoff;
|
|
||||||
+
|
|
||||||
+ if (pp->blobs_loaded < 1)
|
|
||||||
+ continue;
|
|
||||||
+
|
|
||||||
+ bp = &pp->blobs[0];
|
|
||||||
+
|
|
||||||
+ if (!bp || bp->blob_header->type != 0)
|
|
||||||
+ continue;
|
|
||||||
+
|
|
||||||
+ dst_xoff = (info->var.xres - pp->pic_header->width) / 2;
|
|
||||||
+ dst_yoff = (info->var.yres - pp->pic_header->height) / 2;
|
|
||||||
+
|
|
||||||
+ if (dst_xoff < 0
|
|
||||||
+ || dst_yoff < 0
|
|
||||||
+ || dst_xoff + pp->pic_header->width > info->var.xres
|
|
||||||
+ || dst_yoff + pp->pic_header->height > info->var.yres) {
|
|
||||||
+ pr_info_once("Picture %u is out of bounds at current resolution: %dx%d\n"
|
|
||||||
+ "(this will only be printed once every reboot)\n",
|
|
||||||
+ i, info->var.xres, info->var.yres);
|
|
||||||
+
|
|
||||||
+ continue;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ /* Draw next splash frame */
|
|
||||||
+ splash_convert_to_fb(info->screen_buffer, &info->var,
|
|
||||||
+ info->fix.line_length, dst_xoff, dst_yoff,
|
|
||||||
+ bp->data,
|
|
||||||
+ pp->pic_header->width, pp->pic_header->height);
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
diff --git a/include/uapi/linux/bootsplash_file.h b/include/uapi/linux/bootsplash_file.h
|
|
||||||
new file mode 100644
|
|
||||||
index 000000000000..89dc9cca8f0c
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/include/uapi/linux/bootsplash_file.h
|
|
||||||
@@ -0,0 +1,118 @@
|
|
||||||
+/*
|
|
||||||
+ * Kernel based bootsplash.
|
|
||||||
+ *
|
|
||||||
+ * (File format)
|
|
||||||
+ *
|
|
||||||
+ * Authors:
|
|
||||||
+ * Max Staudt <mstaudt@suse.de>
|
|
||||||
+ *
|
|
||||||
+ * SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
|
|
||||||
+ */
|
|
||||||
+
|
|
||||||
+#ifndef __BOOTSPLASH_FILE_H
|
|
||||||
+#define __BOOTSPLASH_FILE_H
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+#define BOOTSPLASH_VERSION 55561
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+#include <linux/kernel.h>
|
|
||||||
+#include <linux/types.h>
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+/*
|
|
||||||
+ * On-disk types
|
|
||||||
+ *
|
|
||||||
+ * A splash file consists of:
|
|
||||||
+ * - One single 'struct splash_file_header'
|
|
||||||
+ * - An array of 'struct splash_pic_header'
|
|
||||||
+ * - An array of raw data blocks, each padded to 16 bytes and
|
|
||||||
+ * preceded by a 'struct splash_blob_header'
|
|
||||||
+ *
|
|
||||||
+ * A single-frame splash may look like this:
|
|
||||||
+ *
|
|
||||||
+ * +--------------------+
|
|
||||||
+ * | |
|
|
||||||
+ * | splash_file_header |
|
|
||||||
+ * | -> num_blobs = 1 |
|
|
||||||
+ * | -> num_pics = 1 |
|
|
||||||
+ * | |
|
|
||||||
+ * +--------------------+
|
|
||||||
+ * | |
|
|
||||||
+ * | splash_pic_header |
|
|
||||||
+ * | |
|
|
||||||
+ * +--------------------+
|
|
||||||
+ * | |
|
|
||||||
+ * | splash_blob_header |
|
|
||||||
+ * | -> type = 0 |
|
|
||||||
+ * | -> picture_id = 0 |
|
|
||||||
+ * | |
|
|
||||||
+ * | (raw RGB data) |
|
|
||||||
+ * | (pad to 16 bytes) |
|
|
||||||
+ * | |
|
|
||||||
+ * +--------------------+
|
|
||||||
+ *
|
|
||||||
+ * All multi-byte values are stored on disk in the native format
|
|
||||||
+ * expected by the system the file will be used on.
|
|
||||||
+ */
|
|
||||||
+#define BOOTSPLASH_MAGIC_BE "Linux bootsplash"
|
|
||||||
+#define BOOTSPLASH_MAGIC_LE "hsalpstoob xuniL"
|
|
||||||
+
|
|
||||||
+struct splash_file_header {
|
|
||||||
+ uint8_t id[16]; /* "Linux bootsplash" (no trailing NUL) */
|
|
||||||
+
|
|
||||||
+ /* Splash file format version to avoid clashes */
|
|
||||||
+ uint16_t version;
|
|
||||||
+
|
|
||||||
+ /* The background color */
|
|
||||||
+ uint8_t bg_red;
|
|
||||||
+ uint8_t bg_green;
|
|
||||||
+ uint8_t bg_blue;
|
|
||||||
+ uint8_t bg_reserved;
|
|
||||||
+
|
|
||||||
+ /*
|
|
||||||
+ * Number of pic/blobs so we can allocate memory for internal
|
|
||||||
+ * structures ahead of time when reading the file
|
|
||||||
+ */
|
|
||||||
+ uint16_t num_blobs;
|
|
||||||
+ uint8_t num_pics;
|
|
||||||
+
|
|
||||||
+ uint8_t padding[103];
|
|
||||||
+} __attribute__((__packed__));
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+struct splash_pic_header {
|
|
||||||
+ uint16_t width;
|
|
||||||
+ uint16_t height;
|
|
||||||
+
|
|
||||||
+ /*
|
|
||||||
+ * Number of data packages associated with this picture.
|
|
||||||
+ * Currently, the only use for more than 1 is for animations.
|
|
||||||
+ */
|
|
||||||
+ uint8_t num_blobs;
|
|
||||||
+
|
|
||||||
+ uint8_t padding[27];
|
|
||||||
+} __attribute__((__packed__));
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+struct splash_blob_header {
|
|
||||||
+ /* Length of the data block in bytes. */
|
|
||||||
+ uint32_t length;
|
|
||||||
+
|
|
||||||
+ /*
|
|
||||||
+ * Type of the contents.
|
|
||||||
+ * 0 - Raw RGB data.
|
|
||||||
+ */
|
|
||||||
+ uint16_t type;
|
|
||||||
+
|
|
||||||
+ /*
|
|
||||||
+ * Picture this blob is associated with.
|
|
||||||
+ * Blobs will be added to a picture in the order they are
|
|
||||||
+ * found in the file.
|
|
||||||
+ */
|
|
||||||
+ uint8_t picture_id;
|
|
||||||
+
|
|
||||||
+ uint8_t padding[9];
|
|
||||||
+} __attribute__((__packed__));
|
|
||||||
+
|
|
||||||
+#endif
|
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
diff --git a/drivers/video/fbdev/core/bootsplash.c b/drivers/video/fbdev/core/bootsplash.c
|
|
||||||
index 843c5400fefc..815b007f81ca 100644
|
|
||||||
--- a/drivers/video/fbdev/core/bootsplash.c
|
|
||||||
+++ b/drivers/video/fbdev/core/bootsplash.c
|
|
||||||
@@ -112,6 +112,8 @@ void bootsplash_render_full(struct fb_info *info)
|
|
||||||
|
|
||||||
bootsplash_do_render_pictures(info, splash_state.file);
|
|
||||||
|
|
||||||
+ bootsplash_do_render_flush(info);
|
|
||||||
+
|
|
||||||
out:
|
|
||||||
mutex_unlock(&splash_state.data_lock);
|
|
||||||
}
|
|
||||||
diff --git a/drivers/video/fbdev/core/bootsplash_internal.h b/drivers/video/fbdev/core/bootsplash_internal.h
|
|
||||||
index 71e2a27ac0b8..0acb383aa4e3 100644
|
|
||||||
--- a/drivers/video/fbdev/core/bootsplash_internal.h
|
|
||||||
+++ b/drivers/video/fbdev/core/bootsplash_internal.h
|
|
||||||
@@ -89,6 +89,7 @@ void bootsplash_do_render_background(struct fb_info *info,
|
|
||||||
const struct splash_file_priv *fp);
|
|
||||||
void bootsplash_do_render_pictures(struct fb_info *info,
|
|
||||||
const struct splash_file_priv *fp);
|
|
||||||
+void bootsplash_do_render_flush(struct fb_info *info);
|
|
||||||
|
|
||||||
|
|
||||||
void bootsplash_free_file(struct splash_file_priv *fp);
|
|
||||||
diff --git a/drivers/video/fbdev/core/bootsplash_render.c b/drivers/video/fbdev/core/bootsplash_render.c
|
|
||||||
index 2ae36949d0e3..8c09c306ff67 100644
|
|
||||||
--- a/drivers/video/fbdev/core/bootsplash_render.c
|
|
||||||
+++ b/drivers/video/fbdev/core/bootsplash_render.c
|
|
||||||
@@ -186,3 +186,36 @@ void bootsplash_do_render_pictures(struct fb_info *info,
|
|
||||||
pp->pic_header->width, pp->pic_header->height);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+void bootsplash_do_render_flush(struct fb_info *info)
|
|
||||||
+{
|
|
||||||
+ /*
|
|
||||||
+ * FB drivers using deferred_io (such as Xen) need to sync the
|
|
||||||
+ * screen after modifying its contents. When the FB is mmap()ed
|
|
||||||
+ * from userspace, this happens via a dirty pages callback, but
|
|
||||||
+ * when modifying the FB from the kernel, there is no such thing.
|
|
||||||
+ *
|
|
||||||
+ * So let's issue a fake fb_copyarea (copying the FB onto itself)
|
|
||||||
+ * to trick the FB driver into syncing the screen.
|
|
||||||
+ *
|
|
||||||
+ * A few DRM drivers' FB implementations are broken by not using
|
|
||||||
+ * deferred_io when they really should - we match on the known
|
|
||||||
+ * bad ones manually for now.
|
|
||||||
+ */
|
|
||||||
+ if (info->fbdefio
|
|
||||||
+ || !strcmp(info->fix.id, "astdrmfb")
|
|
||||||
+ || !strcmp(info->fix.id, "cirrusdrmfb")
|
|
||||||
+ || !strcmp(info->fix.id, "mgadrmfb")) {
|
|
||||||
+ struct fb_copyarea area;
|
|
||||||
+
|
|
||||||
+ area.dx = 0;
|
|
||||||
+ area.dy = 0;
|
|
||||||
+ area.width = info->var.xres;
|
|
||||||
+ area.height = info->var.yres;
|
|
||||||
+ area.sx = 0;
|
|
||||||
+ area.sy = 0;
|
|
||||||
+
|
|
||||||
+ info->fbops->fb_copyarea(info, &area);
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
@@ -1,215 +0,0 @@
|
|||||||
diff --git a/drivers/video/fbdev/core/bootsplash_render.c b/drivers/video/fbdev/core/bootsplash_render.c
|
|
||||||
index 8c09c306ff67..07e3a4eab811 100644
|
|
||||||
--- a/drivers/video/fbdev/core/bootsplash_render.c
|
|
||||||
+++ b/drivers/video/fbdev/core/bootsplash_render.c
|
|
||||||
@@ -155,6 +155,7 @@ void bootsplash_do_render_pictures(struct fb_info *info,
|
|
||||||
for (i = 0; i < fp->header->num_pics; i++) {
|
|
||||||
struct splash_blob_priv *bp;
|
|
||||||
struct splash_pic_priv *pp = &fp->pics[i];
|
|
||||||
+ const struct splash_pic_header *ph = pp->pic_header;
|
|
||||||
long dst_xoff, dst_yoff;
|
|
||||||
|
|
||||||
if (pp->blobs_loaded < 1)
|
|
||||||
@@ -165,8 +166,139 @@ void bootsplash_do_render_pictures(struct fb_info *info,
|
|
||||||
if (!bp || bp->blob_header->type != 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
- dst_xoff = (info->var.xres - pp->pic_header->width) / 2;
|
|
||||||
- dst_yoff = (info->var.yres - pp->pic_header->height) / 2;
|
|
||||||
+ switch (ph->position) {
|
|
||||||
+ case SPLASH_POS_FLAG_CORNER | SPLASH_CORNER_TOP_LEFT:
|
|
||||||
+ dst_xoff = 0;
|
|
||||||
+ dst_yoff = 0;
|
|
||||||
+
|
|
||||||
+ dst_xoff += ph->position_offset;
|
|
||||||
+ dst_yoff += ph->position_offset;
|
|
||||||
+ break;
|
|
||||||
+ case SPLASH_POS_FLAG_CORNER | SPLASH_CORNER_TOP:
|
|
||||||
+ dst_xoff = info->var.xres - pp->pic_header->width;
|
|
||||||
+ dst_xoff /= 2;
|
|
||||||
+ dst_yoff = 0;
|
|
||||||
+
|
|
||||||
+ dst_yoff += ph->position_offset;
|
|
||||||
+ break;
|
|
||||||
+ case SPLASH_POS_FLAG_CORNER | SPLASH_CORNER_TOP_RIGHT:
|
|
||||||
+ dst_xoff = info->var.xres - pp->pic_header->width;
|
|
||||||
+ dst_yoff = 0;
|
|
||||||
+
|
|
||||||
+ dst_xoff -= ph->position_offset;
|
|
||||||
+ dst_yoff += ph->position_offset;
|
|
||||||
+ break;
|
|
||||||
+ case SPLASH_POS_FLAG_CORNER | SPLASH_CORNER_RIGHT:
|
|
||||||
+ dst_xoff = info->var.xres - pp->pic_header->width;
|
|
||||||
+ dst_yoff = info->var.yres - pp->pic_header->height;
|
|
||||||
+ dst_yoff /= 2;
|
|
||||||
+
|
|
||||||
+ dst_xoff -= ph->position_offset;
|
|
||||||
+ break;
|
|
||||||
+ case SPLASH_POS_FLAG_CORNER | SPLASH_CORNER_BOTTOM_RIGHT:
|
|
||||||
+ dst_xoff = info->var.xres - pp->pic_header->width;
|
|
||||||
+ dst_yoff = info->var.yres - pp->pic_header->height;
|
|
||||||
+
|
|
||||||
+ dst_xoff -= ph->position_offset;
|
|
||||||
+ dst_yoff -= ph->position_offset;
|
|
||||||
+ break;
|
|
||||||
+ case SPLASH_POS_FLAG_CORNER | SPLASH_CORNER_BOTTOM:
|
|
||||||
+ dst_xoff = info->var.xres - pp->pic_header->width;
|
|
||||||
+ dst_xoff /= 2;
|
|
||||||
+ dst_yoff = info->var.yres - pp->pic_header->height;
|
|
||||||
+
|
|
||||||
+ dst_yoff -= ph->position_offset;
|
|
||||||
+ break;
|
|
||||||
+ case SPLASH_POS_FLAG_CORNER | SPLASH_CORNER_BOTTOM_LEFT:
|
|
||||||
+ dst_xoff = 0 + ph->position_offset;
|
|
||||||
+ dst_yoff = info->var.yres - pp->pic_header->height
|
|
||||||
+ - ph->position_offset;
|
|
||||||
+ break;
|
|
||||||
+ case SPLASH_POS_FLAG_CORNER | SPLASH_CORNER_LEFT:
|
|
||||||
+ dst_xoff = 0;
|
|
||||||
+ dst_yoff = info->var.yres - pp->pic_header->height;
|
|
||||||
+ dst_yoff /= 2;
|
|
||||||
+
|
|
||||||
+ dst_xoff += ph->position_offset;
|
|
||||||
+ break;
|
|
||||||
+
|
|
||||||
+ case SPLASH_CORNER_TOP_LEFT:
|
|
||||||
+ dst_xoff = info->var.xres - pp->pic_header->width;
|
|
||||||
+ dst_xoff /= 2;
|
|
||||||
+ dst_yoff = info->var.yres - pp->pic_header->height;
|
|
||||||
+ dst_yoff /= 2;
|
|
||||||
+
|
|
||||||
+ dst_xoff -= ph->position_offset;
|
|
||||||
+ dst_yoff -= ph->position_offset;
|
|
||||||
+ break;
|
|
||||||
+ case SPLASH_CORNER_TOP:
|
|
||||||
+ dst_xoff = info->var.xres - pp->pic_header->width;
|
|
||||||
+ dst_xoff /= 2;
|
|
||||||
+ dst_yoff = info->var.yres - pp->pic_header->height;
|
|
||||||
+ dst_yoff /= 2;
|
|
||||||
+
|
|
||||||
+ dst_yoff -= ph->position_offset;
|
|
||||||
+ break;
|
|
||||||
+ case SPLASH_CORNER_TOP_RIGHT:
|
|
||||||
+ dst_xoff = info->var.xres - pp->pic_header->width;
|
|
||||||
+ dst_xoff /= 2;
|
|
||||||
+ dst_yoff = info->var.yres - pp->pic_header->height;
|
|
||||||
+ dst_yoff /= 2;
|
|
||||||
+
|
|
||||||
+ dst_xoff += ph->position_offset;
|
|
||||||
+ dst_yoff -= ph->position_offset;
|
|
||||||
+ break;
|
|
||||||
+ case SPLASH_CORNER_RIGHT:
|
|
||||||
+ dst_xoff = info->var.xres - pp->pic_header->width;
|
|
||||||
+ dst_xoff /= 2;
|
|
||||||
+ dst_yoff = info->var.yres - pp->pic_header->height;
|
|
||||||
+ dst_yoff /= 2;
|
|
||||||
+
|
|
||||||
+ dst_xoff += ph->position_offset;
|
|
||||||
+ break;
|
|
||||||
+ case SPLASH_CORNER_BOTTOM_RIGHT:
|
|
||||||
+ dst_xoff = info->var.xres - pp->pic_header->width;
|
|
||||||
+ dst_xoff /= 2;
|
|
||||||
+ dst_yoff = info->var.yres - pp->pic_header->height;
|
|
||||||
+ dst_yoff /= 2;
|
|
||||||
+
|
|
||||||
+ dst_xoff += ph->position_offset;
|
|
||||||
+ dst_yoff += ph->position_offset;
|
|
||||||
+ break;
|
|
||||||
+ case SPLASH_CORNER_BOTTOM:
|
|
||||||
+ dst_xoff = info->var.xres - pp->pic_header->width;
|
|
||||||
+ dst_xoff /= 2;
|
|
||||||
+ dst_yoff = info->var.yres - pp->pic_header->height;
|
|
||||||
+ dst_yoff /= 2;
|
|
||||||
+
|
|
||||||
+ dst_yoff += ph->position_offset;
|
|
||||||
+ break;
|
|
||||||
+ case SPLASH_CORNER_BOTTOM_LEFT:
|
|
||||||
+ dst_xoff = info->var.xres - pp->pic_header->width;
|
|
||||||
+ dst_xoff /= 2;
|
|
||||||
+ dst_yoff = info->var.yres - pp->pic_header->height;
|
|
||||||
+ dst_yoff /= 2;
|
|
||||||
+
|
|
||||||
+ dst_xoff -= ph->position_offset;
|
|
||||||
+ dst_yoff += ph->position_offset;
|
|
||||||
+ break;
|
|
||||||
+ case SPLASH_CORNER_LEFT:
|
|
||||||
+ dst_xoff = info->var.xres - pp->pic_header->width;
|
|
||||||
+ dst_xoff /= 2;
|
|
||||||
+ dst_yoff = info->var.yres - pp->pic_header->height;
|
|
||||||
+ dst_yoff /= 2;
|
|
||||||
+
|
|
||||||
+ dst_xoff -= ph->position_offset;
|
|
||||||
+ break;
|
|
||||||
+
|
|
||||||
+ default:
|
|
||||||
+ /* As a fallback, center the picture. */
|
|
||||||
+ dst_xoff = info->var.xres - pp->pic_header->width;
|
|
||||||
+ dst_xoff /= 2;
|
|
||||||
+ dst_yoff = info->var.yres - pp->pic_header->height;
|
|
||||||
+ dst_yoff /= 2;
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
if (dst_xoff < 0
|
|
||||||
|| dst_yoff < 0
|
|
||||||
diff --git a/include/uapi/linux/bootsplash_file.h b/include/uapi/linux/bootsplash_file.h
|
|
||||||
index 89dc9cca8f0c..71cedcc68933 100644
|
|
||||||
--- a/include/uapi/linux/bootsplash_file.h
|
|
||||||
+++ b/include/uapi/linux/bootsplash_file.h
|
|
||||||
@@ -91,7 +91,32 @@ struct splash_pic_header {
|
|
||||||
*/
|
|
||||||
uint8_t num_blobs;
|
|
||||||
|
|
||||||
- uint8_t padding[27];
|
|
||||||
+ /*
|
|
||||||
+ * Corner to move the picture to / from.
|
|
||||||
+ * 0x00 - Top left
|
|
||||||
+ * 0x01 - Top
|
|
||||||
+ * 0x02 - Top right
|
|
||||||
+ * 0x03 - Right
|
|
||||||
+ * 0x04 - Bottom right
|
|
||||||
+ * 0x05 - Bottom
|
|
||||||
+ * 0x06 - Bottom left
|
|
||||||
+ * 0x07 - Left
|
|
||||||
+ *
|
|
||||||
+ * Flags:
|
|
||||||
+ * 0x10 - Calculate offset from the corner towards the center,
|
|
||||||
+ * rather than from the center towards the corner
|
|
||||||
+ */
|
|
||||||
+ uint8_t position;
|
|
||||||
+
|
|
||||||
+ /*
|
|
||||||
+ * Pixel offset from the selected position.
|
|
||||||
+ * Example: If the picture is in the top right corner, it will
|
|
||||||
+ * be placed position_offset pixels from the top and
|
|
||||||
+ * position_offset pixels from the right margin.
|
|
||||||
+ */
|
|
||||||
+ uint16_t position_offset;
|
|
||||||
+
|
|
||||||
+ uint8_t padding[24];
|
|
||||||
} __attribute__((__packed__));
|
|
||||||
|
|
||||||
|
|
||||||
@@ -115,4 +140,22 @@ struct splash_blob_header {
|
|
||||||
uint8_t padding[9];
|
|
||||||
} __attribute__((__packed__));
|
|
||||||
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+/*
|
|
||||||
+ * Enums for on-disk types
|
|
||||||
+ */
|
|
||||||
+enum splash_position {
|
|
||||||
+ SPLASH_CORNER_TOP_LEFT = 0,
|
|
||||||
+ SPLASH_CORNER_TOP = 1,
|
|
||||||
+ SPLASH_CORNER_TOP_RIGHT = 2,
|
|
||||||
+ SPLASH_CORNER_RIGHT = 3,
|
|
||||||
+ SPLASH_CORNER_BOTTOM_RIGHT = 4,
|
|
||||||
+ SPLASH_CORNER_BOTTOM = 5,
|
|
||||||
+ SPLASH_CORNER_BOTTOM_LEFT = 6,
|
|
||||||
+ SPLASH_CORNER_LEFT = 7,
|
|
||||||
+ SPLASH_POS_FLAG_CORNER = 0x10,
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
#endif
|
|
||||||
@@ -1,327 +0,0 @@
|
|||||||
diff --git a/drivers/video/fbdev/core/bootsplash.c b/drivers/video/fbdev/core/bootsplash.c
|
|
||||||
index 815b007f81ca..c8642142cfea 100644
|
|
||||||
--- a/drivers/video/fbdev/core/bootsplash.c
|
|
||||||
+++ b/drivers/video/fbdev/core/bootsplash.c
|
|
||||||
@@ -53,6 +53,14 @@ static void splash_callback_redraw_vc(struct work_struct *ignored)
|
|
||||||
console_unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
+static void splash_callback_animation(struct work_struct *ignored)
|
|
||||||
+{
|
|
||||||
+ if (bootsplash_would_render_now()) {
|
|
||||||
+ /* This will also re-schedule this delayed worker */
|
|
||||||
+ splash_callback_redraw_vc(ignored);
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
|
|
||||||
static bool is_fb_compatible(const struct fb_info *info)
|
|
||||||
{
|
|
||||||
@@ -103,17 +111,44 @@ static bool is_fb_compatible(const struct fb_info *info)
|
|
||||||
*/
|
|
||||||
void bootsplash_render_full(struct fb_info *info)
|
|
||||||
{
|
|
||||||
+ bool is_update = false;
|
|
||||||
+
|
|
||||||
mutex_lock(&splash_state.data_lock);
|
|
||||||
|
|
||||||
- if (!is_fb_compatible(info))
|
|
||||||
- goto out;
|
|
||||||
+ /*
|
|
||||||
+ * If we've painted on this FB recently, we don't have to do
|
|
||||||
+ * the sanity checks and background drawing again.
|
|
||||||
+ */
|
|
||||||
+ if (splash_state.splash_fb == info)
|
|
||||||
+ is_update = true;
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+ if (!is_update) {
|
|
||||||
+ /* Check whether we actually support this FB. */
|
|
||||||
+ splash_state.splash_fb = NULL;
|
|
||||||
+
|
|
||||||
+ if (!is_fb_compatible(info))
|
|
||||||
+ goto out;
|
|
||||||
+
|
|
||||||
+ /* Draw the background only once */
|
|
||||||
+ bootsplash_do_render_background(info, splash_state.file);
|
|
||||||
|
|
||||||
- bootsplash_do_render_background(info, splash_state.file);
|
|
||||||
+ /* Mark this FB as last seen */
|
|
||||||
+ splash_state.splash_fb = info;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
- bootsplash_do_render_pictures(info, splash_state.file);
|
|
||||||
+ bootsplash_do_render_pictures(info, splash_state.file, is_update);
|
|
||||||
|
|
||||||
bootsplash_do_render_flush(info);
|
|
||||||
|
|
||||||
+ bootsplash_do_step_animations(splash_state.file);
|
|
||||||
+
|
|
||||||
+ /* Schedule update for animated splash screens */
|
|
||||||
+ if (splash_state.file->frame_ms > 0)
|
|
||||||
+ schedule_delayed_work(&splash_state.dwork_animation,
|
|
||||||
+ msecs_to_jiffies(
|
|
||||||
+ splash_state.file->frame_ms));
|
|
||||||
+
|
|
||||||
out:
|
|
||||||
mutex_unlock(&splash_state.data_lock);
|
|
||||||
}
|
|
||||||
@@ -169,8 +204,14 @@ void bootsplash_enable(void)
|
|
||||||
|
|
||||||
was_enabled = test_and_set_bit(0, &splash_state.enabled);
|
|
||||||
|
|
||||||
- if (!was_enabled)
|
|
||||||
+ if (!was_enabled) {
|
|
||||||
+ /* Force a full redraw when the splash is re-activated */
|
|
||||||
+ mutex_lock(&splash_state.data_lock);
|
|
||||||
+ splash_state.splash_fb = NULL;
|
|
||||||
+ mutex_unlock(&splash_state.data_lock);
|
|
||||||
+
|
|
||||||
schedule_work(&splash_state.work_redraw_vc);
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@@ -227,6 +268,14 @@ ATTRIBUTE_GROUPS(splash_dev);
|
|
||||||
*/
|
|
||||||
static int splash_resume(struct device *device)
|
|
||||||
{
|
|
||||||
+ /*
|
|
||||||
+ * Force full redraw on resume since we've probably lost the
|
|
||||||
+ * framebuffer's contents meanwhile
|
|
||||||
+ */
|
|
||||||
+ mutex_lock(&splash_state.data_lock);
|
|
||||||
+ splash_state.splash_fb = NULL;
|
|
||||||
+ mutex_unlock(&splash_state.data_lock);
|
|
||||||
+
|
|
||||||
if (bootsplash_would_render_now())
|
|
||||||
schedule_work(&splash_state.work_redraw_vc);
|
|
||||||
|
|
||||||
@@ -235,6 +284,7 @@ static int splash_resume(struct device *device)
|
|
||||||
|
|
||||||
static int splash_suspend(struct device *device)
|
|
||||||
{
|
|
||||||
+ cancel_delayed_work_sync(&splash_state.dwork_animation);
|
|
||||||
cancel_work_sync(&splash_state.work_redraw_vc);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
@@ -296,6 +346,8 @@ void bootsplash_init(void)
|
|
||||||
set_bit(0, &splash_state.enabled);
|
|
||||||
|
|
||||||
INIT_WORK(&splash_state.work_redraw_vc, splash_callback_redraw_vc);
|
|
||||||
+ INIT_DELAYED_WORK(&splash_state.dwork_animation,
|
|
||||||
+ splash_callback_animation);
|
|
||||||
|
|
||||||
|
|
||||||
if (!splash_state.bootfile || !strlen(splash_state.bootfile))
|
|
||||||
diff --git a/drivers/video/fbdev/core/bootsplash_internal.h b/drivers/video/fbdev/core/bootsplash_internal.h
|
|
||||||
index 0acb383aa4e3..b3a74835d90f 100644
|
|
||||||
--- a/drivers/video/fbdev/core/bootsplash_internal.h
|
|
||||||
+++ b/drivers/video/fbdev/core/bootsplash_internal.h
|
|
||||||
@@ -37,6 +37,8 @@ struct splash_pic_priv {
|
|
||||||
|
|
||||||
struct splash_blob_priv *blobs;
|
|
||||||
u16 blobs_loaded;
|
|
||||||
+
|
|
||||||
+ u16 anim_nextframe;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
@@ -45,6 +47,12 @@ struct splash_file_priv {
|
|
||||||
const struct splash_file_header *header;
|
|
||||||
|
|
||||||
struct splash_pic_priv *pics;
|
|
||||||
+
|
|
||||||
+ /*
|
|
||||||
+ * A local copy of the frame delay in the header.
|
|
||||||
+ * We modify it to keep the code simple.
|
|
||||||
+ */
|
|
||||||
+ u16 frame_ms;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
@@ -71,6 +79,7 @@ struct splash_priv {
|
|
||||||
struct platform_device *splash_device;
|
|
||||||
|
|
||||||
struct work_struct work_redraw_vc;
|
|
||||||
+ struct delayed_work dwork_animation;
|
|
||||||
|
|
||||||
/* Splash data structures including lock for everything below */
|
|
||||||
struct mutex data_lock;
|
|
||||||
@@ -88,8 +97,10 @@ struct splash_priv {
|
|
||||||
void bootsplash_do_render_background(struct fb_info *info,
|
|
||||||
const struct splash_file_priv *fp);
|
|
||||||
void bootsplash_do_render_pictures(struct fb_info *info,
|
|
||||||
- const struct splash_file_priv *fp);
|
|
||||||
+ const struct splash_file_priv *fp,
|
|
||||||
+ bool is_update);
|
|
||||||
void bootsplash_do_render_flush(struct fb_info *info);
|
|
||||||
+void bootsplash_do_step_animations(struct splash_file_priv *fp);
|
|
||||||
|
|
||||||
|
|
||||||
void bootsplash_free_file(struct splash_file_priv *fp);
|
|
||||||
diff --git a/drivers/video/fbdev/core/bootsplash_load.c b/drivers/video/fbdev/core/bootsplash_load.c
|
|
||||||
index fd807571ab7d..1f661b2d4cc9 100644
|
|
||||||
--- a/drivers/video/fbdev/core/bootsplash_load.c
|
|
||||||
+++ b/drivers/video/fbdev/core/bootsplash_load.c
|
|
||||||
@@ -71,6 +71,7 @@ struct splash_file_priv *bootsplash_load_firmware(struct device *device,
|
|
||||||
{
|
|
||||||
const struct firmware *fw;
|
|
||||||
struct splash_file_priv *fp;
|
|
||||||
+ bool have_anim = false;
|
|
||||||
unsigned int i;
|
|
||||||
const u8 *walker;
|
|
||||||
|
|
||||||
@@ -135,6 +136,13 @@ struct splash_file_priv *bootsplash_load_firmware(struct device *device,
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ if (ph->anim_type > SPLASH_ANIM_LOOP_FORWARD) {
|
|
||||||
+ pr_warn("Picture %u: Unsupported animation type %u.\n",
|
|
||||||
+ i, ph->anim_type);
|
|
||||||
+
|
|
||||||
+ ph->anim_type = SPLASH_ANIM_NONE;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
pp->pic_header = ph;
|
|
||||||
pp->blobs = vzalloc(ph->num_blobs
|
|
||||||
* sizeof(struct splash_blob_priv));
|
|
||||||
@@ -202,6 +210,7 @@ struct splash_file_priv *bootsplash_load_firmware(struct device *device,
|
|
||||||
/* Walk over pictures and ensure all blob slots are filled */
|
|
||||||
for (i = 0; i < fp->header->num_pics; i++) {
|
|
||||||
struct splash_pic_priv *pp = &fp->pics[i];
|
|
||||||
+ const struct splash_pic_header *ph = pp->pic_header;
|
|
||||||
|
|
||||||
if (pp->blobs_loaded != pp->pic_header->num_blobs) {
|
|
||||||
pr_err("Picture %u doesn't have all blob slots filled.\n",
|
|
||||||
@@ -209,8 +218,20 @@ struct splash_file_priv *bootsplash_load_firmware(struct device *device,
|
|
||||||
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
+
|
|
||||||
+ if (ph->anim_type
|
|
||||||
+ && ph->num_blobs > 1
|
|
||||||
+ && ph->anim_loop < pp->blobs_loaded)
|
|
||||||
+ have_anim = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ if (!have_anim)
|
|
||||||
+ /* Disable animation timer if there is nothing to animate */
|
|
||||||
+ fp->frame_ms = 0;
|
|
||||||
+ else
|
|
||||||
+ /* Enforce minimum delay between frames */
|
|
||||||
+ fp->frame_ms = max((u16)20, fp->header->frame_ms);
|
|
||||||
+
|
|
||||||
pr_info("Loaded (%ld bytes, %u pics, %u blobs).\n",
|
|
||||||
fw->size,
|
|
||||||
fp->header->num_pics,
|
|
||||||
diff --git a/drivers/video/fbdev/core/bootsplash_render.c b/drivers/video/fbdev/core/bootsplash_render.c
|
|
||||||
index 07e3a4eab811..76033606ca8a 100644
|
|
||||||
--- a/drivers/video/fbdev/core/bootsplash_render.c
|
|
||||||
+++ b/drivers/video/fbdev/core/bootsplash_render.c
|
|
||||||
@@ -148,7 +148,8 @@ void bootsplash_do_render_background(struct fb_info *info,
|
|
||||||
|
|
||||||
|
|
||||||
void bootsplash_do_render_pictures(struct fb_info *info,
|
|
||||||
- const struct splash_file_priv *fp)
|
|
||||||
+ const struct splash_file_priv *fp,
|
|
||||||
+ bool is_update)
|
|
||||||
{
|
|
||||||
unsigned int i;
|
|
||||||
|
|
||||||
@@ -161,7 +162,11 @@ void bootsplash_do_render_pictures(struct fb_info *info,
|
|
||||||
if (pp->blobs_loaded < 1)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
- bp = &pp->blobs[0];
|
|
||||||
+ /* Skip static pictures when refreshing animations */
|
|
||||||
+ if (ph->anim_type == SPLASH_ANIM_NONE && is_update)
|
|
||||||
+ continue;
|
|
||||||
+
|
|
||||||
+ bp = &pp->blobs[pp->anim_nextframe];
|
|
||||||
|
|
||||||
if (!bp || bp->blob_header->type != 0)
|
|
||||||
continue;
|
|
||||||
@@ -351,3 +356,24 @@ void bootsplash_do_render_flush(struct fb_info *info)
|
|
||||||
info->fbops->fb_copyarea(info, &area);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+void bootsplash_do_step_animations(struct splash_file_priv *fp)
|
|
||||||
+{
|
|
||||||
+ unsigned int i;
|
|
||||||
+
|
|
||||||
+ /* Step every animation once */
|
|
||||||
+ for (i = 0; i < fp->header->num_pics; i++) {
|
|
||||||
+ struct splash_pic_priv *pp = &fp->pics[i];
|
|
||||||
+
|
|
||||||
+ if (pp->blobs_loaded < 2
|
|
||||||
+ || pp->pic_header->anim_loop > pp->blobs_loaded)
|
|
||||||
+ continue;
|
|
||||||
+
|
|
||||||
+ if (pp->pic_header->anim_type == SPLASH_ANIM_LOOP_FORWARD) {
|
|
||||||
+ pp->anim_nextframe++;
|
|
||||||
+ if (pp->anim_nextframe >= pp->pic_header->num_blobs)
|
|
||||||
+ pp->anim_nextframe = pp->pic_header->anim_loop;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
diff --git a/include/uapi/linux/bootsplash_file.h b/include/uapi/linux/bootsplash_file.h
|
|
||||||
index 71cedcc68933..b3af0a3c6487 100644
|
|
||||||
--- a/include/uapi/linux/bootsplash_file.h
|
|
||||||
+++ b/include/uapi/linux/bootsplash_file.h
|
|
||||||
@@ -77,7 +77,17 @@ struct splash_file_header {
|
|
||||||
uint16_t num_blobs;
|
|
||||||
uint8_t num_pics;
|
|
||||||
|
|
||||||
- uint8_t padding[103];
|
|
||||||
+ uint8_t unused_1;
|
|
||||||
+
|
|
||||||
+ /*
|
|
||||||
+ * Milliseconds to wait before painting the next frame in
|
|
||||||
+ * an animation.
|
|
||||||
+ * This is actually a minimum, as the system is allowed to
|
|
||||||
+ * stall for longer between frames.
|
|
||||||
+ */
|
|
||||||
+ uint16_t frame_ms;
|
|
||||||
+
|
|
||||||
+ uint8_t padding[100];
|
|
||||||
} __attribute__((__packed__));
|
|
||||||
|
|
||||||
|
|
||||||
@@ -116,7 +126,23 @@ struct splash_pic_header {
|
|
||||||
*/
|
|
||||||
uint16_t position_offset;
|
|
||||||
|
|
||||||
- uint8_t padding[24];
|
|
||||||
+ /*
|
|
||||||
+ * Animation type.
|
|
||||||
+ * 0 - off
|
|
||||||
+ * 1 - forward loop
|
|
||||||
+ */
|
|
||||||
+ uint8_t anim_type;
|
|
||||||
+
|
|
||||||
+ /*
|
|
||||||
+ * Animation loop point.
|
|
||||||
+ * Actual meaning depends on animation type:
|
|
||||||
+ * Type 0 - Unused
|
|
||||||
+ * 1 - Frame at which to restart the forward loop
|
|
||||||
+ * (allowing for "intro" frames)
|
|
||||||
+ */
|
|
||||||
+ uint8_t anim_loop;
|
|
||||||
+
|
|
||||||
+ uint8_t padding[22];
|
|
||||||
} __attribute__((__packed__));
|
|
||||||
|
|
||||||
|
|
||||||
@@ -158,4 +184,9 @@ enum splash_position {
|
|
||||||
SPLASH_POS_FLAG_CORNER = 0x10,
|
|
||||||
};
|
|
||||||
|
|
||||||
+enum splash_anim_type {
|
|
||||||
+ SPLASH_ANIM_NONE = 0,
|
|
||||||
+ SPLASH_ANIM_LOOP_FORWARD = 1,
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
#endif
|
|
||||||
@@ -1,82 +0,0 @@
|
|||||||
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
|
|
||||||
index 2ebaba16f785..416735ab6dc1 100644
|
|
||||||
--- a/drivers/tty/vt/vt.c
|
|
||||||
+++ b/drivers/tty/vt/vt.c
|
|
||||||
@@ -105,6 +105,7 @@
|
|
||||||
#include <linux/ctype.h>
|
|
||||||
#include <linux/bsearch.h>
|
|
||||||
#include <linux/gcd.h>
|
|
||||||
+#include <linux/bootsplash.h>
|
|
||||||
|
|
||||||
#define MAX_NR_CON_DRIVER 16
|
|
||||||
|
|
||||||
@@ -4235,6 +4236,7 @@ void do_unblank_screen(int leaving_gfx)
|
|
||||||
}
|
|
||||||
|
|
||||||
console_blanked = 0;
|
|
||||||
+ bootsplash_mark_dirty();
|
|
||||||
if (vc->vc_sw->con_blank(vc, 0, leaving_gfx))
|
|
||||||
/* Low-level driver cannot restore -> do it ourselves */
|
|
||||||
update_screen(vc);
|
|
||||||
diff --git a/drivers/video/fbdev/core/bootsplash.c b/drivers/video/fbdev/core/bootsplash.c
|
|
||||||
index c8642142cfea..13fcaabbc2ca 100644
|
|
||||||
--- a/drivers/video/fbdev/core/bootsplash.c
|
|
||||||
+++ b/drivers/video/fbdev/core/bootsplash.c
|
|
||||||
@@ -165,6 +165,13 @@ bool bootsplash_would_render_now(void)
|
|
||||||
&& bootsplash_is_enabled();
|
|
||||||
}
|
|
||||||
|
|
||||||
+void bootsplash_mark_dirty(void)
|
|
||||||
+{
|
|
||||||
+ mutex_lock(&splash_state.data_lock);
|
|
||||||
+ splash_state.splash_fb = NULL;
|
|
||||||
+ mutex_unlock(&splash_state.data_lock);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
bool bootsplash_is_enabled(void)
|
|
||||||
{
|
|
||||||
bool was_enabled;
|
|
||||||
@@ -206,9 +213,7 @@ void bootsplash_enable(void)
|
|
||||||
|
|
||||||
if (!was_enabled) {
|
|
||||||
/* Force a full redraw when the splash is re-activated */
|
|
||||||
- mutex_lock(&splash_state.data_lock);
|
|
||||||
- splash_state.splash_fb = NULL;
|
|
||||||
- mutex_unlock(&splash_state.data_lock);
|
|
||||||
+ bootsplash_mark_dirty();
|
|
||||||
|
|
||||||
schedule_work(&splash_state.work_redraw_vc);
|
|
||||||
}
|
|
||||||
@@ -272,9 +277,7 @@ static int splash_resume(struct device *device)
|
|
||||||
* Force full redraw on resume since we've probably lost the
|
|
||||||
* framebuffer's contents meanwhile
|
|
||||||
*/
|
|
||||||
- mutex_lock(&splash_state.data_lock);
|
|
||||||
- splash_state.splash_fb = NULL;
|
|
||||||
- mutex_unlock(&splash_state.data_lock);
|
|
||||||
+ bootsplash_mark_dirty();
|
|
||||||
|
|
||||||
if (bootsplash_would_render_now())
|
|
||||||
schedule_work(&splash_state.work_redraw_vc);
|
|
||||||
diff --git a/include/linux/bootsplash.h b/include/linux/bootsplash.h
|
|
||||||
index c6dd0b43180d..4075098aaadd 100644
|
|
||||||
--- a/include/linux/bootsplash.h
|
|
||||||
+++ b/include/linux/bootsplash.h
|
|
||||||
@@ -19,6 +19,8 @@ extern void bootsplash_render_full(struct fb_info *info);
|
|
||||||
|
|
||||||
extern bool bootsplash_would_render_now(void);
|
|
||||||
|
|
||||||
+extern void bootsplash_mark_dirty(void);
|
|
||||||
+
|
|
||||||
extern bool bootsplash_is_enabled(void);
|
|
||||||
extern void bootsplash_disable(void);
|
|
||||||
extern void bootsplash_enable(void);
|
|
||||||
@@ -31,6 +33,8 @@ extern void bootsplash_init(void);
|
|
||||||
|
|
||||||
#define bootsplash_would_render_now() (false)
|
|
||||||
|
|
||||||
+#define bootsplash_mark_dirty()
|
|
||||||
+
|
|
||||||
#define bootsplash_is_enabled() (false)
|
|
||||||
#define bootsplash_disable()
|
|
||||||
#define bootsplash_enable()
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c
|
|
||||||
index f4166263bb3a..a248429194bb 100644
|
|
||||||
--- a/drivers/tty/vt/keyboard.c
|
|
||||||
+++ b/drivers/tty/vt/keyboard.c
|
|
||||||
@@ -28,6 +28,7 @@
|
|
||||||
* 21-08-02: Converted to input API, major cleanup. (Vojtech Pavlik)
|
|
||||||
*/
|
|
||||||
|
|
||||||
+#include <linux/bootsplash.h>
|
|
||||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
|
||||||
|
|
||||||
#include <linux/consolemap.h>
|
|
||||||
@@ -1353,6 +1355,28 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw)
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
+ /* Trap keys when bootsplash is shown */
|
|
||||||
+ if (bootsplash_would_render_now()) {
|
|
||||||
+ /* Deactivate bootsplash on ESC or Alt+Fxx VT switch */
|
|
||||||
+ if (keycode >= KEY_F1 && keycode <= KEY_F12) {
|
|
||||||
+ bootsplash_disable();
|
|
||||||
+
|
|
||||||
+ /*
|
|
||||||
+ * No return here since we want to actually
|
|
||||||
+ * perform the VT switch.
|
|
||||||
+ */
|
|
||||||
+ } else {
|
|
||||||
+ if (keycode == KEY_ESC)
|
|
||||||
+ bootsplash_disable();
|
|
||||||
+
|
|
||||||
+ /*
|
|
||||||
+ * Just drop any other keys.
|
|
||||||
+ * Their effect would be hidden by the splash.
|
|
||||||
+ */
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
if (kbd->kbdmode == VC_MEDIUMRAW) {
|
|
||||||
/*
|
|
||||||
* This is extended medium raw mode, with keys above 127
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c
|
|
||||||
index 3ffc1ce29023..bc6a24c9dfa8 100644
|
|
||||||
--- a/drivers/tty/sysrq.c
|
|
||||||
+++ b/drivers/tty/sysrq.c
|
|
||||||
@@ -49,6 +49,7 @@
|
|
||||||
#include <linux/syscalls.h>
|
|
||||||
#include <linux/of.h>
|
|
||||||
#include <linux/rcupdate.h>
|
|
||||||
+#include <linux/bootsplash.h>
|
|
||||||
|
|
||||||
#include <asm/ptrace.h>
|
|
||||||
#include <asm/irq_regs.h>
|
|
||||||
@@ -104,6 +105,8 @@ static void sysrq_handle_SAK(int key)
|
|
||||||
{
|
|
||||||
struct work_struct *SAK_work = &vc_cons[fg_console].SAK_work;
|
|
||||||
schedule_work(SAK_work);
|
|
||||||
+
|
|
||||||
+ bootsplash_disable();
|
|
||||||
}
|
|
||||||
static struct sysrq_key_op sysrq_SAK_op = {
|
|
||||||
.handler = sysrq_handle_SAK,
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
|
|
||||||
index 9a39a6fcfe98..8a9c67e1c5d8 100644
|
|
||||||
--- a/drivers/video/fbdev/core/fbcon.c
|
|
||||||
+++ b/drivers/video/fbdev/core/fbcon.c
|
|
||||||
@@ -1343,6 +1343,16 @@ static void fbcon_cursor(struct vc_data *vc, int mode)
|
|
||||||
int y;
|
|
||||||
int c = scr_readw((u16 *) vc->vc_pos);
|
|
||||||
|
|
||||||
+ /*
|
|
||||||
+ * Disable the splash here so we don't have to hook into
|
|
||||||
+ * vt_console_print() in drivers/tty/vt/vt.c
|
|
||||||
+ *
|
|
||||||
+ * We'd disable the splash just before the call to
|
|
||||||
+ * hide_cursor() anyway, so this spot is just fine.
|
|
||||||
+ */
|
|
||||||
+ if (oops_in_progress)
|
|
||||||
+ bootsplash_disable();
|
|
||||||
+
|
|
||||||
ops->cur_blink_jiffies = msecs_to_jiffies(vc->vc_cur_blink_ms);
|
|
||||||
|
|
||||||
if (fbcon_is_inactive(vc, info) || vc->vc_deccm != 1)
|
|
||||||
@@ -1,308 +0,0 @@
|
|||||||
diff --git a/Documentation/ABI/testing/sysfs-platform-bootsplash b/Documentation/ABI/testing/sysfs-platform-bootsplash
|
|
||||||
new file mode 100644
|
|
||||||
index 000000000000..742c7b035ded
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/Documentation/ABI/testing/sysfs-platform-bootsplash
|
|
||||||
@@ -0,0 +1,11 @@
|
|
||||||
+What: /sys/devices/platform/bootsplash.0/enabled
|
|
||||||
+Date: Oct 2017
|
|
||||||
+KernelVersion: 4.14
|
|
||||||
+Contact: Max Staudt <mstaudt@suse.de>
|
|
||||||
+Description:
|
|
||||||
+ Can be set and read.
|
|
||||||
+
|
|
||||||
+ 0: Splash is disabled.
|
|
||||||
+ 1: Splash is shown whenever fbcon would show a text console
|
|
||||||
+ (i.e. no graphical application is running), and a splash
|
|
||||||
+ file is loaded.
|
|
||||||
diff --git a/Documentation/bootsplash.rst b/Documentation/bootsplash.rst
|
|
||||||
new file mode 100644
|
|
||||||
index 000000000000..611f0c558925
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/Documentation/bootsplash.rst
|
|
||||||
@@ -0,0 +1,285 @@
|
|
||||||
+====================
|
|
||||||
+The Linux bootsplash
|
|
||||||
+====================
|
|
||||||
+
|
|
||||||
+:Date: November, 2017
|
|
||||||
+:Author: Max Staudt <mstaudt@suse.de>
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+The Linux bootsplash is a graphical replacement for the '``quiet``' boot
|
|
||||||
+option, typically showing a logo and a spinner animation as the system starts.
|
|
||||||
+
|
|
||||||
+Currently, it is a part of the Framebuffer Console support, and can be found
|
|
||||||
+as ``CONFIG_BOOTSPLASH`` in the kernel configuration. This means that as long
|
|
||||||
+as it is enabled, it hijacks fbcon's output and draws a splash screen instead.
|
|
||||||
+
|
|
||||||
+Purely compiling in the bootsplash will not render it functional - to actually
|
|
||||||
+render a splash, you will also need a splash theme file. See the example
|
|
||||||
+utility and script in ``tools/bootsplash`` for a live demo.
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+Motivation
|
|
||||||
+==========
|
|
||||||
+
|
|
||||||
+- The '``quiet``' boot option only suppresses most messages during boot, but
|
|
||||||
+ errors are still shown.
|
|
||||||
+
|
|
||||||
+- A user space implementation can only show a logo once user space has been
|
|
||||||
+ initialized far enough to allow this. A kernel splash can display a splash
|
|
||||||
+ immediately as soon as fbcon can be displayed.
|
|
||||||
+
|
|
||||||
+- Implementing a splash screen in user space (e.g. Plymouth) is problematic
|
|
||||||
+ due to resource conflicts.
|
|
||||||
+
|
|
||||||
+ For example, if Plymouth is keeping ``/dev/fb0`` (provided via vesafb/efifb)
|
|
||||||
+ open, then most DRM drivers can't replace it because the address space is
|
|
||||||
+ still busy - thus leading to a VRAM reservation error.
|
|
||||||
+
|
|
||||||
+ See: https://bugzilla.opensuse.org/show_bug.cgi?id=980750
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+Command line arguments
|
|
||||||
+======================
|
|
||||||
+
|
|
||||||
+``bootsplash.bootfile``
|
|
||||||
+ Which file in the initramfs to load.
|
|
||||||
+
|
|
||||||
+ The splash theme is loaded via request_firmware(), thus to load
|
|
||||||
+ ``/lib/firmware/bootsplash/mytheme`` pass the command line:
|
|
||||||
+
|
|
||||||
+ ``bootsplash.bootfile=bootsplash/mytheme``
|
|
||||||
+
|
|
||||||
+ Note: The splash file *has to be* in the initramfs, as it needs to be
|
|
||||||
+ available when the splash is initialized early on.
|
|
||||||
+
|
|
||||||
+ Default: none, i.e. a non-functional splash, falling back to showing text.
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+sysfs run-time configuration
|
|
||||||
+============================
|
|
||||||
+
|
|
||||||
+``/sys/devices/platform/bootsplash.0/enabled``
|
|
||||||
+ Enable/disable the bootsplash.
|
|
||||||
+ The system boots with this set to 1, but will not show a splash unless
|
|
||||||
+ a splash theme file is also loaded.
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+Kconfig
|
|
||||||
+=======
|
|
||||||
+
|
|
||||||
+``BOOTSPLASH``
|
|
||||||
+ Whether to compile in bootsplash support
|
|
||||||
+ (depends on fbcon compiled in, i.e. ``FRAMEBUFFER_CONSOLE=y``)
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+Bootsplash file format
|
|
||||||
+======================
|
|
||||||
+
|
|
||||||
+A file specified in the kernel configuration as ``CONFIG_BOOTSPLASH_FILE``
|
|
||||||
+or specified on the command line as ``bootsplash.bootfile`` will be loaded
|
|
||||||
+and displayed as soon as fbcon is initialized.
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+Main blocks
|
|
||||||
+-----------
|
|
||||||
+
|
|
||||||
+There are 3 main blocks in each file:
|
|
||||||
+
|
|
||||||
+ - one File header
|
|
||||||
+ - n Picture headers
|
|
||||||
+ - m (Blob header + payload) blocks
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+Structures
|
|
||||||
+----------
|
|
||||||
+
|
|
||||||
+The on-disk structures are defined in
|
|
||||||
+``drivers/video/fbdev/core/bootsplash_file.h`` and represent these blocks:
|
|
||||||
+
|
|
||||||
+ - ``struct splash_file_header``
|
|
||||||
+
|
|
||||||
+ Represents the file header, with splash-wide information including:
|
|
||||||
+
|
|
||||||
+ - The magic string "``Linux bootsplash``" on big-endian platforms
|
|
||||||
+ (the reverse on little endian)
|
|
||||||
+ - The file format version (for incompatible updates, hopefully never)
|
|
||||||
+ - The background color
|
|
||||||
+ - Number of picture and blob blocks
|
|
||||||
+ - Animation speed (we only allow one delay for all animations)
|
|
||||||
+
|
|
||||||
+ The file header is followed by the first picture header.
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+ - ``struct splash_picture_header``
|
|
||||||
+
|
|
||||||
+ Represents an object (picture) drawn on screen, including its immutable
|
|
||||||
+ properties:
|
|
||||||
+ - Width, height
|
|
||||||
+ - Positioning relative to screen corners or in the center
|
|
||||||
+ - Animation, if any
|
|
||||||
+ - Animation type
|
|
||||||
+ - Number of blobs
|
|
||||||
+
|
|
||||||
+ The picture header is followed by another picture header, up until n
|
|
||||||
+ picture headers (as defined in the file header) have been read. Then,
|
|
||||||
+ the (blob header, payload) pairs follow.
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+ - ``struct splash_blob_header``
|
|
||||||
+ (followed by payload)
|
|
||||||
+
|
|
||||||
+ Represents one raw data stream. So far, only picture data is defined.
|
|
||||||
+
|
|
||||||
+ The blob header is followed by a payload, then padding to n*16 bytes,
|
|
||||||
+ then (if further blobs are defined in the file header) a further blob
|
|
||||||
+ header.
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+Alignment
|
|
||||||
+---------
|
|
||||||
+
|
|
||||||
+The bootsplash file is designed to be loaded into memory as-is.
|
|
||||||
+
|
|
||||||
+All structures are a multiple of 16 bytes long, all elements therein are
|
|
||||||
+aligned to multiples of their length, and the payloads are always padded
|
|
||||||
+up to multiples of 16 bytes. This is to allow aligned accesses in all
|
|
||||||
+cases while still simply mapping the structures over an in-memory copy of
|
|
||||||
+the bootsplash file.
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+Further information
|
|
||||||
+-------------------
|
|
||||||
+
|
|
||||||
+Please see ``drivers/video/fbdev/core/bootsplash_file.h`` for further
|
|
||||||
+details and possible values in the file.
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+Hooks - how the bootsplash is integrated
|
|
||||||
+========================================
|
|
||||||
+
|
|
||||||
+``drivers/video/fbdev/core/fbcon.c``
|
|
||||||
+ ``fbcon_init()`` calls ``bootsplash_init()``, which loads the default
|
|
||||||
+ bootsplash file or the one specified on the kernel command line.
|
|
||||||
+
|
|
||||||
+ ``fbcon_switch()`` draws the bootsplash when it's active, and is also
|
|
||||||
+ one of the callers of ``set_blitting_type()``.
|
|
||||||
+
|
|
||||||
+ ``set_blitting_type()`` calls ``fbcon_set_dummyops()`` when the
|
|
||||||
+ bootsplash is active, overriding the text rendering functions.
|
|
||||||
+
|
|
||||||
+ ``fbcon_cursor()`` will call ``bootsplash_disable()`` when an oops is
|
|
||||||
+ being printed in order to make a kernel panic visible.
|
|
||||||
+
|
|
||||||
+``drivers/video/fbdev/core/dummyblit.c``
|
|
||||||
+ This contains the dummy text rendering functions used to suppress text
|
|
||||||
+ output while the bootsplash is shown.
|
|
||||||
+
|
|
||||||
+``drivers/tty/vt/keyboard.c``
|
|
||||||
+ ``kbd_keycode()`` can call ``bootsplash_disable()`` when the user
|
|
||||||
+ presses ESC or F1-F12 (changing VT). This is to provide a built-in way
|
|
||||||
+ of disabling the splash manually at any time.
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+FAQ: Frequently Asked Questions
|
|
||||||
+===============================
|
|
||||||
+
|
|
||||||
+I want to see the log! How do I show the log?
|
|
||||||
+---------------------------------------------
|
|
||||||
+
|
|
||||||
+Press ESC while the splash is shown, or remove the ``bootsplash.bootfile``
|
|
||||||
+parameter from the kernel cmdline. Without that parameter, the bootsplash
|
|
||||||
+will boot disabled.
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+Why use FB instead of modern DRM/KMS?
|
|
||||||
+-------------------------------------
|
|
||||||
+
|
|
||||||
+This is a semantic problem:
|
|
||||||
+ - What memory to draw the splash to?
|
|
||||||
+ - And what mode will the screen be set to?
|
|
||||||
+
|
|
||||||
+Using the fbdev emulation solves these issues.
|
|
||||||
+
|
|
||||||
+Let's start from a bare KMS system, without fbcon, and without fbdev
|
|
||||||
+emulation. In this case, as long as userspace doesn't open the KMS
|
|
||||||
+device, the state of the screen is undefined. No framebuffer is
|
|
||||||
+allocated in video RAM, and no particular mode is set.
|
|
||||||
+
|
|
||||||
+In this case, we'd have to allocate a framebuffer to show the splash,
|
|
||||||
+and set our mode ourselves. This either wastes a screenful of video RAM
|
|
||||||
+if the splash is to co-exist with the userspace program's own allocated
|
|
||||||
+framebuffer, or there is a flicker as we deactivate and delete the
|
|
||||||
+bootsplash's framebuffer and hand control over to userspace. Since we
|
|
||||||
+may set a different mode than userspace, we'd also have flicker due
|
|
||||||
+to mode switching.
|
|
||||||
+
|
|
||||||
+This logic is already contained in every KMS driver that performs fbdev
|
|
||||||
+emulation. So we might as well use that. And the correct API to do so is
|
|
||||||
+fbdev. Plus, we get compatibility with old, pure fbdev drivers for free.
|
|
||||||
+With the fbdev emulation, there is *always* a well-defined framebuffer
|
|
||||||
+to draw on. And the selection of mode has already been done by the
|
|
||||||
+graphics driver, so we don't need to reinvent that wheel, either.
|
|
||||||
+Finally, if userspace decides to use /dev/fbX, we don't have to worry
|
|
||||||
+about wasting video RAM, either.
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+Why is the bootsplash integrated in fbcon?
|
|
||||||
+------------------------------------------
|
|
||||||
+
|
|
||||||
+Right now, the bootsplash is drawn from within fbcon, as this allows us
|
|
||||||
+to easily know *when* to draw - i.e. when we're safe from fbcon and
|
|
||||||
+userspace drawing all over our beautiful splash logo.
|
|
||||||
+
|
|
||||||
+Separating them is not easy - see the to-do list below.
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+TO DO list for future development
|
|
||||||
+=================================
|
|
||||||
+
|
|
||||||
+Second enable/disable switch for the system
|
|
||||||
+-------------------------------------------
|
|
||||||
+
|
|
||||||
+It may be helpful to differentiate between the system and the user
|
|
||||||
+switching off the bootsplash. Thus, the system may make it disappear and
|
|
||||||
+reappear e.g. for a password prompt, yet once the user has pressed ESC,
|
|
||||||
+it could stay gone.
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+Fix buggy DRM/KMS drivers
|
|
||||||
+-------------------------
|
|
||||||
+
|
|
||||||
+Currently, the splash code manually checks for fbdev emulation provided by
|
|
||||||
+the ast, cirrus, and mgag200 DRM/KMS drivers.
|
|
||||||
+These drivers use a manual mechanism similar to deferred I/O for their FB
|
|
||||||
+emulation, and thus need to be manually flushed onto the screen in the same
|
|
||||||
+way.
|
|
||||||
+
|
|
||||||
+This may be improved upon in several ways:
|
|
||||||
+
|
|
||||||
+1. Changing these drivers to expose the fbdev BO's memory directly, like
|
|
||||||
+ bochsdrmfb does.
|
|
||||||
+2. Creating a new fb_ops->fb_flush() API to allow the kernel to flush the
|
|
||||||
+ framebuffer once the bootsplash has been drawn into it.
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+Separating from fbcon
|
|
||||||
+---------------------
|
|
||||||
+
|
|
||||||
+Separating these two components would yield independence from fbcon being
|
|
||||||
+compiled into the kernel, and thus lowering code size in embedded
|
|
||||||
+applications.
|
|
||||||
+
|
|
||||||
+To do this cleanly will involve a clean separation of users of an FB device
|
|
||||||
+within the kernel, i.e. fbcon, bootsplash, and userspace. Right now, the
|
|
||||||
+legacy fbcon code and VT code co-operate to switch between fbcon and
|
|
||||||
+userspace (by setting the VT into KD_GRAPHICS mode). Installing a muxer
|
|
||||||
+between these components ensues refactoring of old code and checking for
|
|
||||||
+correct locking.
|
|
||||||
@@ -1,129 +0,0 @@
|
|||||||
diff --git a/Documentation/ABI/testing/sysfs-platform-bootsplash b/Documentation/ABI/testing/sysfs-platform-bootsplash
|
|
||||||
index 742c7b035ded..f8f4b259220e 100644
|
|
||||||
--- a/Documentation/ABI/testing/sysfs-platform-bootsplash
|
|
||||||
+++ b/Documentation/ABI/testing/sysfs-platform-bootsplash
|
|
||||||
@@ -9,3 +9,35 @@ Description:
|
|
||||||
1: Splash is shown whenever fbcon would show a text console
|
|
||||||
(i.e. no graphical application is running), and a splash
|
|
||||||
file is loaded.
|
|
||||||
+
|
|
||||||
+What: /sys/devices/platform/bootsplash.0/drop_splash
|
|
||||||
+Date: Oct 2017
|
|
||||||
+KernelVersion: 4.14
|
|
||||||
+Contact: Max Staudt <mstaudt@suse.de>
|
|
||||||
+Description:
|
|
||||||
+ Can only be set.
|
|
||||||
+
|
|
||||||
+ Any value written will cause the current splash theme file
|
|
||||||
+ to be unloaded and the text console to be redrawn.
|
|
||||||
+
|
|
||||||
+What: /sys/devices/platform/bootsplash.0/load_file
|
|
||||||
+Date: Oct 2017
|
|
||||||
+KernelVersion: 4.14
|
|
||||||
+Contact: Max Staudt <mstaudt@suse.de>
|
|
||||||
+Description:
|
|
||||||
+ Can only be set.
|
|
||||||
+
|
|
||||||
+ Any value written will cause the splash to be disabled and
|
|
||||||
+ internal memory structures to be freed.
|
|
||||||
+
|
|
||||||
+ A firmware path written will cause a new theme file to be
|
|
||||||
+ loaded and the current bootsplash to be replaced.
|
|
||||||
+ The current enabled/disabled status is not touched.
|
|
||||||
+ If the splash is already active, it will be redrawn.
|
|
||||||
+
|
|
||||||
+ The path has to be a path in /lib/firmware since
|
|
||||||
+ request_firmware() is used to fetch the data.
|
|
||||||
+
|
|
||||||
+ When setting the splash from the shell, echo -n has to be
|
|
||||||
+ used as any trailing '\n' newline will be interpreted as
|
|
||||||
+ part of the path.
|
|
||||||
diff --git a/Documentation/bootsplash.rst b/Documentation/bootsplash.rst
|
|
||||||
index 611f0c558925..b35aba5093e8 100644
|
|
||||||
--- a/Documentation/bootsplash.rst
|
|
||||||
+++ b/Documentation/bootsplash.rst
|
|
||||||
@@ -67,6 +67,14 @@ sysfs run-time configuration
|
|
||||||
a splash theme file is also loaded.
|
|
||||||
|
|
||||||
|
|
||||||
+``/sys/devices/platform/bootsplash.0/drop_splash``
|
|
||||||
+ Unload splash data and free memory.
|
|
||||||
+
|
|
||||||
+``/sys/devices/platform/bootsplash.0/load_file``
|
|
||||||
+ Load a splash file from ``/lib/firmware/``.
|
|
||||||
+ Note that trailing newlines will be interpreted as part of the file name.
|
|
||||||
+
|
|
||||||
+
|
|
||||||
|
|
||||||
Kconfig
|
|
||||||
=======
|
|
||||||
diff --git a/drivers/video/fbdev/core/bootsplash.c b/drivers/video/fbdev/core/bootsplash.c
|
|
||||||
index 13fcaabbc2ca..16cb0493629d 100644
|
|
||||||
--- a/drivers/video/fbdev/core/bootsplash.c
|
|
||||||
+++ b/drivers/video/fbdev/core/bootsplash.c
|
|
||||||
@@ -251,11 +251,65 @@ static ssize_t splash_store_enabled(struct device *device,
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
+static ssize_t splash_store_drop_splash(struct device *device,
|
|
||||||
+ struct device_attribute *attr,
|
|
||||||
+ const char *buf, size_t count)
|
|
||||||
+{
|
|
||||||
+ struct splash_file_priv *fp;
|
|
||||||
+
|
|
||||||
+ if (!buf || !count || !splash_state.file)
|
|
||||||
+ return count;
|
|
||||||
+
|
|
||||||
+ mutex_lock(&splash_state.data_lock);
|
|
||||||
+ fp = splash_state.file;
|
|
||||||
+ splash_state.file = NULL;
|
|
||||||
+ mutex_unlock(&splash_state.data_lock);
|
|
||||||
+
|
|
||||||
+ /* Redraw the text console */
|
|
||||||
+ schedule_work(&splash_state.work_redraw_vc);
|
|
||||||
+
|
|
||||||
+ bootsplash_free_file(fp);
|
|
||||||
+
|
|
||||||
+ return count;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static ssize_t splash_store_load_file(struct device *device,
|
|
||||||
+ struct device_attribute *attr,
|
|
||||||
+ const char *buf, size_t count)
|
|
||||||
+{
|
|
||||||
+ struct splash_file_priv *fp, *fp_old;
|
|
||||||
+
|
|
||||||
+ if (!count)
|
|
||||||
+ return 0;
|
|
||||||
+
|
|
||||||
+ fp = bootsplash_load_firmware(&splash_state.splash_device->dev,
|
|
||||||
+ buf);
|
|
||||||
+
|
|
||||||
+ if (!fp)
|
|
||||||
+ return -ENXIO;
|
|
||||||
+
|
|
||||||
+ mutex_lock(&splash_state.data_lock);
|
|
||||||
+ fp_old = splash_state.file;
|
|
||||||
+ splash_state.splash_fb = NULL;
|
|
||||||
+ splash_state.file = fp;
|
|
||||||
+ mutex_unlock(&splash_state.data_lock);
|
|
||||||
+
|
|
||||||
+ /* Update the splash or text console */
|
|
||||||
+ schedule_work(&splash_state.work_redraw_vc);
|
|
||||||
+
|
|
||||||
+ bootsplash_free_file(fp_old);
|
|
||||||
+ return count;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static DEVICE_ATTR(enabled, 0644, splash_show_enabled, splash_store_enabled);
|
|
||||||
+static DEVICE_ATTR(drop_splash, 0200, NULL, splash_store_drop_splash);
|
|
||||||
+static DEVICE_ATTR(load_file, 0200, NULL, splash_store_load_file);
|
|
||||||
|
|
||||||
|
|
||||||
static struct attribute *splash_dev_attrs[] = {
|
|
||||||
&dev_attr_enabled.attr,
|
|
||||||
+ &dev_attr_drop_splash.attr,
|
|
||||||
+ &dev_attr_load_file.attr,
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
@@ -1,499 +0,0 @@
|
|||||||
diff --git a/tools/bootsplash/.gitignore b/tools/bootsplash/.gitignore
|
|
||||||
new file mode 100644
|
|
||||||
index 000000000000..091b99a17567
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/tools/bootsplash/.gitignore
|
|
||||||
@@ -0,0 +1 @@
|
|
||||||
+bootsplash-packer
|
|
||||||
diff --git a/tools/bootsplash/Makefile b/tools/bootsplash/Makefile
|
|
||||||
new file mode 100644
|
|
||||||
index 000000000000..0ad8e8a84942
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/tools/bootsplash/Makefile
|
|
||||||
@@ -0,0 +1,9 @@
|
|
||||||
+CC := $(CROSS_COMPILE)gcc
|
|
||||||
+CFLAGS := -I../../usr/include
|
|
||||||
+
|
|
||||||
+PROGS := bootsplash-packer
|
|
||||||
+
|
|
||||||
+all: $(PROGS)
|
|
||||||
+
|
|
||||||
+clean:
|
|
||||||
+ rm -fr $(PROGS)
|
|
||||||
diff --git a/tools/bootsplash/bootsplash-packer.c b/tools/bootsplash/bootsplash-packer.c
|
|
||||||
new file mode 100644
|
|
||||||
index 000000000000..ffb6a8b69885
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/tools/bootsplash/bootsplash-packer.c
|
|
||||||
@@ -0,0 +1,471 @@
|
|
||||||
+/*
|
|
||||||
+ * Kernel based bootsplash.
|
|
||||||
+ *
|
|
||||||
+ * (Splash file packer tool)
|
|
||||||
+ *
|
|
||||||
+ * Authors:
|
|
||||||
+ * Max Staudt <mstaudt@suse.de>
|
|
||||||
+ *
|
|
||||||
+ * SPDX-License-Identifier: GPL-2.0
|
|
||||||
+ */
|
|
||||||
+
|
|
||||||
+#include <endian.h>
|
|
||||||
+#include <getopt.h>
|
|
||||||
+#include <stdint.h>
|
|
||||||
+#include <stdio.h>
|
|
||||||
+#include <stdlib.h>
|
|
||||||
+#include <string.h>
|
|
||||||
+
|
|
||||||
+#include <linux/bootsplash_file.h>
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+static void print_help(char *progname)
|
|
||||||
+{
|
|
||||||
+ printf("Usage: %s [OPTIONS] outfile\n", progname);
|
|
||||||
+ printf("\n"
|
|
||||||
+ "Options, executed in order given:\n"
|
|
||||||
+ " -h, --help Print this help message\n"
|
|
||||||
+ "\n"
|
|
||||||
+ " --bg_red <u8> Background color (red part)\n"
|
|
||||||
+ " --bg_green <u8> Background color (green part)\n"
|
|
||||||
+ " --bg_blue <u8> Background color (blue part)\n"
|
|
||||||
+ " --bg_reserved <u8> (do not use)\n"
|
|
||||||
+ " --frame_ms <u16> Minimum milliseconds between animation steps\n"
|
|
||||||
+ "\n"
|
|
||||||
+ " --picture Start describing the next picture\n"
|
|
||||||
+ " --pic_width <u16> Picture width in pixels\n"
|
|
||||||
+ " --pic_height <u16> Picture height in pixels\n"
|
|
||||||
+ " --pic_position <u8> Coarse picture placement:\n"
|
|
||||||
+ " 0x00 - Top left\n"
|
|
||||||
+ " 0x01 - Top\n"
|
|
||||||
+ " 0x02 - Top right\n"
|
|
||||||
+ " 0x03 - Right\n"
|
|
||||||
+ " 0x04 - Bottom right\n"
|
|
||||||
+ " 0x05 - Bottom\n"
|
|
||||||
+ " 0x06 - Bottom left\n"
|
|
||||||
+ " 0x07 - Left\n"
|
|
||||||
+ "\n"
|
|
||||||
+ " Flags:\n"
|
|
||||||
+ " 0x10 - Calculate offset from corner towards center,\n"
|
|
||||||
+ " rather than from center towards corner\n"
|
|
||||||
+ " --pic_position_offset <u16> Distance from base position in pixels\n"
|
|
||||||
+ " --pic_anim_type <u8> Animation type:\n"
|
|
||||||
+ " 0 - None\n"
|
|
||||||
+ " 1 - Forward loop\n"
|
|
||||||
+ " --pic_anim_loop <u8> Loop point for animation\n"
|
|
||||||
+ "\n"
|
|
||||||
+ " --blob <filename> Include next data stream\n"
|
|
||||||
+ " --blob_type <u16> Type of data\n"
|
|
||||||
+ " --blob_picture_id <u8> Picture to associate this blob with, starting at 0\n"
|
|
||||||
+ " (default: number of last --picture)\n"
|
|
||||||
+ "\n");
|
|
||||||
+ printf("This tool will write %s files.\n\n",
|
|
||||||
+#if __BYTE_ORDER == __BIG_ENDIAN
|
|
||||||
+ "Big Endian (BE)");
|
|
||||||
+#elif __BYTE_ORDER == __LITTLE_ENDIAN
|
|
||||||
+ "Little Endian (LE)");
|
|
||||||
+#else
|
|
||||||
+#error
|
|
||||||
+#endif
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+struct blob_entry {
|
|
||||||
+ struct blob_entry *next;
|
|
||||||
+
|
|
||||||
+ char *fn;
|
|
||||||
+
|
|
||||||
+ struct splash_blob_header header;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+static void dump_file_header(struct splash_file_header *h)
|
|
||||||
+{
|
|
||||||
+ printf(" --- File header ---\n");
|
|
||||||
+ printf("\n");
|
|
||||||
+ printf(" version: %5u\n", h->version);
|
|
||||||
+ printf("\n");
|
|
||||||
+ printf(" bg_red: %5u\n", h->bg_red);
|
|
||||||
+ printf(" bg_green: %5u\n", h->bg_green);
|
|
||||||
+ printf(" bg_blue: %5u\n", h->bg_blue);
|
|
||||||
+ printf(" bg_reserved: %5u\n", h->bg_reserved);
|
|
||||||
+ printf("\n");
|
|
||||||
+ printf(" num_blobs: %5u\n", h->num_blobs);
|
|
||||||
+ printf(" num_pics: %5u\n", h->num_pics);
|
|
||||||
+ printf("\n");
|
|
||||||
+ printf(" frame_ms: %5u\n", h->frame_ms);
|
|
||||||
+ printf("\n");
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void dump_pic_header(struct splash_pic_header *ph)
|
|
||||||
+{
|
|
||||||
+ printf(" --- Picture header ---\n");
|
|
||||||
+ printf("\n");
|
|
||||||
+ printf(" width: %5u\n", ph->width);
|
|
||||||
+ printf(" height: %5u\n", ph->height);
|
|
||||||
+ printf("\n");
|
|
||||||
+ printf(" num_blobs: %5u\n", ph->num_blobs);
|
|
||||||
+ printf("\n");
|
|
||||||
+ printf(" position: %0x3x\n", ph->position);
|
|
||||||
+ printf(" position_offset: %5u\n", ph->position_offset);
|
|
||||||
+ printf("\n");
|
|
||||||
+ printf(" anim_type: %5u\n", ph->anim_type);
|
|
||||||
+ printf(" anim_loop: %5u\n", ph->anim_loop);
|
|
||||||
+ printf("\n");
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void dump_blob(struct blob_entry *b)
|
|
||||||
+{
|
|
||||||
+ printf(" --- Blob header ---\n");
|
|
||||||
+ printf("\n");
|
|
||||||
+ printf(" length: %7u\n", b->header.length);
|
|
||||||
+ printf(" type: %7u\n", b->header.type);
|
|
||||||
+ printf("\n");
|
|
||||||
+ printf(" picture_id: %7u\n", b->header.picture_id);
|
|
||||||
+ printf("\n");
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+#define OPT_MAX(var, max) \
|
|
||||||
+ do { \
|
|
||||||
+ if ((var) > max) { \
|
|
||||||
+ fprintf(stderr, "--%s: Invalid value\n", \
|
|
||||||
+ long_options[option_index].name); \
|
|
||||||
+ break; \
|
|
||||||
+ } \
|
|
||||||
+ } while (0)
|
|
||||||
+
|
|
||||||
+static struct option long_options[] = {
|
|
||||||
+ {"help", 0, 0, 'h'},
|
|
||||||
+ {"bg_red", 1, 0, 10001},
|
|
||||||
+ {"bg_green", 1, 0, 10002},
|
|
||||||
+ {"bg_blue", 1, 0, 10003},
|
|
||||||
+ {"bg_reserved", 1, 0, 10004},
|
|
||||||
+ {"frame_ms", 1, 0, 10005},
|
|
||||||
+ {"picture", 0, 0, 20000},
|
|
||||||
+ {"pic_width", 1, 0, 20001},
|
|
||||||
+ {"pic_height", 1, 0, 20002},
|
|
||||||
+ {"pic_position", 1, 0, 20003},
|
|
||||||
+ {"pic_position_offset", 1, 0, 20004},
|
|
||||||
+ {"pic_anim_type", 1, 0, 20005},
|
|
||||||
+ {"pic_anim_loop", 1, 0, 20006},
|
|
||||||
+ {"blob", 1, 0, 30000},
|
|
||||||
+ {"blob_type", 1, 0, 30001},
|
|
||||||
+ {"blob_picture_id", 1, 0, 30002},
|
|
||||||
+ {NULL, 0, NULL, 0}
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+int main(int argc, char **argv)
|
|
||||||
+{
|
|
||||||
+ FILE *of;
|
|
||||||
+ char *ofn;
|
|
||||||
+ int c;
|
|
||||||
+ int option_index = 0;
|
|
||||||
+
|
|
||||||
+ unsigned long ul;
|
|
||||||
+ struct splash_file_header fh = {};
|
|
||||||
+ struct splash_pic_header ph[255];
|
|
||||||
+ struct blob_entry *blob_first = NULL;
|
|
||||||
+ struct blob_entry *blob_last = NULL;
|
|
||||||
+ struct blob_entry *blob_cur = NULL;
|
|
||||||
+
|
|
||||||
+ if (argc < 2) {
|
|
||||||
+ print_help(argv[0]);
|
|
||||||
+ return EXIT_FAILURE;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+ /* Parse and and execute user commands */
|
|
||||||
+ while ((c = getopt_long(argc, argv, "h",
|
|
||||||
+ long_options, &option_index)) != -1) {
|
|
||||||
+ switch (c) {
|
|
||||||
+ case 10001: /* bg_red */
|
|
||||||
+ ul = strtoul(optarg, NULL, 0);
|
|
||||||
+ OPT_MAX(ul, 255);
|
|
||||||
+ fh.bg_red = ul;
|
|
||||||
+ break;
|
|
||||||
+ case 10002: /* bg_green */
|
|
||||||
+ ul = strtoul(optarg, NULL, 0);
|
|
||||||
+ OPT_MAX(ul, 255);
|
|
||||||
+ fh.bg_green = ul;
|
|
||||||
+ break;
|
|
||||||
+ case 10003: /* bg_blue */
|
|
||||||
+ ul = strtoul(optarg, NULL, 0);
|
|
||||||
+ OPT_MAX(ul, 255);
|
|
||||||
+ fh.bg_blue = ul;
|
|
||||||
+ break;
|
|
||||||
+ case 10004: /* bg_reserved */
|
|
||||||
+ ul = strtoul(optarg, NULL, 0);
|
|
||||||
+ OPT_MAX(ul, 255);
|
|
||||||
+ fh.bg_reserved = ul;
|
|
||||||
+ break;
|
|
||||||
+ case 10005: /* frame_ms */
|
|
||||||
+ ul = strtoul(optarg, NULL, 0);
|
|
||||||
+ OPT_MAX(ul, 65535);
|
|
||||||
+ fh.frame_ms = ul;
|
|
||||||
+ break;
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+ case 20000: /* picture */
|
|
||||||
+ if (fh.num_pics >= 255) {
|
|
||||||
+ fprintf(stderr, "--%s: Picture array full\n",
|
|
||||||
+ long_options[option_index].name);
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ fh.num_pics++;
|
|
||||||
+ break;
|
|
||||||
+
|
|
||||||
+ case 20001: /* pic_width */
|
|
||||||
+ ul = strtoul(optarg, NULL, 0);
|
|
||||||
+ OPT_MAX(ul, 65535);
|
|
||||||
+ ph[fh.num_pics - 1].width = ul;
|
|
||||||
+ break;
|
|
||||||
+
|
|
||||||
+ case 20002: /* pic_height */
|
|
||||||
+ ul = strtoul(optarg, NULL, 0);
|
|
||||||
+ OPT_MAX(ul, 65535);
|
|
||||||
+ ph[fh.num_pics - 1].height = ul;
|
|
||||||
+ break;
|
|
||||||
+
|
|
||||||
+ case 20003: /* pic_position */
|
|
||||||
+ ul = strtoul(optarg, NULL, 0);
|
|
||||||
+ OPT_MAX(ul, 255);
|
|
||||||
+ ph[fh.num_pics - 1].position = ul;
|
|
||||||
+ break;
|
|
||||||
+
|
|
||||||
+ case 20004: /* pic_position_offset */
|
|
||||||
+ ul = strtoul(optarg, NULL, 0);
|
|
||||||
+ OPT_MAX(ul, 255);
|
|
||||||
+ ph[fh.num_pics - 1].position_offset = ul;
|
|
||||||
+ break;
|
|
||||||
+
|
|
||||||
+ case 20005: /* pic_anim_type */
|
|
||||||
+ ul = strtoul(optarg, NULL, 0);
|
|
||||||
+ OPT_MAX(ul, 255);
|
|
||||||
+ ph[fh.num_pics - 1].anim_type = ul;
|
|
||||||
+ break;
|
|
||||||
+
|
|
||||||
+ case 20006: /* pic_anim_loop */
|
|
||||||
+ ul = strtoul(optarg, NULL, 0);
|
|
||||||
+ OPT_MAX(ul, 255);
|
|
||||||
+ ph[fh.num_pics - 1].anim_loop = ul;
|
|
||||||
+ break;
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+ case 30000: /* blob */
|
|
||||||
+ if (fh.num_blobs >= 65535) {
|
|
||||||
+ fprintf(stderr, "--%s: Blob array full\n",
|
|
||||||
+ long_options[option_index].name);
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ blob_cur = calloc(1, sizeof(struct blob_entry));
|
|
||||||
+ if (!blob_cur) {
|
|
||||||
+ fprintf(stderr, "--%s: Out of memory\n",
|
|
||||||
+ long_options[option_index].name);
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ blob_cur->fn = optarg;
|
|
||||||
+ if (fh.num_pics)
|
|
||||||
+ blob_cur->header.picture_id = fh.num_pics - 1;
|
|
||||||
+
|
|
||||||
+ if (!blob_first)
|
|
||||||
+ blob_first = blob_cur;
|
|
||||||
+ if (blob_last)
|
|
||||||
+ blob_last->next = blob_cur;
|
|
||||||
+ blob_last = blob_cur;
|
|
||||||
+ fh.num_blobs++;
|
|
||||||
+ break;
|
|
||||||
+
|
|
||||||
+ case 30001: /* blob_type */
|
|
||||||
+ if (!blob_cur) {
|
|
||||||
+ fprintf(stderr, "--%s: No blob selected\n",
|
|
||||||
+ long_options[option_index].name);
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ ul = strtoul(optarg, NULL, 0);
|
|
||||||
+ OPT_MAX(ul, 255);
|
|
||||||
+ blob_cur->header.type = ul;
|
|
||||||
+ break;
|
|
||||||
+
|
|
||||||
+ case 30002: /* blob_picture_id */
|
|
||||||
+ if (!blob_cur) {
|
|
||||||
+ fprintf(stderr, "--%s: No blob selected\n",
|
|
||||||
+ long_options[option_index].name);
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ ul = strtoul(optarg, NULL, 0);
|
|
||||||
+ OPT_MAX(ul, 255);
|
|
||||||
+ blob_cur->header.picture_id = ul;
|
|
||||||
+ break;
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+ case 'h':
|
|
||||||
+ case '?':
|
|
||||||
+ default:
|
|
||||||
+ print_help(argv[0]);
|
|
||||||
+ goto EXIT;
|
|
||||||
+ } /* switch (c) */
|
|
||||||
+ } /* while ((c = getopt_long(...)) != -1) */
|
|
||||||
+
|
|
||||||
+ /* Consume and drop lone arguments */
|
|
||||||
+ while (optind < argc) {
|
|
||||||
+ ofn = argv[optind];
|
|
||||||
+ optind++;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+ /* Read file lengths */
|
|
||||||
+ for (blob_cur = blob_first; blob_cur; blob_cur = blob_cur->next) {
|
|
||||||
+ FILE *f;
|
|
||||||
+ long pos;
|
|
||||||
+ int i;
|
|
||||||
+
|
|
||||||
+ if (!blob_cur->fn)
|
|
||||||
+ continue;
|
|
||||||
+
|
|
||||||
+ f = fopen(blob_cur->fn, "rb");
|
|
||||||
+ if (!f)
|
|
||||||
+ goto ERR_FILE_LEN;
|
|
||||||
+
|
|
||||||
+ if (fseek(f, 0, SEEK_END))
|
|
||||||
+ goto ERR_FILE_LEN;
|
|
||||||
+
|
|
||||||
+ pos = ftell(f);
|
|
||||||
+ if (pos < 0 || pos > (1 << 30))
|
|
||||||
+ goto ERR_FILE_LEN;
|
|
||||||
+
|
|
||||||
+ blob_cur->header.length = pos;
|
|
||||||
+
|
|
||||||
+ fclose(f);
|
|
||||||
+ continue;
|
|
||||||
+
|
|
||||||
+ERR_FILE_LEN:
|
|
||||||
+ fprintf(stderr, "Error getting file length (or too long): %s\n",
|
|
||||||
+ blob_cur->fn);
|
|
||||||
+ if (f)
|
|
||||||
+ fclose(f);
|
|
||||||
+ continue;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+ /* Set magic headers */
|
|
||||||
+#if __BYTE_ORDER == __BIG_ENDIAN
|
|
||||||
+ memcpy(&fh.id[0], BOOTSPLASH_MAGIC_BE, 16);
|
|
||||||
+#elif __BYTE_ORDER == __LITTLE_ENDIAN
|
|
||||||
+ memcpy(&fh.id[0], BOOTSPLASH_MAGIC_LE, 16);
|
|
||||||
+#else
|
|
||||||
+#error
|
|
||||||
+#endif
|
|
||||||
+ fh.version = BOOTSPLASH_VERSION;
|
|
||||||
+
|
|
||||||
+ /* Set blob counts */
|
|
||||||
+ for (blob_cur = blob_first; blob_cur; blob_cur = blob_cur->next) {
|
|
||||||
+ if (blob_cur->header.picture_id < fh.num_pics)
|
|
||||||
+ ph[blob_cur->header.picture_id].num_blobs++;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+ /* Dump structs */
|
|
||||||
+ dump_file_header(&fh);
|
|
||||||
+
|
|
||||||
+ for (ul = 0; ul < fh.num_pics; ul++)
|
|
||||||
+ dump_pic_header(&ph[ul]);
|
|
||||||
+
|
|
||||||
+ for (blob_cur = blob_first; blob_cur; blob_cur = blob_cur->next)
|
|
||||||
+ dump_blob(blob_cur);
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+ /* Write to file */
|
|
||||||
+ printf("Writing splash to file: %s\n", ofn);
|
|
||||||
+ of = fopen(ofn, "wb");
|
|
||||||
+ if (!of)
|
|
||||||
+ goto ERR_WRITING;
|
|
||||||
+
|
|
||||||
+ if (fwrite(&fh, sizeof(struct splash_file_header), 1, of) != 1)
|
|
||||||
+ goto ERR_WRITING;
|
|
||||||
+
|
|
||||||
+ for (ul = 0; ul < fh.num_pics; ul++) {
|
|
||||||
+ if (fwrite(&ph[ul], sizeof(struct splash_pic_header), 1, of)
|
|
||||||
+ != 1)
|
|
||||||
+ goto ERR_WRITING;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ blob_cur = blob_first;
|
|
||||||
+ while (blob_cur) {
|
|
||||||
+ struct blob_entry *blob_old = blob_cur;
|
|
||||||
+ FILE *f;
|
|
||||||
+ char *buf[256];
|
|
||||||
+ uint32_t left;
|
|
||||||
+
|
|
||||||
+ if (fwrite(&blob_cur->header,
|
|
||||||
+ sizeof(struct splash_blob_header), 1, of) != 1)
|
|
||||||
+ goto ERR_WRITING;
|
|
||||||
+
|
|
||||||
+ if (!blob_cur->header.length || !blob_cur->fn)
|
|
||||||
+ continue;
|
|
||||||
+
|
|
||||||
+ f = fopen(blob_cur->fn, "rb");
|
|
||||||
+ if (!f)
|
|
||||||
+ goto ERR_FILE_COPY;
|
|
||||||
+
|
|
||||||
+ left = blob_cur->header.length;
|
|
||||||
+ while (left >= sizeof(buf)) {
|
|
||||||
+ if (fread(buf, sizeof(buf), 1, f) != 1)
|
|
||||||
+ goto ERR_FILE_COPY;
|
|
||||||
+ if (fwrite(buf, sizeof(buf), 1, of) != 1)
|
|
||||||
+ goto ERR_FILE_COPY;
|
|
||||||
+ left -= sizeof(buf);
|
|
||||||
+ }
|
|
||||||
+ if (left) {
|
|
||||||
+ if (fread(buf, left, 1, f) != 1)
|
|
||||||
+ goto ERR_FILE_COPY;
|
|
||||||
+ if (fwrite(buf, left, 1, of) != 1)
|
|
||||||
+ goto ERR_FILE_COPY;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ /* Pad data stream to 16 bytes */
|
|
||||||
+ if (left % 16) {
|
|
||||||
+ if (fwrite("\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0",
|
|
||||||
+ 16 - (left % 16), 1, of) != 1)
|
|
||||||
+ goto ERR_FILE_COPY;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ fclose(f);
|
|
||||||
+ blob_cur = blob_cur->next;
|
|
||||||
+ free(blob_old);
|
|
||||||
+ continue;
|
|
||||||
+
|
|
||||||
+ERR_FILE_COPY:
|
|
||||||
+ if (f)
|
|
||||||
+ fclose(f);
|
|
||||||
+ goto ERR_WRITING;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ fclose(of);
|
|
||||||
+
|
|
||||||
+EXIT:
|
|
||||||
+ return EXIT_SUCCESS;
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+ERR_WRITING:
|
|
||||||
+ fprintf(stderr, "Error writing splash.\n");
|
|
||||||
+ fprintf(stderr, "The output file is probably corrupt.\n");
|
|
||||||
+ if (of)
|
|
||||||
+ fclose(of);
|
|
||||||
+
|
|
||||||
+ while (blob_cur) {
|
|
||||||
+ struct blob_entry *blob_old = blob_cur;
|
|
||||||
+
|
|
||||||
+ blob_cur = blob_cur->next;
|
|
||||||
+ free(blob_old);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return EXIT_FAILURE;
|
|
||||||
+}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
--- a/fbtft-core.c
|
|
||||||
+++ b/fbtft-core.c
|
|
||||||
@@ -52,7 +52,7 @@
|
|
||||||
module_param(debug, ulong , 0);
|
|
||||||
MODULE_PARM_DESC(debug, "override device debug level");
|
|
||||||
|
|
||||||
-static bool dma = true;
|
|
||||||
+static bool dma = false;
|
|
||||||
module_param(dma, bool, 0);
|
|
||||||
MODULE_PARM_DESC(dma, "Use DMA buffer");
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
From 27517cde069da44a218ce13b5d46fee19c1bcc77 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Helge Deller <deller@gmx.de>
|
|
||||||
Date: Mon, 7 Feb 2022 16:59:31 +0100
|
|
||||||
Subject: [PATCH] Revert "fbcon: Avoid 'cap' set but not used warning"
|
|
||||||
|
|
||||||
This reverts commit 3523167d665852fc5f92971aefea8f3bd4e2f6fd.
|
|
||||||
---
|
|
||||||
drivers/video/fbdev/core/fbcon.c | 7 ++++---
|
|
||||||
1 file changed, 4 insertions(+), 3 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
|
|
||||||
index a53c1f6906f0..f7b7d35953e8 100644
|
|
||||||
--- a/drivers/video/fbdev/core/fbcon.c
|
|
||||||
+++ b/drivers/video/fbdev/core/fbcon.c
|
|
||||||
@@ -1025,7 +1025,7 @@ static void fbcon_init(struct vc_data *vc, int init)
|
|
||||||
struct vc_data *svc = *default_mode;
|
|
||||||
struct fbcon_display *t, *p = &fb_display[vc->vc_num];
|
|
||||||
int logo = 1, new_rows, new_cols, rows, cols;
|
|
||||||
- int ret;
|
|
||||||
+ int cap, ret;
|
|
||||||
|
|
||||||
if (WARN_ON(info_idx == -1))
|
|
||||||
return;
|
|
||||||
@@ -1136,8 +1137,8 @@ static void fbcon_init(struct vc_data *vc, int init)
|
|
||||||
ops->graphics = 0;
|
|
||||||
|
|
||||||
#ifdef CONFIG_FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION
|
|
||||||
- if ((info->flags & FBINFO_HWACCEL_COPYAREA) &&
|
|
||||||
- !(info->flags & FBINFO_HWACCEL_DISABLED))
|
|
||||||
+ if ((cap & FBINFO_HWACCEL_COPYAREA) &&
|
|
||||||
+ !(cap & FBINFO_HWACCEL_DISABLED))
|
|
||||||
p->scrollmode = SCROLL_MOVE;
|
|
||||||
else /* default to something safe */
|
|
||||||
p->scrollmode = SCROLL_REDRAW;
|
|
||||||
--
|
|
||||||
2.25.1
|
|
||||||
|
|
||||||
@@ -1,360 +0,0 @@
|
|||||||
From b205b9e8c05a4e9ea136036f36739e3385878477 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Igor Pecovnik <igor.pecovnik@gmail.com>
|
|
||||||
Date: Thu, 10 Feb 2022 16:48:05 +0100
|
|
||||||
Subject: [PATCH 1/2] Revert "fbcon: Add option to enable legacy hardware
|
|
||||||
acceleration"
|
|
||||||
|
|
||||||
This reverts commit 72c4cec1d21ab6fa1b7b6ed5a60a85b421028b89.
|
|
||||||
---
|
|
||||||
drivers/video/console/Kconfig | 20 -------------
|
|
||||||
drivers/video/fbdev/core/fbcon.c | 39 +++++++------------------
|
|
||||||
drivers/video/fbdev/core/fbcon.h | 15 +---------
|
|
||||||
drivers/video/fbdev/core/fbcon_ccw.c | 10 +++----
|
|
||||||
drivers/video/fbdev/core/fbcon_cw.c | 10 +++----
|
|
||||||
drivers/video/fbdev/core/fbcon_rotate.h | 4 +--
|
|
||||||
drivers/video/fbdev/core/fbcon_ud.c | 20 ++++++-------
|
|
||||||
7 files changed, 34 insertions(+), 84 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
|
|
||||||
index fcc46380e7c9..840d9813b0bc 100644
|
|
||||||
--- a/drivers/video/console/Kconfig
|
|
||||||
+++ b/drivers/video/console/Kconfig
|
|
||||||
@@ -78,26 +78,6 @@ config FRAMEBUFFER_CONSOLE
|
|
||||||
help
|
|
||||||
Low-level framebuffer-based console driver.
|
|
||||||
|
|
||||||
-config FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION
|
|
||||||
- bool "Enable legacy fbcon hardware acceleration code"
|
|
||||||
- depends on FRAMEBUFFER_CONSOLE
|
|
||||||
- default y if PARISC
|
|
||||||
- default n
|
|
||||||
- help
|
|
||||||
- This option enables the fbcon (framebuffer text-based) hardware
|
|
||||||
- acceleration for graphics drivers which were written for the fbdev
|
|
||||||
- graphics interface.
|
|
||||||
-
|
|
||||||
- On modern machines, on mainstream machines (like x86-64) or when
|
|
||||||
- using a modern Linux distribution those fbdev drivers usually aren't used.
|
|
||||||
- So enabling this option wouldn't have any effect, which is why you want
|
|
||||||
- to disable this option on such newer machines.
|
|
||||||
-
|
|
||||||
- If you compile this kernel for older machines which still require the
|
|
||||||
- fbdev drivers, you may want to say Y.
|
|
||||||
-
|
|
||||||
- If unsure, select n.
|
|
||||||
-
|
|
||||||
config FRAMEBUFFER_CONSOLE_DETECT_PRIMARY
|
|
||||||
bool "Map the console to the primary display device"
|
|
||||||
depends on FRAMEBUFFER_CONSOLE
|
|
||||||
diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
|
|
||||||
index f36829eeb5a9..0cc2a36b674a 100644
|
|
||||||
--- a/drivers/video/fbdev/core/fbcon.c
|
|
||||||
+++ b/drivers/video/fbdev/core/fbcon.c
|
|
||||||
@@ -1136,13 +1136,11 @@ static void fbcon_init(struct vc_data *vc, int init)
|
|
||||||
|
|
||||||
ops->graphics = 0;
|
|
||||||
|
|
||||||
-#ifdef CONFIG_FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION
|
|
||||||
if ((cap & FBINFO_HWACCEL_COPYAREA) &&
|
|
||||||
!(cap & FBINFO_HWACCEL_DISABLED))
|
|
||||||
p->scrollmode = SCROLL_MOVE;
|
|
||||||
else /* default to something safe */
|
|
||||||
p->scrollmode = SCROLL_REDRAW;
|
|
||||||
-#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* ++guenther: console.c:vc_allocate() relies on initializing
|
|
||||||
@@ -1707,7 +1705,7 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b,
|
|
||||||
count = vc->vc_rows;
|
|
||||||
if (logo_shown >= 0)
|
|
||||||
goto redraw_up;
|
|
||||||
- switch (fb_scrollmode(p)) {
|
|
||||||
+ switch (p->scrollmode) {
|
|
||||||
case SCROLL_MOVE:
|
|
||||||
fbcon_redraw_blit(vc, info, p, t, b - t - count,
|
|
||||||
count);
|
|
||||||
@@ -1797,7 +1795,7 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b,
|
|
||||||
count = vc->vc_rows;
|
|
||||||
if (logo_shown >= 0)
|
|
||||||
goto redraw_down;
|
|
||||||
- switch (fb_scrollmode(p)) {
|
|
||||||
+ switch (p->scrollmode) {
|
|
||||||
case SCROLL_MOVE:
|
|
||||||
fbcon_redraw_blit(vc, info, p, b - 1, b - t - count,
|
|
||||||
-count);
|
|
||||||
@@ -1948,12 +1946,12 @@ static void fbcon_bmove_rec(struct vc_data *vc, struct fbcon_display *p, int sy,
|
|
||||||
height, width);
|
|
||||||
}
|
|
||||||
|
|
||||||
-static void updatescrollmode_accel(struct fbcon_display *p,
|
|
||||||
+static void updatescrollmode(struct fbcon_display *p,
|
|
||||||
struct fb_info *info,
|
|
||||||
struct vc_data *vc)
|
|
||||||
{
|
|
||||||
-#ifdef CONFIG_FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION
|
|
||||||
struct fbcon_ops *ops = info->fbcon_par;
|
|
||||||
+ int fh = vc->vc_font.height;
|
|
||||||
int cap = info->flags;
|
|
||||||
u16 t = 0;
|
|
||||||
int ypan = FBCON_SWAP(ops->rotate, info->fix.ypanstep,
|
|
||||||
@@ -1974,6 +1972,12 @@ static void updatescrollmode_accel(struct fbcon_display *p,
|
|
||||||
int fast_imageblit = (cap & FBINFO_HWACCEL_IMAGEBLIT) &&
|
|
||||||
!(cap & FBINFO_HWACCEL_DISABLED);
|
|
||||||
|
|
||||||
+ p->vrows = vyres/fh;
|
|
||||||
+ if (yres > (fh * (vc->vc_rows + 1)))
|
|
||||||
+ p->vrows -= (yres - (fh * vc->vc_rows)) / fh;
|
|
||||||
+ if ((yres % fh) && (vyres % fh < yres % fh))
|
|
||||||
+ p->vrows--;
|
|
||||||
+
|
|
||||||
if (good_wrap || good_pan) {
|
|
||||||
if (reading_fast || fast_copyarea)
|
|
||||||
p->scrollmode = good_wrap ?
|
|
||||||
@@ -1987,27 +1991,6 @@ static void updatescrollmode_accel(struct fbcon_display *p,
|
|
||||||
else
|
|
||||||
p->scrollmode = SCROLL_REDRAW;
|
|
||||||
}
|
|
||||||
-#endif
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
-static void updatescrollmode(struct fbcon_display *p,
|
|
||||||
- struct fb_info *info,
|
|
||||||
- struct vc_data *vc)
|
|
||||||
-{
|
|
||||||
- struct fbcon_ops *ops = info->fbcon_par;
|
|
||||||
- int fh = vc->vc_font.height;
|
|
||||||
- int yres = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
|
|
||||||
- int vyres = FBCON_SWAP(ops->rotate, info->var.yres_virtual,
|
|
||||||
- info->var.xres_virtual);
|
|
||||||
-
|
|
||||||
- p->vrows = vyres/fh;
|
|
||||||
- if (yres > (fh * (vc->vc_rows + 1)))
|
|
||||||
- p->vrows -= (yres - (fh * vc->vc_rows)) / fh;
|
|
||||||
- if ((yres % fh) && (vyres % fh < yres % fh))
|
|
||||||
- p->vrows--;
|
|
||||||
-
|
|
||||||
- /* update scrollmode in case hardware acceleration is used */
|
|
||||||
- updatescrollmode_accel(p, info, vc);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define PITCH(w) (((w) + 7) >> 3)
|
|
||||||
@@ -2165,7 +2148,7 @@ static int fbcon_switch(struct vc_data *vc)
|
|
||||||
|
|
||||||
updatescrollmode(p, info, vc);
|
|
||||||
|
|
||||||
- switch (fb_scrollmode(p)) {
|
|
||||||
+ switch (p->scrollmode) {
|
|
||||||
case SCROLL_WRAP_MOVE:
|
|
||||||
scrollback_phys_max = p->vrows - vc->vc_rows;
|
|
||||||
break;
|
|
||||||
diff --git a/drivers/video/fbdev/core/fbcon.h b/drivers/video/fbdev/core/fbcon.h
|
|
||||||
index 969d41ecede5..5246d0f2574b 100644
|
|
||||||
--- a/drivers/video/fbdev/core/fbcon.h
|
|
||||||
+++ b/drivers/video/fbdev/core/fbcon.h
|
|
||||||
@@ -29,9 +29,7 @@ struct fbcon_display {
|
|
||||||
/* Filled in by the low-level console driver */
|
|
||||||
const u_char *fontdata;
|
|
||||||
int userfont; /* != 0 if fontdata kmalloc()ed */
|
|
||||||
-#ifdef CONFIG_FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION
|
|
||||||
- u_short scrollmode; /* Scroll Method, use fb_scrollmode() */
|
|
||||||
-#endif
|
|
||||||
+ u_short scrollmode; /* Scroll Method */
|
|
||||||
u_short inverse; /* != 0 text black on white as default */
|
|
||||||
short yscroll; /* Hardware scrolling */
|
|
||||||
int vrows; /* number of virtual rows */
|
|
||||||
@@ -210,17 +208,6 @@ static inline int attr_col_ec(int shift, struct vc_data *vc,
|
|
||||||
#define SCROLL_REDRAW 0x004
|
|
||||||
#define SCROLL_PAN_REDRAW 0x005
|
|
||||||
|
|
||||||
-static inline u_short fb_scrollmode(struct fbcon_display *fb)
|
|
||||||
-{
|
|
||||||
-#ifdef CONFIG_FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION
|
|
||||||
- return fb->scrollmode;
|
|
||||||
-#else
|
|
||||||
- /* hardcoded to SCROLL_REDRAW if acceleration was disabled. */
|
|
||||||
- return SCROLL_REDRAW;
|
|
||||||
-#endif
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
-
|
|
||||||
#ifdef CONFIG_FB_TILEBLITTING
|
|
||||||
extern void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info);
|
|
||||||
#endif
|
|
||||||
diff --git a/drivers/video/fbdev/core/fbcon_ccw.c b/drivers/video/fbdev/core/fbcon_ccw.c
|
|
||||||
index 2789ace79634..9cd2c4b05c32 100644
|
|
||||||
--- a/drivers/video/fbdev/core/fbcon_ccw.c
|
|
||||||
+++ b/drivers/video/fbdev/core/fbcon_ccw.c
|
|
||||||
@@ -65,7 +65,7 @@ static void ccw_bmove(struct vc_data *vc, struct fb_info *info, int sy,
|
|
||||||
{
|
|
||||||
struct fbcon_ops *ops = info->fbcon_par;
|
|
||||||
struct fb_copyarea area;
|
|
||||||
- u32 vyres = GETVYRES(ops->p, info);
|
|
||||||
+ u32 vyres = GETVYRES(ops->p->scrollmode, info);
|
|
||||||
|
|
||||||
area.sx = sy * vc->vc_font.height;
|
|
||||||
area.sy = vyres - ((sx + width) * vc->vc_font.width);
|
|
||||||
@@ -83,7 +83,7 @@ static void ccw_clear(struct vc_data *vc, struct fb_info *info, int sy,
|
|
||||||
struct fbcon_ops *ops = info->fbcon_par;
|
|
||||||
struct fb_fillrect region;
|
|
||||||
int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
|
|
||||||
- u32 vyres = GETVYRES(ops->p, info);
|
|
||||||
+ u32 vyres = GETVYRES(ops->p->scrollmode, info);
|
|
||||||
|
|
||||||
region.color = attr_bgcol_ec(bgshift,vc,info);
|
|
||||||
region.dx = sy * vc->vc_font.height;
|
|
||||||
@@ -140,7 +140,7 @@ static void ccw_putcs(struct vc_data *vc, struct fb_info *info,
|
|
||||||
u32 cnt, pitch, size;
|
|
||||||
u32 attribute = get_attribute(info, scr_readw(s));
|
|
||||||
u8 *dst, *buf = NULL;
|
|
||||||
- u32 vyres = GETVYRES(ops->p, info);
|
|
||||||
+ u32 vyres = GETVYRES(ops->p->scrollmode, info);
|
|
||||||
|
|
||||||
if (!ops->fontbuffer)
|
|
||||||
return;
|
|
||||||
@@ -229,7 +229,7 @@ static void ccw_cursor(struct vc_data *vc, struct fb_info *info, int mode,
|
|
||||||
int attribute, use_sw = vc->vc_cursor_type & CUR_SW;
|
|
||||||
int err = 1, dx, dy;
|
|
||||||
char *src;
|
|
||||||
- u32 vyres = GETVYRES(ops->p, info);
|
|
||||||
+ u32 vyres = GETVYRES(ops->p->scrollmode, info);
|
|
||||||
|
|
||||||
if (!ops->fontbuffer)
|
|
||||||
return;
|
|
||||||
@@ -387,7 +387,7 @@ static int ccw_update_start(struct fb_info *info)
|
|
||||||
{
|
|
||||||
struct fbcon_ops *ops = info->fbcon_par;
|
|
||||||
u32 yoffset;
|
|
||||||
- u32 vyres = GETVYRES(ops->p, info);
|
|
||||||
+ u32 vyres = GETVYRES(ops->p->scrollmode, info);
|
|
||||||
int err;
|
|
||||||
|
|
||||||
yoffset = (vyres - info->var.yres) - ops->var.xoffset;
|
|
||||||
diff --git a/drivers/video/fbdev/core/fbcon_cw.c b/drivers/video/fbdev/core/fbcon_cw.c
|
|
||||||
index 86a254c1b2b7..88d89fad3f05 100644
|
|
||||||
--- a/drivers/video/fbdev/core/fbcon_cw.c
|
|
||||||
+++ b/drivers/video/fbdev/core/fbcon_cw.c
|
|
||||||
@@ -50,7 +50,7 @@ static void cw_bmove(struct vc_data *vc, struct fb_info *info, int sy,
|
|
||||||
{
|
|
||||||
struct fbcon_ops *ops = info->fbcon_par;
|
|
||||||
struct fb_copyarea area;
|
|
||||||
- u32 vxres = GETVXRES(ops->p, info);
|
|
||||||
+ u32 vxres = GETVXRES(ops->p->scrollmode, info);
|
|
||||||
|
|
||||||
area.sx = vxres - ((sy + height) * vc->vc_font.height);
|
|
||||||
area.sy = sx * vc->vc_font.width;
|
|
||||||
@@ -68,7 +68,7 @@ static void cw_clear(struct vc_data *vc, struct fb_info *info, int sy,
|
|
||||||
struct fbcon_ops *ops = info->fbcon_par;
|
|
||||||
struct fb_fillrect region;
|
|
||||||
int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
|
|
||||||
- u32 vxres = GETVXRES(ops->p, info);
|
|
||||||
+ u32 vxres = GETVXRES(ops->p->scrollmode, info);
|
|
||||||
|
|
||||||
region.color = attr_bgcol_ec(bgshift,vc,info);
|
|
||||||
region.dx = vxres - ((sy + height) * vc->vc_font.height);
|
|
||||||
@@ -125,7 +125,7 @@ static void cw_putcs(struct vc_data *vc, struct fb_info *info,
|
|
||||||
u32 cnt, pitch, size;
|
|
||||||
u32 attribute = get_attribute(info, scr_readw(s));
|
|
||||||
u8 *dst, *buf = NULL;
|
|
||||||
- u32 vxres = GETVXRES(ops->p, info);
|
|
||||||
+ u32 vxres = GETVXRES(ops->p->scrollmode, info);
|
|
||||||
|
|
||||||
if (!ops->fontbuffer)
|
|
||||||
return;
|
|
||||||
@@ -212,7 +212,7 @@ static void cw_cursor(struct vc_data *vc, struct fb_info *info, int mode,
|
|
||||||
int attribute, use_sw = vc->vc_cursor_type & CUR_SW;
|
|
||||||
int err = 1, dx, dy;
|
|
||||||
char *src;
|
|
||||||
- u32 vxres = GETVXRES(ops->p, info);
|
|
||||||
+ u32 vxres = GETVXRES(ops->p->scrollmode, info);
|
|
||||||
|
|
||||||
if (!ops->fontbuffer)
|
|
||||||
return;
|
|
||||||
@@ -369,7 +369,7 @@ static void cw_cursor(struct vc_data *vc, struct fb_info *info, int mode,
|
|
||||||
static int cw_update_start(struct fb_info *info)
|
|
||||||
{
|
|
||||||
struct fbcon_ops *ops = info->fbcon_par;
|
|
||||||
- u32 vxres = GETVXRES(ops->p, info);
|
|
||||||
+ u32 vxres = GETVXRES(ops->p->scrollmode, info);
|
|
||||||
u32 xoffset;
|
|
||||||
int err;
|
|
||||||
|
|
||||||
diff --git a/drivers/video/fbdev/core/fbcon_rotate.h b/drivers/video/fbdev/core/fbcon_rotate.h
|
|
||||||
index 01cbe303b8a2..e233444cda66 100644
|
|
||||||
--- a/drivers/video/fbdev/core/fbcon_rotate.h
|
|
||||||
+++ b/drivers/video/fbdev/core/fbcon_rotate.h
|
|
||||||
@@ -12,11 +12,11 @@
|
|
||||||
#define _FBCON_ROTATE_H
|
|
||||||
|
|
||||||
#define GETVYRES(s,i) ({ \
|
|
||||||
- (fb_scrollmode(s) == SCROLL_REDRAW || fb_scrollmode(s) == SCROLL_MOVE) ? \
|
|
||||||
+ (s == SCROLL_REDRAW || s == SCROLL_MOVE) ? \
|
|
||||||
(i)->var.yres : (i)->var.yres_virtual; })
|
|
||||||
|
|
||||||
#define GETVXRES(s,i) ({ \
|
|
||||||
- (fb_scrollmode(s) == SCROLL_REDRAW || fb_scrollmode(s) == SCROLL_MOVE || !(i)->fix.xpanstep) ? \
|
|
||||||
+ (s == SCROLL_REDRAW || s == SCROLL_MOVE || !(i)->fix.xpanstep) ? \
|
|
||||||
(i)->var.xres : (i)->var.xres_virtual; })
|
|
||||||
|
|
||||||
|
|
||||||
diff --git a/drivers/video/fbdev/core/fbcon_ud.c b/drivers/video/fbdev/core/fbcon_ud.c
|
|
||||||
index 23bc045769d0..8d5e66b1bdfb 100644
|
|
||||||
--- a/drivers/video/fbdev/core/fbcon_ud.c
|
|
||||||
+++ b/drivers/video/fbdev/core/fbcon_ud.c
|
|
||||||
@@ -50,8 +50,8 @@ static void ud_bmove(struct vc_data *vc, struct fb_info *info, int sy,
|
|
||||||
{
|
|
||||||
struct fbcon_ops *ops = info->fbcon_par;
|
|
||||||
struct fb_copyarea area;
|
|
||||||
- u32 vyres = GETVYRES(ops->p, info);
|
|
||||||
- u32 vxres = GETVXRES(ops->p, info);
|
|
||||||
+ u32 vyres = GETVYRES(ops->p->scrollmode, info);
|
|
||||||
+ u32 vxres = GETVXRES(ops->p->scrollmode, info);
|
|
||||||
|
|
||||||
area.sy = vyres - ((sy + height) * vc->vc_font.height);
|
|
||||||
area.sx = vxres - ((sx + width) * vc->vc_font.width);
|
|
||||||
@@ -69,8 +69,8 @@ static void ud_clear(struct vc_data *vc, struct fb_info *info, int sy,
|
|
||||||
struct fbcon_ops *ops = info->fbcon_par;
|
|
||||||
struct fb_fillrect region;
|
|
||||||
int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
|
|
||||||
- u32 vyres = GETVYRES(ops->p, info);
|
|
||||||
- u32 vxres = GETVXRES(ops->p, info);
|
|
||||||
+ u32 vyres = GETVYRES(ops->p->scrollmode, info);
|
|
||||||
+ u32 vxres = GETVXRES(ops->p->scrollmode, info);
|
|
||||||
|
|
||||||
region.color = attr_bgcol_ec(bgshift,vc,info);
|
|
||||||
region.dy = vyres - ((sy + height) * vc->vc_font.height);
|
|
||||||
@@ -162,8 +162,8 @@ static void ud_putcs(struct vc_data *vc, struct fb_info *info,
|
|
||||||
u32 mod = vc->vc_font.width % 8, cnt, pitch, size;
|
|
||||||
u32 attribute = get_attribute(info, scr_readw(s));
|
|
||||||
u8 *dst, *buf = NULL;
|
|
||||||
- u32 vyres = GETVYRES(ops->p, info);
|
|
||||||
- u32 vxres = GETVXRES(ops->p, info);
|
|
||||||
+ u32 vyres = GETVYRES(ops->p->scrollmode, info);
|
|
||||||
+ u32 vxres = GETVXRES(ops->p->scrollmode, info);
|
|
||||||
|
|
||||||
if (!ops->fontbuffer)
|
|
||||||
return;
|
|
||||||
@@ -259,8 +259,8 @@ static void ud_cursor(struct vc_data *vc, struct fb_info *info, int mode,
|
|
||||||
int attribute, use_sw = vc->vc_cursor_type & CUR_SW;
|
|
||||||
int err = 1, dx, dy;
|
|
||||||
char *src;
|
|
||||||
- u32 vyres = GETVYRES(ops->p, info);
|
|
||||||
- u32 vxres = GETVXRES(ops->p, info);
|
|
||||||
+ u32 vyres = GETVYRES(ops->p->scrollmode, info);
|
|
||||||
+ u32 vxres = GETVXRES(ops->p->scrollmode, info);
|
|
||||||
|
|
||||||
if (!ops->fontbuffer)
|
|
||||||
return;
|
|
||||||
@@ -410,8 +410,8 @@ static int ud_update_start(struct fb_info *info)
|
|
||||||
{
|
|
||||||
struct fbcon_ops *ops = info->fbcon_par;
|
|
||||||
int xoffset, yoffset;
|
|
||||||
- u32 vyres = GETVYRES(ops->p, info);
|
|
||||||
- u32 vxres = GETVXRES(ops->p, info);
|
|
||||||
+ u32 vyres = GETVYRES(ops->p->scrollmode, info);
|
|
||||||
+ u32 vxres = GETVXRES(ops->p->scrollmode, info);
|
|
||||||
int err;
|
|
||||||
|
|
||||||
xoffset = vxres - info->var.xres - ops->var.xoffset;
|
|
||||||
--
|
|
||||||
2.25.1
|
|
||||||
|
|
||||||
@@ -1,132 +0,0 @@
|
|||||||
From abd60692635211581dec506af647ac9295d21d69 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Igor Pecovnik <igor.pecovnik@gmail.com>
|
|
||||||
Date: Thu, 10 Feb 2022 16:48:23 +0100
|
|
||||||
Subject: [PATCH 2/2] Revert "Revert "fbcon: Disable accelerated scrolling""
|
|
||||||
|
|
||||||
This reverts commit ba724328faffc640b7772c953bd061bf6c4d39cd.
|
|
||||||
---
|
|
||||||
Documentation/gpu/todo.rst | 21 +++++++++++++++
|
|
||||||
drivers/video/fbdev/core/fbcon.c | 45 ++++++--------------------------
|
|
||||||
2 files changed, 29 insertions(+), 37 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/Documentation/gpu/todo.rst b/Documentation/gpu/todo.rst
|
|
||||||
index 01fb97dd2dd0..6613543955e9 100644
|
|
||||||
--- a/Documentation/gpu/todo.rst
|
|
||||||
+++ b/Documentation/gpu/todo.rst
|
|
||||||
@@ -311,6 +311,27 @@ Contact: Daniel Vetter, Noralf Tronnes
|
|
||||||
|
|
||||||
Level: Advanced
|
|
||||||
|
|
||||||
+Garbage collect fbdev scrolling acceleration
|
|
||||||
+--------------------------------------------
|
|
||||||
+
|
|
||||||
+Scroll acceleration is disabled in fbcon by hard-wiring p->scrollmode =
|
|
||||||
+SCROLL_REDRAW. There's a ton of code this will allow us to remove:
|
|
||||||
+
|
|
||||||
+- lots of code in fbcon.c
|
|
||||||
+
|
|
||||||
+- a bunch of the hooks in fbcon_ops, maybe the remaining hooks could be called
|
|
||||||
+ directly instead of the function table (with a switch on p->rotate)
|
|
||||||
+
|
|
||||||
+- fb_copyarea is unused after this, and can be deleted from all drivers
|
|
||||||
+
|
|
||||||
+Note that not all acceleration code can be deleted, since clearing and cursor
|
|
||||||
+support is still accelerated, which might be good candidates for further
|
|
||||||
+deletion projects.
|
|
||||||
+
|
|
||||||
+Contact: Daniel Vetter
|
|
||||||
+
|
|
||||||
+Level: Intermediate
|
|
||||||
+
|
|
||||||
idr_init_base()
|
|
||||||
---------------
|
|
||||||
|
|
||||||
diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
|
|
||||||
index 0cc2a36b674a..fc34caddf9cf 100644
|
|
||||||
--- a/drivers/video/fbdev/core/fbcon.c
|
|
||||||
+++ b/drivers/video/fbdev/core/fbcon.c
|
|
||||||
@@ -1025,7 +1025,7 @@ static void fbcon_init(struct vc_data *vc, int init)
|
|
||||||
struct vc_data *svc = *default_mode;
|
|
||||||
struct fbcon_display *t, *p = &fb_display[vc->vc_num];
|
|
||||||
int logo = 1, new_rows, new_cols, rows, cols;
|
|
||||||
- int cap, ret;
|
|
||||||
+ int ret;
|
|
||||||
|
|
||||||
if (WARN_ON(info_idx == -1))
|
|
||||||
return;
|
|
||||||
@@ -1034,7 +1034,6 @@ static void fbcon_init(struct vc_data *vc, int init)
|
|
||||||
con2fb_map[vc->vc_num] = info_idx;
|
|
||||||
|
|
||||||
info = registered_fb[con2fb_map[vc->vc_num]];
|
|
||||||
- cap = info->flags;
|
|
||||||
|
|
||||||
if (logo_shown < 0 && console_loglevel <= CONSOLE_LOGLEVEL_QUIET)
|
|
||||||
logo_shown = FBCON_LOGO_DONTSHOW;
|
|
||||||
@@ -1136,11 +1135,13 @@ static void fbcon_init(struct vc_data *vc, int init)
|
|
||||||
|
|
||||||
ops->graphics = 0;
|
|
||||||
|
|
||||||
- if ((cap & FBINFO_HWACCEL_COPYAREA) &&
|
|
||||||
- !(cap & FBINFO_HWACCEL_DISABLED))
|
|
||||||
- p->scrollmode = SCROLL_MOVE;
|
|
||||||
- else /* default to something safe */
|
|
||||||
- p->scrollmode = SCROLL_REDRAW;
|
|
||||||
+ /*
|
|
||||||
+ * No more hw acceleration for fbcon.
|
|
||||||
+ *
|
|
||||||
+ * FIXME: Garbage collect all the now dead code after sufficient time
|
|
||||||
+ * has passed.
|
|
||||||
+ */
|
|
||||||
+ p->scrollmode = SCROLL_REDRAW;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* ++guenther: console.c:vc_allocate() relies on initializing
|
|
||||||
@@ -1952,45 +1953,15 @@ static void updatescrollmode(struct fbcon_display *p,
|
|
||||||
{
|
|
||||||
struct fbcon_ops *ops = info->fbcon_par;
|
|
||||||
int fh = vc->vc_font.height;
|
|
||||||
- int cap = info->flags;
|
|
||||||
- u16 t = 0;
|
|
||||||
- int ypan = FBCON_SWAP(ops->rotate, info->fix.ypanstep,
|
|
||||||
- info->fix.xpanstep);
|
|
||||||
- int ywrap = FBCON_SWAP(ops->rotate, info->fix.ywrapstep, t);
|
|
||||||
int yres = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
|
|
||||||
int vyres = FBCON_SWAP(ops->rotate, info->var.yres_virtual,
|
|
||||||
info->var.xres_virtual);
|
|
||||||
- int good_pan = (cap & FBINFO_HWACCEL_YPAN) &&
|
|
||||||
- divides(ypan, vc->vc_font.height) && vyres > yres;
|
|
||||||
- int good_wrap = (cap & FBINFO_HWACCEL_YWRAP) &&
|
|
||||||
- divides(ywrap, vc->vc_font.height) &&
|
|
||||||
- divides(vc->vc_font.height, vyres) &&
|
|
||||||
- divides(vc->vc_font.height, yres);
|
|
||||||
- int reading_fast = cap & FBINFO_READS_FAST;
|
|
||||||
- int fast_copyarea = (cap & FBINFO_HWACCEL_COPYAREA) &&
|
|
||||||
- !(cap & FBINFO_HWACCEL_DISABLED);
|
|
||||||
- int fast_imageblit = (cap & FBINFO_HWACCEL_IMAGEBLIT) &&
|
|
||||||
- !(cap & FBINFO_HWACCEL_DISABLED);
|
|
||||||
|
|
||||||
p->vrows = vyres/fh;
|
|
||||||
if (yres > (fh * (vc->vc_rows + 1)))
|
|
||||||
p->vrows -= (yres - (fh * vc->vc_rows)) / fh;
|
|
||||||
if ((yres % fh) && (vyres % fh < yres % fh))
|
|
||||||
p->vrows--;
|
|
||||||
-
|
|
||||||
- if (good_wrap || good_pan) {
|
|
||||||
- if (reading_fast || fast_copyarea)
|
|
||||||
- p->scrollmode = good_wrap ?
|
|
||||||
- SCROLL_WRAP_MOVE : SCROLL_PAN_MOVE;
|
|
||||||
- else
|
|
||||||
- p->scrollmode = good_wrap ? SCROLL_REDRAW :
|
|
||||||
- SCROLL_PAN_REDRAW;
|
|
||||||
- } else {
|
|
||||||
- if (reading_fast || (fast_copyarea && !fast_imageblit))
|
|
||||||
- p->scrollmode = SCROLL_MOVE;
|
|
||||||
- else
|
|
||||||
- p->scrollmode = SCROLL_REDRAW;
|
|
||||||
- }
|
|
||||||
}
|
|
||||||
|
|
||||||
#define PITCH(w) (((w) + 7) >> 3)
|
|
||||||
--
|
|
||||||
2.25.1
|
|
||||||
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
From d8eb6e5e70ba30717bb8aea4390c112cb8892e1b Mon Sep 17 00:00:00 2001
|
|
||||||
From: Igor Pecovnik <igor.pecovnik@gmail.com>
|
|
||||||
Date: Tue, 20 Jul 2021 17:38:53 +0000
|
|
||||||
Subject: [PATCH] Revert "vgacon: drop unused vga_init_done"
|
|
||||||
|
|
||||||
This reverts commit 0ae798fd96f8c28850e09d22d3f0d455071ed8eb.
|
|
||||||
---
|
|
||||||
drivers/video/console/vgacon.c | 3 +++
|
|
||||||
1 file changed, 3 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
|
|
||||||
index ef9c57ce0906..8cba9f46ddf9 100644
|
|
||||||
--- a/drivers/video/console/vgacon.c
|
|
||||||
+++ b/drivers/video/console/vgacon.c
|
|
||||||
@@ -79,6 +79,7 @@ static struct uni_pagedir *vgacon_uni_pagedir;
|
|
||||||
static int vgacon_refcount;
|
|
||||||
|
|
||||||
/* Description of the hardware situation */
|
|
||||||
+static bool vga_init_done;
|
|
||||||
static unsigned long vga_vram_base __read_mostly; /* Base of video memory */
|
|
||||||
static unsigned long vga_vram_end __read_mostly; /* End of video memory */
|
|
||||||
static unsigned int vga_vram_size __read_mostly; /* Size of video memory */
|
|
||||||
@@ -358,6 +359,8 @@ static const char *vgacon_startup(void)
|
|
||||||
vgacon_xres = screen_info.orig_video_cols * VGA_FONTWIDTH;
|
|
||||||
vgacon_yres = vga_scan_lines;
|
|
||||||
|
|
||||||
+ vga_init_done = true;
|
|
||||||
+
|
|
||||||
return display_desc;
|
|
||||||
}
|
|
||||||
|
|
||||||
--
|
|
||||||
2.30.2
|
|
||||||
|
|
||||||
@@ -1,338 +0,0 @@
|
|||||||
From 440d5cecaf940b722f9f78a14db7f1e0bc0f61e8 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Igor Pecovnik <igor.pecovnik@gmail.com>
|
|
||||||
Date: Mon, 21 Sep 2020 17:15:09 +0200
|
|
||||||
Subject: [PATCH 1/3] Revert "vgacon: remove software scrollback support"
|
|
||||||
|
|
||||||
This reverts commit 20782abbbdfe922496a28f9cc0c3c0030f7dfb8f.
|
|
||||||
---
|
|
||||||
drivers/video/console/Kconfig | 46 ++++++
|
|
||||||
drivers/video/console/vgacon.c | 221 +++++++++++++++++++++++++-
|
|
||||||
6 files changed, 270 insertions(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
|
|
||||||
index 39deb22a4180..5e850cc9f891 100644
|
|
||||||
--- a/drivers/video/console/Kconfig
|
|
||||||
+++ b/drivers/video/console/Kconfig
|
|
||||||
@@ -22,6 +22,52 @@ config VGA_CONSOLE
|
|
||||||
|
|
||||||
Say Y.
|
|
||||||
|
|
||||||
+config VGACON_SOFT_SCROLLBACK
|
|
||||||
+ bool "Enable Scrollback Buffer in System RAM"
|
|
||||||
+ depends on VGA_CONSOLE
|
|
||||||
+ default n
|
|
||||||
+ help
|
|
||||||
+ The scrollback buffer of the standard VGA console is located in
|
|
||||||
+ the VGA RAM. The size of this RAM is fixed and is quite small.
|
|
||||||
+ If you require a larger scrollback buffer, this can be placed in
|
|
||||||
+ System RAM which is dynamically allocated during initialization.
|
|
||||||
+ Placing the scrollback buffer in System RAM will slightly slow
|
|
||||||
+ down the console.
|
|
||||||
+
|
|
||||||
+ If you want this feature, say 'Y' here and enter the amount of
|
|
||||||
+ RAM to allocate for this buffer. If unsure, say 'N'.
|
|
||||||
+
|
|
||||||
+config VGACON_SOFT_SCROLLBACK_SIZE
|
|
||||||
+ int "Scrollback Buffer Size (in KB)"
|
|
||||||
+ depends on VGACON_SOFT_SCROLLBACK
|
|
||||||
+ range 1 1024
|
|
||||||
+ default "64"
|
|
||||||
+ help
|
|
||||||
+ Enter the amount of System RAM to allocate for scrollback
|
|
||||||
+ buffers of VGA consoles. Each 64KB will give you approximately
|
|
||||||
+ 16 80x25 screenfuls of scrollback buffer.
|
|
||||||
+
|
|
||||||
+config VGACON_SOFT_SCROLLBACK_PERSISTENT_ENABLE_BY_DEFAULT
|
|
||||||
+ bool "Persistent Scrollback History for each console by default"
|
|
||||||
+ depends on VGACON_SOFT_SCROLLBACK
|
|
||||||
+ default n
|
|
||||||
+ help
|
|
||||||
+ Say Y here if the scrollback history should persist by default when
|
|
||||||
+ switching between consoles. Otherwise, the scrollback history will be
|
|
||||||
+ flushed each time the console is switched. This feature can also be
|
|
||||||
+ enabled using the boot command line parameter
|
|
||||||
+ 'vgacon.scrollback_persistent=1'.
|
|
||||||
+
|
|
||||||
+ This feature might break your tool of choice to flush the scrollback
|
|
||||||
+ buffer, e.g. clear(1) will work fine but Debian's clear_console(1)
|
|
||||||
+ will be broken, which might cause security issues.
|
|
||||||
+ You can use the escape sequence \e[3J instead if this feature is
|
|
||||||
+ activated.
|
|
||||||
+
|
|
||||||
+ Note that a buffer of VGACON_SOFT_SCROLLBACK_SIZE is taken for each
|
|
||||||
+ created tty device.
|
|
||||||
+ So if you use a RAM-constrained system, say N here.
|
|
||||||
+
|
|
||||||
config MDA_CONSOLE
|
|
||||||
depends on !M68K && !PARISC && ISA
|
|
||||||
tristate "MDA text console (dual-headed)"
|
|
||||||
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
|
|
||||||
index 6d0418e88ad7..e9254b3085a3 100644
|
|
||||||
--- a/drivers/video/console/vgacon.c
|
|
||||||
+++ b/drivers/video/console/vgacon.c
|
|
||||||
@@ -165,6 +165,214 @@ static inline void vga_set_mem_top(struct vc_data *c)
|
|
||||||
write_vga(12, (c->vc_visible_origin - vga_vram_base) / 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
+#ifdef CONFIG_VGACON_SOFT_SCROLLBACK
|
|
||||||
+/* software scrollback */
|
|
||||||
+struct vgacon_scrollback_info {
|
|
||||||
+ void *data;
|
|
||||||
+ int tail;
|
|
||||||
+ int size;
|
|
||||||
+ int rows;
|
|
||||||
+ int cnt;
|
|
||||||
+ int cur;
|
|
||||||
+ int save;
|
|
||||||
+ int restore;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+static struct vgacon_scrollback_info *vgacon_scrollback_cur;
|
|
||||||
+static struct vgacon_scrollback_info vgacon_scrollbacks[MAX_NR_CONSOLES];
|
|
||||||
+static bool scrollback_persistent = \
|
|
||||||
+ IS_ENABLED(CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT_ENABLE_BY_DEFAULT);
|
|
||||||
+module_param_named(scrollback_persistent, scrollback_persistent, bool, 0000);
|
|
||||||
+MODULE_PARM_DESC(scrollback_persistent, "Enable persistent scrollback for all vga consoles");
|
|
||||||
+
|
|
||||||
+static void vgacon_scrollback_reset(int vc_num, size_t reset_size)
|
|
||||||
+{
|
|
||||||
+ struct vgacon_scrollback_info *scrollback = &vgacon_scrollbacks[vc_num];
|
|
||||||
+
|
|
||||||
+ if (scrollback->data && reset_size > 0)
|
|
||||||
+ memset(scrollback->data, 0, reset_size);
|
|
||||||
+
|
|
||||||
+ scrollback->cnt = 0;
|
|
||||||
+ scrollback->tail = 0;
|
|
||||||
+ scrollback->cur = 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void vgacon_scrollback_init(int vc_num)
|
|
||||||
+{
|
|
||||||
+ int pitch = vga_video_num_columns * 2;
|
|
||||||
+ size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
|
|
||||||
+ int rows = size / pitch;
|
|
||||||
+ void *data;
|
|
||||||
+
|
|
||||||
+ data = kmalloc_array(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE, 1024,
|
|
||||||
+ GFP_NOWAIT);
|
|
||||||
+
|
|
||||||
+ vgacon_scrollbacks[vc_num].data = data;
|
|
||||||
+ vgacon_scrollback_cur = &vgacon_scrollbacks[vc_num];
|
|
||||||
+
|
|
||||||
+ vgacon_scrollback_cur->rows = rows - 1;
|
|
||||||
+ vgacon_scrollback_cur->size = rows * pitch;
|
|
||||||
+
|
|
||||||
+ vgacon_scrollback_reset(vc_num, size);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void vgacon_scrollback_switch(int vc_num)
|
|
||||||
+{
|
|
||||||
+ if (!scrollback_persistent)
|
|
||||||
+ vc_num = 0;
|
|
||||||
+
|
|
||||||
+ if (!vgacon_scrollbacks[vc_num].data) {
|
|
||||||
+ vgacon_scrollback_init(vc_num);
|
|
||||||
+ } else {
|
|
||||||
+ if (scrollback_persistent) {
|
|
||||||
+ vgacon_scrollback_cur = &vgacon_scrollbacks[vc_num];
|
|
||||||
+ } else {
|
|
||||||
+ size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
|
|
||||||
+
|
|
||||||
+ vgacon_scrollback_reset(vc_num, size);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void vgacon_scrollback_startup(void)
|
|
||||||
+{
|
|
||||||
+ vgacon_scrollback_cur = &vgacon_scrollbacks[0];
|
|
||||||
+ vgacon_scrollback_init(0);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void vgacon_scrollback_update(struct vc_data *c, int t, int count)
|
|
||||||
+{
|
|
||||||
+ void *p;
|
|
||||||
+
|
|
||||||
+ if (!vgacon_scrollback_cur->data || !vgacon_scrollback_cur->size ||
|
|
||||||
+ c->vc_num != fg_console)
|
|
||||||
+ return;
|
|
||||||
+
|
|
||||||
+ p = (void *) (c->vc_origin + t * c->vc_size_row);
|
|
||||||
+
|
|
||||||
+ while (count--) {
|
|
||||||
+ if ((vgacon_scrollback_cur->tail + c->vc_size_row) >
|
|
||||||
+ vgacon_scrollback_cur->size)
|
|
||||||
+ vgacon_scrollback_cur->tail = 0;
|
|
||||||
+
|
|
||||||
+ scr_memcpyw(vgacon_scrollback_cur->data +
|
|
||||||
+ vgacon_scrollback_cur->tail,
|
|
||||||
+ p, c->vc_size_row);
|
|
||||||
+
|
|
||||||
+ vgacon_scrollback_cur->cnt++;
|
|
||||||
+ p += c->vc_size_row;
|
|
||||||
+ vgacon_scrollback_cur->tail += c->vc_size_row;
|
|
||||||
+
|
|
||||||
+ if (vgacon_scrollback_cur->tail >= vgacon_scrollback_cur->size)
|
|
||||||
+ vgacon_scrollback_cur->tail = 0;
|
|
||||||
+
|
|
||||||
+ if (vgacon_scrollback_cur->cnt > vgacon_scrollback_cur->rows)
|
|
||||||
+ vgacon_scrollback_cur->cnt = vgacon_scrollback_cur->rows;
|
|
||||||
+
|
|
||||||
+ vgacon_scrollback_cur->cur = vgacon_scrollback_cur->cnt;
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void vgacon_restore_screen(struct vc_data *c)
|
|
||||||
+{
|
|
||||||
+ c->vc_origin = c->vc_visible_origin;
|
|
||||||
+ vgacon_scrollback_cur->save = 0;
|
|
||||||
+
|
|
||||||
+ if (!vga_is_gfx && !vgacon_scrollback_cur->restore) {
|
|
||||||
+ scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf,
|
|
||||||
+ c->vc_screenbuf_size > vga_vram_size ?
|
|
||||||
+ vga_vram_size : c->vc_screenbuf_size);
|
|
||||||
+ vgacon_scrollback_cur->restore = 1;
|
|
||||||
+ vgacon_scrollback_cur->cur = vgacon_scrollback_cur->cnt;
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void vgacon_scrolldelta(struct vc_data *c, int lines)
|
|
||||||
+{
|
|
||||||
+ int start, end, count, soff;
|
|
||||||
+
|
|
||||||
+ if (!lines) {
|
|
||||||
+ vgacon_restore_screen(c);
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (!vgacon_scrollback_cur->data)
|
|
||||||
+ return;
|
|
||||||
+
|
|
||||||
+ if (!vgacon_scrollback_cur->save) {
|
|
||||||
+ vgacon_cursor(c, CM_ERASE);
|
|
||||||
+ vgacon_save_screen(c);
|
|
||||||
+ c->vc_origin = (unsigned long)c->vc_screenbuf;
|
|
||||||
+ vgacon_scrollback_cur->save = 1;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ vgacon_scrollback_cur->restore = 0;
|
|
||||||
+ start = vgacon_scrollback_cur->cur + lines;
|
|
||||||
+ end = start + abs(lines);
|
|
||||||
+
|
|
||||||
+ if (start < 0)
|
|
||||||
+ start = 0;
|
|
||||||
+
|
|
||||||
+ if (start > vgacon_scrollback_cur->cnt)
|
|
||||||
+ start = vgacon_scrollback_cur->cnt;
|
|
||||||
+
|
|
||||||
+ if (end < 0)
|
|
||||||
+ end = 0;
|
|
||||||
+
|
|
||||||
+ if (end > vgacon_scrollback_cur->cnt)
|
|
||||||
+ end = vgacon_scrollback_cur->cnt;
|
|
||||||
+
|
|
||||||
+ vgacon_scrollback_cur->cur = start;
|
|
||||||
+ count = end - start;
|
|
||||||
+ soff = vgacon_scrollback_cur->tail -
|
|
||||||
+ ((vgacon_scrollback_cur->cnt - end) * c->vc_size_row);
|
|
||||||
+ soff -= count * c->vc_size_row;
|
|
||||||
+
|
|
||||||
+ if (soff < 0)
|
|
||||||
+ soff += vgacon_scrollback_cur->size;
|
|
||||||
+
|
|
||||||
+ count = vgacon_scrollback_cur->cnt - start;
|
|
||||||
+
|
|
||||||
+ if (count > c->vc_rows)
|
|
||||||
+ count = c->vc_rows;
|
|
||||||
+
|
|
||||||
+ if (count) {
|
|
||||||
+ int copysize;
|
|
||||||
+
|
|
||||||
+ int diff = c->vc_rows - count;
|
|
||||||
+ void *d = (void *) c->vc_visible_origin;
|
|
||||||
+ void *s = (void *) c->vc_screenbuf;
|
|
||||||
+
|
|
||||||
+ count *= c->vc_size_row;
|
|
||||||
+ /* how much memory to end of buffer left? */
|
|
||||||
+ copysize = min(count, vgacon_scrollback_cur->size - soff);
|
|
||||||
+ scr_memcpyw(d, vgacon_scrollback_cur->data + soff, copysize);
|
|
||||||
+ d += copysize;
|
|
||||||
+ count -= copysize;
|
|
||||||
+
|
|
||||||
+ if (count) {
|
|
||||||
+ scr_memcpyw(d, vgacon_scrollback_cur->data, count);
|
|
||||||
+ d += count;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (diff)
|
|
||||||
+ scr_memcpyw(d, s, diff * c->vc_size_row);
|
|
||||||
+ } else
|
|
||||||
+ vgacon_cursor(c, CM_MOVE);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void vgacon_flush_scrollback(struct vc_data *c)
|
|
||||||
+{
|
|
||||||
+ size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
|
|
||||||
+
|
|
||||||
+ vgacon_scrollback_reset(c->vc_num, size);
|
|
||||||
+}
|
|
||||||
+#else
|
|
||||||
+#define vgacon_scrollback_startup(...) do { } while (0)
|
|
||||||
+#define vgacon_scrollback_init(...) do { } while (0)
|
|
||||||
+#define vgacon_scrollback_update(...) do { } while (0)
|
|
||||||
+#define vgacon_scrollback_switch(...) do { } while (0)
|
|
||||||
+
|
|
||||||
static void vgacon_restore_screen(struct vc_data *c)
|
|
||||||
{
|
|
||||||
if (c->vc_origin != c->vc_visible_origin)
|
|
||||||
@@ -178,6 +386,11 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines)
|
|
||||||
vga_set_mem_top(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
+static void vgacon_flush_scrollback(struct vc_data *c)
|
|
||||||
+{
|
|
||||||
+}
|
|
||||||
+#endif /* CONFIG_VGACON_SOFT_SCROLLBACK */
|
|
||||||
+
|
|
||||||
static const char *vgacon_startup(void)
|
|
||||||
{
|
|
||||||
const char *display_desc = NULL;
|
|
||||||
@@ -360,7 +573,10 @@ static const char *vgacon_startup(void)
|
|
||||||
vgacon_xres = screen_info.orig_video_cols * VGA_FONTWIDTH;
|
|
||||||
vgacon_yres = vga_scan_lines;
|
|
||||||
|
|
||||||
- vga_init_done = true;
|
|
||||||
+ if (!vga_init_done) {
|
|
||||||
+ vgacon_scrollback_startup();
|
|
||||||
+ vga_init_done = true;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
return display_desc;
|
|
||||||
}
|
|
||||||
@@ -651,6 +867,7 @@ static int vgacon_switch(struct vc_data *c)
|
|
||||||
vgacon_doresize(c, c->vc_cols, c->vc_rows);
|
|
||||||
}
|
|
||||||
|
|
||||||
+ vgacon_scrollback_switch(c->vc_num);
|
|
||||||
return 0; /* Redrawing not needed */
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1167,6 +1384,7 @@ static bool vgacon_scroll(struct vc_data *c, unsigned int t, unsigned int b,
|
|
||||||
oldo = c->vc_origin;
|
|
||||||
delta = lines * c->vc_size_row;
|
|
||||||
if (dir == SM_UP) {
|
|
||||||
+ vgacon_scrollback_update(c, t, lines);
|
|
||||||
if (c->vc_scr_end + delta >= vga_vram_end) {
|
|
||||||
scr_memcpyw((u16 *) vga_vram_base,
|
|
||||||
(u16 *) (oldo + delta),
|
|
||||||
@@ -1230,6 +1448,7 @@ const struct consw vga_con = {
|
|
||||||
.con_save_screen = vgacon_save_screen,
|
|
||||||
.con_build_attr = vgacon_build_attr,
|
|
||||||
.con_invert_region = vgacon_invert_region,
|
|
||||||
+ .con_flush_scrollback = vgacon_flush_scrollback,
|
|
||||||
};
|
|
||||||
EXPORT_SYMBOL(vga_con);
|
|
||||||
|
|
||||||
--
|
|
||||||
2.25.1
|
|
||||||
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
From c57a371a7c28e32f0d984a1e0f22ec4e33eea51b Mon Sep 17 00:00:00 2001
|
|
||||||
From: Igor Pecovnik <igor.pecovnik@gmail.com>
|
|
||||||
Date: Thu, 10 Feb 2022 19:20:27 +0100
|
|
||||||
Subject: [PATCH] Revert "drivers: video: fbcon: fix NULL dereference in
|
|
||||||
fbcon_cursor()"
|
|
||||||
|
|
||||||
This reverts commit 61f0c3e8098facbec81dcc32508d58c8611cb799.
|
|
||||||
---
|
|
||||||
drivers/video/fbdev/core/fbcon.c | 3 ---
|
|
||||||
1 file changed, 3 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
|
|
||||||
index 26581194fdf8..8d1ae973041a 100644
|
|
||||||
--- a/drivers/video/fbdev/core/fbcon.c
|
|
||||||
+++ b/drivers/video/fbdev/core/fbcon.c
|
|
||||||
@@ -1344,9 +1344,6 @@ static void fbcon_cursor(struct vc_data *vc, int mode)
|
|
||||||
|
|
||||||
ops->cursor_flash = (mode == CM_ERASE) ? 0 : 1;
|
|
||||||
|
|
||||||
- if (!ops->cursor)
|
|
||||||
- return;
|
|
||||||
-
|
|
||||||
ops->cursor(vc, info, mode, get_color(vc, info, c, 1),
|
|
||||||
get_color(vc, info, c, 0));
|
|
||||||
}
|
|
||||||
--
|
|
||||||
2.25.1
|
|
||||||
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
From 1703e0e113025614c66dee8eb575aa67861934cd Mon Sep 17 00:00:00 2001
|
|
||||||
From: Igor Pecovnik <igor.pecovnik@gmail.com>
|
|
||||||
Date: Thu, 10 Feb 2022 19:26:33 +0100
|
|
||||||
Subject: [PATCH] Revert "fbcon: remove no-op fbcon_set_origin()"
|
|
||||||
|
|
||||||
This reverts commit bfeb28539d1f61829232883ced0986569218c4de.
|
|
||||||
---
|
|
||||||
drivers/video/fbdev/core/fbcon.c | 8 ++++++++
|
|
||||||
1 file changed, 8 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
|
|
||||||
index ad0862d6c1a9..6fea22c4642c 100644
|
|
||||||
--- a/drivers/video/fbdev/core/fbcon.c
|
|
||||||
+++ b/drivers/video/fbdev/core/fbcon.c
|
|
||||||
@@ -163,6 +163,8 @@ static const struct consw fb_con;
|
|
||||||
|
|
||||||
#define advance_row(p, delta) (unsigned short *)((unsigned long)(p) + (delta) * vc->vc_size_row)
|
|
||||||
|
|
||||||
+static int fbcon_set_origin(struct vc_data *);
|
|
||||||
+
|
|
||||||
static int fbcon_cursor_noblink;
|
|
||||||
|
|
||||||
#define divides(a, b) ((!(a) || (b)%(a)) ? 0 : 1)
|
|
||||||
@@ -2633,6 +2635,11 @@ static void fbcon_invert_region(struct vc_data *vc, u16 * p, int cnt)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
+static int fbcon_set_origin(struct vc_data *vc)
|
|
||||||
+{
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
void fbcon_suspended(struct fb_info *info)
|
|
||||||
{
|
|
||||||
struct vc_data *vc = NULL;
|
|
||||||
@@ -3103,6 +3110,7 @@ static const struct consw fb_con = {
|
|
||||||
.con_font_default = fbcon_set_def_font,
|
|
||||||
.con_font_copy = fbcon_copy_font,
|
|
||||||
.con_set_palette = fbcon_set_palette,
|
|
||||||
+ .con_set_origin = fbcon_set_origin,
|
|
||||||
.con_invert_region = fbcon_invert_region,
|
|
||||||
.con_screen_pos = fbcon_screen_pos,
|
|
||||||
.con_getxy = fbcon_getxy,
|
|
||||||
--
|
|
||||||
2.25.1
|
|
||||||
|
|
||||||
@@ -1,184 +0,0 @@
|
|||||||
From 103bdb34be969b844d4854733adc47cdd5d7d236 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Igor Pecovnik <igor.pecovnik@gmail.com>
|
|
||||||
Date: Mon, 21 Sep 2020 17:15:30 +0200
|
|
||||||
Subject: [PATCH 2/3] Revert "fbcon: remove now unusued 'softback_lines'
|
|
||||||
cursor() argument"
|
|
||||||
|
|
||||||
This reverts commit ffa74c8e58b8f42b2d95b29443befba2e28fb260.
|
|
||||||
---
|
|
||||||
drivers/video/fbdev/core/bitblit.c | 11 ++++++++++-
|
|
||||||
drivers/video/fbdev/core/fbcon.c | 4 ++--
|
|
||||||
drivers/video/fbdev/core/fbcon.h | 2 +-
|
|
||||||
drivers/video/fbdev/core/fbcon_ccw.c | 11 ++++++++++-
|
|
||||||
drivers/video/fbdev/core/fbcon_cw.c | 11 ++++++++++-
|
|
||||||
drivers/video/fbdev/core/fbcon_ud.c | 11 ++++++++++-
|
|
||||||
drivers/video/fbdev/core/tileblit.c | 2 +-
|
|
||||||
7 files changed, 44 insertions(+), 8 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/drivers/video/fbdev/core/bitblit.c b/drivers/video/fbdev/core/bitblit.c
|
|
||||||
index 436365efae73..35ebeeccde4d 100644
|
|
||||||
--- a/drivers/video/fbdev/core/bitblit.c
|
|
||||||
+++ b/drivers/video/fbdev/core/bitblit.c
|
|
||||||
@@ -234,7 +234,7 @@ static void bit_clear_margins(struct vc_data *vc, struct fb_info *info,
|
|
||||||
}
|
|
||||||
|
|
||||||
static void bit_cursor(struct vc_data *vc, struct fb_info *info, int mode,
|
|
||||||
- int fg, int bg)
|
|
||||||
+ int softback_lines, int fg, int bg)
|
|
||||||
{
|
|
||||||
struct fb_cursor cursor;
|
|
||||||
struct fbcon_ops *ops = info->fbcon_par;
|
|
||||||
@@ -247,6 +247,15 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, int mode,
|
|
||||||
|
|
||||||
cursor.set = 0;
|
|
||||||
|
|
||||||
+ if (softback_lines) {
|
|
||||||
+ if (y + softback_lines >= vc->vc_rows) {
|
|
||||||
+ mode = CM_ERASE;
|
|
||||||
+ ops->cursor_flash = 0;
|
|
||||||
+ return;
|
|
||||||
+ } else
|
|
||||||
+ y += softback_lines;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
c = scr_readw((u16 *) vc->vc_pos);
|
|
||||||
attribute = get_attribute(info, c);
|
|
||||||
src = vc->vc_font.data + ((c & charmask) * (w * vc->vc_font.height));
|
|
||||||
diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
|
|
||||||
index b36bfe10c712..b30a667663ef 100644
|
|
||||||
--- a/drivers/video/fbdev/core/fbcon.c
|
|
||||||
+++ b/drivers/video/fbdev/core/fbcon.c
|
|
||||||
@@ -394,7 +394,7 @@ static void fb_flashcursor(struct work_struct *work)
|
|
||||||
c = scr_readw((u16 *) vc->vc_pos);
|
|
||||||
mode = (!ops->cursor_flash || ops->cursor_state.enable) ?
|
|
||||||
CM_ERASE : CM_DRAW;
|
|
||||||
- ops->cursor(vc, info, mode, get_color(vc, info, c, 1),
|
|
||||||
+ ops->cursor(vc, info, mode, 0, get_color(vc, info, c, 1),
|
|
||||||
get_color(vc, info, c, 0));
|
|
||||||
console_unlock();
|
|
||||||
}
|
|
||||||
@@ -1345,7 +1345,7 @@ static void fbcon_cursor(struct vc_data *vc, int mode)
|
|
||||||
|
|
||||||
ops->cursor_flash = (mode == CM_ERASE) ? 0 : 1;
|
|
||||||
|
|
||||||
- ops->cursor(vc, info, mode, get_color(vc, info, c, 1),
|
|
||||||
+ ops->cursor(vc, info, mode, 0, get_color(vc, info, c, 1),
|
|
||||||
get_color(vc, info, c, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
diff --git a/drivers/video/fbdev/core/fbcon.h b/drivers/video/fbdev/core/fbcon.h
|
|
||||||
index 78bb14c03643..20dea853765f 100644
|
|
||||||
--- a/drivers/video/fbdev/core/fbcon.h
|
|
||||||
+++ b/drivers/video/fbdev/core/fbcon.h
|
|
||||||
@@ -62,7 +62,7 @@ struct fbcon_ops {
|
|
||||||
void (*clear_margins)(struct vc_data *vc, struct fb_info *info,
|
|
||||||
int color, int bottom_only);
|
|
||||||
void (*cursor)(struct vc_data *vc, struct fb_info *info, int mode,
|
|
||||||
- int fg, int bg);
|
|
||||||
+ int softback_lines, int fg, int bg);
|
|
||||||
int (*update_start)(struct fb_info *info);
|
|
||||||
int (*rotate_font)(struct fb_info *info, struct vc_data *vc);
|
|
||||||
struct fb_var_screeninfo var; /* copy of the current fb_var_screeninfo */
|
|
||||||
diff --git a/drivers/video/fbdev/core/fbcon_ccw.c b/drivers/video/fbdev/core/fbcon_ccw.c
|
|
||||||
index 71ad6967a70e..78f3a5621478 100644
|
|
||||||
--- a/drivers/video/fbdev/core/fbcon_ccw.c
|
|
||||||
+++ b/drivers/video/fbdev/core/fbcon_ccw.c
|
|
||||||
@@ -219,7 +219,7 @@ static void ccw_clear_margins(struct vc_data *vc, struct fb_info *info,
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ccw_cursor(struct vc_data *vc, struct fb_info *info, int mode,
|
|
||||||
- int fg, int bg)
|
|
||||||
+ int softback_lines, int fg, int bg)
|
|
||||||
{
|
|
||||||
struct fb_cursor cursor;
|
|
||||||
struct fbcon_ops *ops = info->fbcon_par;
|
|
||||||
@@ -236,6 +236,15 @@ static void ccw_cursor(struct vc_data *vc, struct fb_info *info, int mode,
|
|
||||||
|
|
||||||
cursor.set = 0;
|
|
||||||
|
|
||||||
+ if (softback_lines) {
|
|
||||||
+ if (y + softback_lines >= vc->vc_rows) {
|
|
||||||
+ mode = CM_ERASE;
|
|
||||||
+ ops->cursor_flash = 0;
|
|
||||||
+ return;
|
|
||||||
+ } else
|
|
||||||
+ y += softback_lines;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
c = scr_readw((u16 *) vc->vc_pos);
|
|
||||||
attribute = get_attribute(info, c);
|
|
||||||
src = ops->fontbuffer + ((c & charmask) * (w * vc->vc_font.width));
|
|
||||||
diff --git a/drivers/video/fbdev/core/fbcon_cw.c b/drivers/video/fbdev/core/fbcon_cw.c
|
|
||||||
index 31fe5dd651d4..fd098ff17574 100644
|
|
||||||
--- a/drivers/video/fbdev/core/fbcon_cw.c
|
|
||||||
+++ b/drivers/video/fbdev/core/fbcon_cw.c
|
|
||||||
@@ -202,7 +202,7 @@ static void cw_clear_margins(struct vc_data *vc, struct fb_info *info,
|
|
||||||
}
|
|
||||||
|
|
||||||
static void cw_cursor(struct vc_data *vc, struct fb_info *info, int mode,
|
|
||||||
- int fg, int bg)
|
|
||||||
+ int softback_lines, int fg, int bg)
|
|
||||||
{
|
|
||||||
struct fb_cursor cursor;
|
|
||||||
struct fbcon_ops *ops = info->fbcon_par;
|
|
||||||
@@ -219,6 +219,15 @@ static void cw_cursor(struct vc_data *vc, struct fb_info *info, int mode,
|
|
||||||
|
|
||||||
cursor.set = 0;
|
|
||||||
|
|
||||||
+ if (softback_lines) {
|
|
||||||
+ if (y + softback_lines >= vc->vc_rows) {
|
|
||||||
+ mode = CM_ERASE;
|
|
||||||
+ ops->cursor_flash = 0;
|
|
||||||
+ return;
|
|
||||||
+ } else
|
|
||||||
+ y += softback_lines;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
c = scr_readw((u16 *) vc->vc_pos);
|
|
||||||
attribute = get_attribute(info, c);
|
|
||||||
src = ops->fontbuffer + ((c & charmask) * (w * vc->vc_font.width));
|
|
||||||
diff --git a/drivers/video/fbdev/core/fbcon_ud.c b/drivers/video/fbdev/core/fbcon_ud.c
|
|
||||||
index b2dd1370e39b..e165a3fad29a 100644
|
|
||||||
--- a/drivers/video/fbdev/core/fbcon_ud.c
|
|
||||||
+++ b/drivers/video/fbdev/core/fbcon_ud.c
|
|
||||||
@@ -249,7 +249,7 @@ static void ud_clear_margins(struct vc_data *vc, struct fb_info *info,
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ud_cursor(struct vc_data *vc, struct fb_info *info, int mode,
|
|
||||||
- int fg, int bg)
|
|
||||||
+ int softback_lines, int fg, int bg)
|
|
||||||
{
|
|
||||||
struct fb_cursor cursor;
|
|
||||||
struct fbcon_ops *ops = info->fbcon_par;
|
|
||||||
@@ -267,6 +267,15 @@ static void ud_cursor(struct vc_data *vc, struct fb_info *info, int mode,
|
|
||||||
|
|
||||||
cursor.set = 0;
|
|
||||||
|
|
||||||
+ if (softback_lines) {
|
|
||||||
+ if (y + softback_lines >= vc->vc_rows) {
|
|
||||||
+ mode = CM_ERASE;
|
|
||||||
+ ops->cursor_flash = 0;
|
|
||||||
+ return;
|
|
||||||
+ } else
|
|
||||||
+ y += softback_lines;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
c = scr_readw((u16 *) vc->vc_pos);
|
|
||||||
attribute = get_attribute(info, c);
|
|
||||||
src = ops->fontbuffer + ((c & charmask) * (w * vc->vc_font.height));
|
|
||||||
diff --git a/drivers/video/fbdev/core/tileblit.c b/drivers/video/fbdev/core/tileblit.c
|
|
||||||
index eb664dbf96f6..93390312957f 100644
|
|
||||||
--- a/drivers/video/fbdev/core/tileblit.c
|
|
||||||
+++ b/drivers/video/fbdev/core/tileblit.c
|
|
||||||
@@ -80,7 +80,7 @@ static void tile_clear_margins(struct vc_data *vc, struct fb_info *info,
|
|
||||||
}
|
|
||||||
|
|
||||||
static void tile_cursor(struct vc_data *vc, struct fb_info *info, int mode,
|
|
||||||
- int fg, int bg)
|
|
||||||
+ int softback_lines, int fg, int bg)
|
|
||||||
{
|
|
||||||
struct fb_tilecursor cursor;
|
|
||||||
int use_sw = (vc->vc_cursor_type & 0x10);
|
|
||||||
--
|
|
||||||
2.25.1
|
|
||||||
|
|
||||||
@@ -1,502 +0,0 @@
|
|||||||
From b204d7d23b3d15b338207b37930ebbe0141007ce Mon Sep 17 00:00:00 2001
|
|
||||||
From: Igor Pecovnik <igor.pecovnik@gmail.com>
|
|
||||||
Date: Mon, 21 Sep 2020 17:15:44 +0200
|
|
||||||
Subject: [PATCH 3/3] Revert "fbcon: remove soft scrollback code"
|
|
||||||
|
|
||||||
This reverts commit 245a228891e3627e47921db1ec1b6612f118158b.
|
|
||||||
---
|
|
||||||
drivers/video/fbdev/core/fbcon.c | 334 ++++++++++++++++++++++++++++++-
|
|
||||||
1 file changed, 330 insertions(+), 4 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
|
|
||||||
index b30a667663ef..fbf10e62bcde 100644
|
|
||||||
--- a/drivers/video/fbdev/core/fbcon.c
|
|
||||||
+++ b/drivers/video/fbdev/core/fbcon.c
|
|
||||||
@@ -122,6 +122,12 @@ static int logo_lines;
|
|
||||||
/* logo_shown is an index to vc_cons when >= 0; otherwise follows FBCON_LOGO
|
|
||||||
enums. */
|
|
||||||
static int logo_shown = FBCON_LOGO_CANSHOW;
|
|
||||||
+/* Software scrollback */
|
|
||||||
+static int fbcon_softback_size = 32768;
|
|
||||||
+static unsigned long softback_buf, softback_curr;
|
|
||||||
+static unsigned long softback_in;
|
|
||||||
+static unsigned long softback_top, softback_end;
|
|
||||||
+static int softback_lines;
|
|
||||||
/* console mappings */
|
|
||||||
static int first_fb_vc;
|
|
||||||
static int last_fb_vc = MAX_NR_CONSOLES - 1;
|
|
||||||
@@ -161,6 +167,8 @@ static int margin_color;
|
|
||||||
|
|
||||||
static const struct consw fb_con;
|
|
||||||
|
|
||||||
+#define CM_SOFTBACK (8)
|
|
||||||
+
|
|
||||||
#define advance_row(p, delta) (unsigned short *)((unsigned long)(p) + (delta) * vc->vc_size_row)
|
|
||||||
|
|
||||||
static int fbcon_set_origin(struct vc_data *);
|
|
||||||
@@ -365,6 +373,18 @@ static int get_color(struct vc_data *vc, struct fb_info *info,
|
|
||||||
return color;
|
|
||||||
}
|
|
||||||
|
|
||||||
+static void fbcon_update_softback(struct vc_data *vc)
|
|
||||||
+{
|
|
||||||
+ int l = fbcon_softback_size / vc->vc_size_row;
|
|
||||||
+
|
|
||||||
+ if (l > 5)
|
|
||||||
+ softback_end = softback_buf + l * vc->vc_size_row;
|
|
||||||
+ else
|
|
||||||
+ /* Smaller scrollback makes no sense, and 0 would screw
|
|
||||||
+ the operation totally */
|
|
||||||
+ softback_top = 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static void fb_flashcursor(struct work_struct *work)
|
|
||||||
{
|
|
||||||
struct fb_info *info = container_of(work, struct fb_info, queue);
|
|
||||||
@@ -394,7 +414,7 @@ static void fb_flashcursor(struct work_struct *work)
|
|
||||||
c = scr_readw((u16 *) vc->vc_pos);
|
|
||||||
mode = (!ops->cursor_flash || ops->cursor_state.enable) ?
|
|
||||||
CM_ERASE : CM_DRAW;
|
|
||||||
- ops->cursor(vc, info, mode, 0, get_color(vc, info, c, 1),
|
|
||||||
+ ops->cursor(vc, info, mode, softback_lines, get_color(vc, info, c, 1),
|
|
||||||
get_color(vc, info, c, 0));
|
|
||||||
console_unlock();
|
|
||||||
}
|
|
||||||
@@ -451,7 +471,13 @@ static int __init fb_console_setup(char *this_opt)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!strncmp(options, "scrollback:", 11)) {
|
|
||||||
- pr_warn("Ignoring scrollback size option\n");
|
|
||||||
+ options += 11;
|
|
||||||
+ if (*options) {
|
|
||||||
+ fbcon_softback_size = simple_strtoul(options, &options, 0);
|
|
||||||
+ if (*options == 'k' || *options == 'K') {
|
|
||||||
+ fbcon_softback_size *= 1024;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -996,6 +1022,31 @@ static const char *fbcon_startup(void)
|
|
||||||
|
|
||||||
set_blitting_type(vc, info);
|
|
||||||
|
|
||||||
+ if (info->fix.type != FB_TYPE_TEXT) {
|
|
||||||
+ if (fbcon_softback_size) {
|
|
||||||
+ if (!softback_buf) {
|
|
||||||
+ softback_buf =
|
|
||||||
+ (unsigned long)
|
|
||||||
+ kvmalloc(fbcon_softback_size,
|
|
||||||
+ GFP_KERNEL);
|
|
||||||
+ if (!softback_buf) {
|
|
||||||
+ fbcon_softback_size = 0;
|
|
||||||
+ softback_top = 0;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ } else {
|
|
||||||
+ if (softback_buf) {
|
|
||||||
+ kvfree((void *) softback_buf);
|
|
||||||
+ softback_buf = 0;
|
|
||||||
+ softback_top = 0;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ if (softback_buf)
|
|
||||||
+ softback_in = softback_top = softback_curr =
|
|
||||||
+ softback_buf;
|
|
||||||
+ softback_lines = 0;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
/* Setup default font */
|
|
||||||
if (!p->fontdata && !vc->vc_font.data) {
|
|
||||||
if (!fontname[0] || !(font = find_font(fontname)))
|
|
||||||
@@ -1169,6 +1220,9 @@ static void fbcon_init(struct vc_data *vc, int init)
|
|
||||||
if (logo)
|
|
||||||
fbcon_prepare_logo(vc, info, cols, rows, new_cols, new_rows);
|
|
||||||
|
|
||||||
+ if (vc == svc && softback_buf)
|
|
||||||
+ fbcon_update_softback(vc);
|
|
||||||
+
|
|
||||||
if (ops->rotate_font && ops->rotate_font(info, vc)) {
|
|
||||||
ops->rotate = FB_ROTATE_UR;
|
|
||||||
set_blitting_type(vc, info);
|
|
||||||
@@ -1331,6 +1385,7 @@ static void fbcon_cursor(struct vc_data *vc, int mode)
|
|
||||||
{
|
|
||||||
struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
|
|
||||||
struct fbcon_ops *ops = info->fbcon_par;
|
|
||||||
+ int y;
|
|
||||||
int c = scr_readw((u16 *) vc->vc_pos);
|
|
||||||
|
|
||||||
ops->cur_blink_jiffies = msecs_to_jiffies(vc->vc_cur_blink_ms);
|
|
||||||
@@ -1344,8 +1399,16 @@ static void fbcon_cursor(struct vc_data *vc, int mode)
|
|
||||||
fbcon_add_cursor_timer(info);
|
|
||||||
|
|
||||||
ops->cursor_flash = (mode == CM_ERASE) ? 0 : 1;
|
|
||||||
+ if (mode & CM_SOFTBACK) {
|
|
||||||
+ mode &= ~CM_SOFTBACK;
|
|
||||||
+ y = softback_lines;
|
|
||||||
+ } else {
|
|
||||||
+ if (softback_lines)
|
|
||||||
+ fbcon_set_origin(vc);
|
|
||||||
+ y = 0;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
- ops->cursor(vc, info, mode, 0, get_color(vc, info, c, 1),
|
|
||||||
+ ops->cursor(vc, info, mode, y, get_color(vc, info, c, 1),
|
|
||||||
get_color(vc, info, c, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1416,6 +1479,8 @@ static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var,
|
|
||||||
|
|
||||||
if (con_is_visible(vc)) {
|
|
||||||
update_screen(vc);
|
|
||||||
+ if (softback_buf)
|
|
||||||
+ fbcon_update_softback(vc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1553,6 +1618,99 @@ static __inline__ void ypan_down_redraw(struct vc_data *vc, int t, int count)
|
|
||||||
scrollback_current = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
+static void fbcon_redraw_softback(struct vc_data *vc, struct fbcon_display *p,
|
|
||||||
+ long delta)
|
|
||||||
+{
|
|
||||||
+ int count = vc->vc_rows;
|
|
||||||
+ unsigned short *d, *s;
|
|
||||||
+ unsigned long n;
|
|
||||||
+ int line = 0;
|
|
||||||
+
|
|
||||||
+ d = (u16 *) softback_curr;
|
|
||||||
+ if (d == (u16 *) softback_in)
|
|
||||||
+ d = (u16 *) vc->vc_origin;
|
|
||||||
+ n = softback_curr + delta * vc->vc_size_row;
|
|
||||||
+ softback_lines -= delta;
|
|
||||||
+ if (delta < 0) {
|
|
||||||
+ if (softback_curr < softback_top && n < softback_buf) {
|
|
||||||
+ n += softback_end - softback_buf;
|
|
||||||
+ if (n < softback_top) {
|
|
||||||
+ softback_lines -=
|
|
||||||
+ (softback_top - n) / vc->vc_size_row;
|
|
||||||
+ n = softback_top;
|
|
||||||
+ }
|
|
||||||
+ } else if (softback_curr >= softback_top
|
|
||||||
+ && n < softback_top) {
|
|
||||||
+ softback_lines -=
|
|
||||||
+ (softback_top - n) / vc->vc_size_row;
|
|
||||||
+ n = softback_top;
|
|
||||||
+ }
|
|
||||||
+ } else {
|
|
||||||
+ if (softback_curr > softback_in && n >= softback_end) {
|
|
||||||
+ n += softback_buf - softback_end;
|
|
||||||
+ if (n > softback_in) {
|
|
||||||
+ n = softback_in;
|
|
||||||
+ softback_lines = 0;
|
|
||||||
+ }
|
|
||||||
+ } else if (softback_curr <= softback_in && n > softback_in) {
|
|
||||||
+ n = softback_in;
|
|
||||||
+ softback_lines = 0;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ if (n == softback_curr)
|
|
||||||
+ return;
|
|
||||||
+ softback_curr = n;
|
|
||||||
+ s = (u16 *) softback_curr;
|
|
||||||
+ if (s == (u16 *) softback_in)
|
|
||||||
+ s = (u16 *) vc->vc_origin;
|
|
||||||
+ while (count--) {
|
|
||||||
+ unsigned short *start;
|
|
||||||
+ unsigned short *le;
|
|
||||||
+ unsigned short c;
|
|
||||||
+ int x = 0;
|
|
||||||
+ unsigned short attr = 1;
|
|
||||||
+
|
|
||||||
+ start = s;
|
|
||||||
+ le = advance_row(s, 1);
|
|
||||||
+ do {
|
|
||||||
+ c = scr_readw(s);
|
|
||||||
+ if (attr != (c & 0xff00)) {
|
|
||||||
+ attr = c & 0xff00;
|
|
||||||
+ if (s > start) {
|
|
||||||
+ fbcon_putcs(vc, start, s - start,
|
|
||||||
+ line, x);
|
|
||||||
+ x += s - start;
|
|
||||||
+ start = s;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ if (c == scr_readw(d)) {
|
|
||||||
+ if (s > start) {
|
|
||||||
+ fbcon_putcs(vc, start, s - start,
|
|
||||||
+ line, x);
|
|
||||||
+ x += s - start + 1;
|
|
||||||
+ start = s + 1;
|
|
||||||
+ } else {
|
|
||||||
+ x++;
|
|
||||||
+ start++;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ s++;
|
|
||||||
+ d++;
|
|
||||||
+ } while (s < le);
|
|
||||||
+ if (s > start)
|
|
||||||
+ fbcon_putcs(vc, start, s - start, line, x);
|
|
||||||
+ line++;
|
|
||||||
+ if (d == (u16 *) softback_end)
|
|
||||||
+ d = (u16 *) softback_buf;
|
|
||||||
+ if (d == (u16 *) softback_in)
|
|
||||||
+ d = (u16 *) vc->vc_origin;
|
|
||||||
+ if (s == (u16 *) softback_end)
|
|
||||||
+ s = (u16 *) softback_buf;
|
|
||||||
+ if (s == (u16 *) softback_in)
|
|
||||||
+ s = (u16 *) vc->vc_origin;
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static void fbcon_redraw_move(struct vc_data *vc, struct fbcon_display *p,
|
|
||||||
int line, int count, int dy)
|
|
||||||
{
|
|
||||||
@@ -1692,6 +1850,31 @@ static void fbcon_redraw(struct vc_data *vc, struct fbcon_display *p,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
+static inline void fbcon_softback_note(struct vc_data *vc, int t,
|
|
||||||
+ int count)
|
|
||||||
+{
|
|
||||||
+ unsigned short *p;
|
|
||||||
+
|
|
||||||
+ if (vc->vc_num != fg_console)
|
|
||||||
+ return;
|
|
||||||
+ p = (unsigned short *) (vc->vc_origin + t * vc->vc_size_row);
|
|
||||||
+
|
|
||||||
+ while (count) {
|
|
||||||
+ scr_memcpyw((u16 *) softback_in, p, vc->vc_size_row);
|
|
||||||
+ count--;
|
|
||||||
+ p = advance_row(p, 1);
|
|
||||||
+ softback_in += vc->vc_size_row;
|
|
||||||
+ if (softback_in == softback_end)
|
|
||||||
+ softback_in = softback_buf;
|
|
||||||
+ if (softback_in == softback_top) {
|
|
||||||
+ softback_top += vc->vc_size_row;
|
|
||||||
+ if (softback_top == softback_end)
|
|
||||||
+ softback_top = softback_buf;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ softback_curr = softback_in;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b,
|
|
||||||
enum con_scroll dir, unsigned int count)
|
|
||||||
{
|
|
||||||
@@ -1714,6 +1897,8 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b,
|
|
||||||
case SM_UP:
|
|
||||||
if (count > vc->vc_rows) /* Maximum realistic size */
|
|
||||||
count = vc->vc_rows;
|
|
||||||
+ if (softback_top)
|
|
||||||
+ fbcon_softback_note(vc, t, count);
|
|
||||||
if (logo_shown >= 0)
|
|
||||||
goto redraw_up;
|
|
||||||
switch (p->scrollmode) {
|
|
||||||
@@ -2084,6 +2269,14 @@ static int fbcon_switch(struct vc_data *vc)
|
|
||||||
info = registered_fb[con2fb_map[vc->vc_num]];
|
|
||||||
ops = info->fbcon_par;
|
|
||||||
|
|
||||||
+ if (softback_top) {
|
|
||||||
+ if (softback_lines)
|
|
||||||
+ fbcon_set_origin(vc);
|
|
||||||
+ softback_top = softback_curr = softback_in = softback_buf;
|
|
||||||
+ softback_lines = 0;
|
|
||||||
+ fbcon_update_softback(vc);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
if (logo_shown >= 0) {
|
|
||||||
struct vc_data *conp2 = vc_cons[logo_shown].d;
|
|
||||||
|
|
||||||
@@ -2407,6 +2600,9 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h,
|
|
||||||
int cnt;
|
|
||||||
char *old_data = NULL;
|
|
||||||
|
|
||||||
+ if (con_is_visible(vc) && softback_lines)
|
|
||||||
+ fbcon_set_origin(vc);
|
|
||||||
+
|
|
||||||
resize = (w != vc->vc_font.width) || (h != vc->vc_font.height);
|
|
||||||
if (p->userfont)
|
|
||||||
old_data = vc->vc_font.data;
|
|
||||||
@@ -2432,6 +2628,8 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h,
|
|
||||||
cols /= w;
|
|
||||||
rows /= h;
|
|
||||||
vc_resize(vc, cols, rows);
|
|
||||||
+ if (con_is_visible(vc) && softback_buf)
|
|
||||||
+ fbcon_update_softback(vc);
|
|
||||||
} else if (con_is_visible(vc)
|
|
||||||
&& vc->vc_mode == KD_TEXT) {
|
|
||||||
fbcon_clear_margins(vc, 0);
|
|
||||||
@@ -2590,7 +2788,19 @@ static void fbcon_set_palette(struct vc_data *vc, const unsigned char *table)
|
|
||||||
|
|
||||||
static u16 *fbcon_screen_pos(struct vc_data *vc, int offset)
|
|
||||||
{
|
|
||||||
- return (u16 *) (vc->vc_origin + offset);
|
|
||||||
+ unsigned long p;
|
|
||||||
+ int line;
|
|
||||||
+
|
|
||||||
+ if (vc->vc_num != fg_console || !softback_lines)
|
|
||||||
+ return (u16 *) (vc->vc_origin + offset);
|
|
||||||
+ line = offset / vc->vc_size_row;
|
|
||||||
+ if (line >= softback_lines)
|
|
||||||
+ return (u16 *) (vc->vc_origin + offset -
|
|
||||||
+ softback_lines * vc->vc_size_row);
|
|
||||||
+ p = softback_curr + offset;
|
|
||||||
+ if (p >= softback_end)
|
|
||||||
+ p += softback_buf - softback_end;
|
|
||||||
+ return (u16 *) p;
|
|
||||||
}
|
|
||||||
|
|
||||||
static unsigned long fbcon_getxy(struct vc_data *vc, unsigned long pos,
|
|
||||||
@@ -2604,7 +2814,22 @@ static unsigned long fbcon_getxy(struct vc_data *vc, unsigned long pos,
|
|
||||||
|
|
||||||
x = offset % vc->vc_cols;
|
|
||||||
y = offset / vc->vc_cols;
|
|
||||||
+ if (vc->vc_num == fg_console)
|
|
||||||
+ y += softback_lines;
|
|
||||||
ret = pos + (vc->vc_cols - x) * 2;
|
|
||||||
+ } else if (vc->vc_num == fg_console && softback_lines) {
|
|
||||||
+ unsigned long offset = pos - softback_curr;
|
|
||||||
+
|
|
||||||
+ if (pos < softback_curr)
|
|
||||||
+ offset += softback_end - softback_buf;
|
|
||||||
+ offset /= 2;
|
|
||||||
+ x = offset % vc->vc_cols;
|
|
||||||
+ y = offset / vc->vc_cols;
|
|
||||||
+ ret = pos + (vc->vc_cols - x) * 2;
|
|
||||||
+ if (ret == softback_end)
|
|
||||||
+ ret = softback_buf;
|
|
||||||
+ if (ret == softback_in)
|
|
||||||
+ ret = vc->vc_origin;
|
|
||||||
} else {
|
|
||||||
/* Should not happen */
|
|
||||||
x = y = 0;
|
|
||||||
@@ -2632,11 +2857,106 @@ static void fbcon_invert_region(struct vc_data *vc, u16 * p, int cnt)
|
|
||||||
a = ((a) & 0x88ff) | (((a) & 0x7000) >> 4) |
|
|
||||||
(((a) & 0x0700) << 4);
|
|
||||||
scr_writew(a, p++);
|
|
||||||
+ if (p == (u16 *) softback_end)
|
|
||||||
+ p = (u16 *) softback_buf;
|
|
||||||
+ if (p == (u16 *) softback_in)
|
|
||||||
+ p = (u16 *) vc->vc_origin;
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void fbcon_scrolldelta(struct vc_data *vc, int lines)
|
|
||||||
+{
|
|
||||||
+ struct fb_info *info = registered_fb[con2fb_map[fg_console]];
|
|
||||||
+ struct fbcon_ops *ops = info->fbcon_par;
|
|
||||||
+ struct fbcon_display *disp = &fb_display[fg_console];
|
|
||||||
+ int offset, limit, scrollback_old;
|
|
||||||
+
|
|
||||||
+ if (softback_top) {
|
|
||||||
+ if (vc->vc_num != fg_console)
|
|
||||||
+ return;
|
|
||||||
+ if (vc->vc_mode != KD_TEXT || !lines)
|
|
||||||
+ return;
|
|
||||||
+ if (logo_shown >= 0) {
|
|
||||||
+ struct vc_data *conp2 = vc_cons[logo_shown].d;
|
|
||||||
+
|
|
||||||
+ if (conp2->vc_top == logo_lines
|
|
||||||
+ && conp2->vc_bottom == conp2->vc_rows)
|
|
||||||
+ conp2->vc_top = 0;
|
|
||||||
+ if (logo_shown == vc->vc_num) {
|
|
||||||
+ unsigned long p, q;
|
|
||||||
+ int i;
|
|
||||||
+
|
|
||||||
+ p = softback_in;
|
|
||||||
+ q = vc->vc_origin +
|
|
||||||
+ logo_lines * vc->vc_size_row;
|
|
||||||
+ for (i = 0; i < logo_lines; i++) {
|
|
||||||
+ if (p == softback_top)
|
|
||||||
+ break;
|
|
||||||
+ if (p == softback_buf)
|
|
||||||
+ p = softback_end;
|
|
||||||
+ p -= vc->vc_size_row;
|
|
||||||
+ q -= vc->vc_size_row;
|
|
||||||
+ scr_memcpyw((u16 *) q, (u16 *) p,
|
|
||||||
+ vc->vc_size_row);
|
|
||||||
+ }
|
|
||||||
+ softback_in = softback_curr = p;
|
|
||||||
+ update_region(vc, vc->vc_origin,
|
|
||||||
+ logo_lines * vc->vc_cols);
|
|
||||||
+ }
|
|
||||||
+ logo_shown = FBCON_LOGO_CANSHOW;
|
|
||||||
+ }
|
|
||||||
+ fbcon_cursor(vc, CM_ERASE | CM_SOFTBACK);
|
|
||||||
+ fbcon_redraw_softback(vc, disp, lines);
|
|
||||||
+ fbcon_cursor(vc, CM_DRAW | CM_SOFTBACK);
|
|
||||||
+ return;
|
|
||||||
}
|
|
||||||
+
|
|
||||||
+ if (!scrollback_phys_max)
|
|
||||||
+ return;
|
|
||||||
+
|
|
||||||
+ scrollback_old = scrollback_current;
|
|
||||||
+ scrollback_current -= lines;
|
|
||||||
+ if (scrollback_current < 0)
|
|
||||||
+ scrollback_current = 0;
|
|
||||||
+ else if (scrollback_current > scrollback_max)
|
|
||||||
+ scrollback_current = scrollback_max;
|
|
||||||
+ if (scrollback_current == scrollback_old)
|
|
||||||
+ return;
|
|
||||||
+
|
|
||||||
+ if (fbcon_is_inactive(vc, info))
|
|
||||||
+ return;
|
|
||||||
+
|
|
||||||
+ fbcon_cursor(vc, CM_ERASE);
|
|
||||||
+
|
|
||||||
+ offset = disp->yscroll - scrollback_current;
|
|
||||||
+ limit = disp->vrows;
|
|
||||||
+ switch (disp->scrollmode) {
|
|
||||||
+ case SCROLL_WRAP_MOVE:
|
|
||||||
+ info->var.vmode |= FB_VMODE_YWRAP;
|
|
||||||
+ break;
|
|
||||||
+ case SCROLL_PAN_MOVE:
|
|
||||||
+ case SCROLL_PAN_REDRAW:
|
|
||||||
+ limit -= vc->vc_rows;
|
|
||||||
+ info->var.vmode &= ~FB_VMODE_YWRAP;
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
+ if (offset < 0)
|
|
||||||
+ offset += limit;
|
|
||||||
+ else if (offset >= limit)
|
|
||||||
+ offset -= limit;
|
|
||||||
+
|
|
||||||
+ ops->var.xoffset = 0;
|
|
||||||
+ ops->var.yoffset = offset * vc->vc_font.height;
|
|
||||||
+ ops->update_start(info);
|
|
||||||
+
|
|
||||||
+ if (!scrollback_current)
|
|
||||||
+ fbcon_cursor(vc, CM_DRAW);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int fbcon_set_origin(struct vc_data *vc)
|
|
||||||
{
|
|
||||||
+ if (softback_lines)
|
|
||||||
+ fbcon_scrolldelta(vc, softback_lines);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -2700,6 +3020,8 @@ static void fbcon_modechanged(struct fb_info *info)
|
|
||||||
|
|
||||||
fbcon_set_palette(vc, color_table);
|
|
||||||
update_screen(vc);
|
|
||||||
+ if (softback_buf)
|
|
||||||
+ fbcon_update_softback(vc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -3110,6 +3432,7 @@ static const struct consw fb_con = {
|
|
||||||
.con_font_default = fbcon_set_def_font,
|
|
||||||
.con_font_copy = fbcon_copy_font,
|
|
||||||
.con_set_palette = fbcon_set_palette,
|
|
||||||
+ .con_scrolldelta = fbcon_scrolldelta,
|
|
||||||
.con_set_origin = fbcon_set_origin,
|
|
||||||
.con_invert_region = fbcon_invert_region,
|
|
||||||
.con_screen_pos = fbcon_screen_pos,
|
|
||||||
--
|
|
||||||
2.25.1
|
|
||||||
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
Revert "fbcon: Fix accelerated fbdev scrolling while logo is still shown"
|
|
||||||
|
|
||||||
This reverts commit 3866cba87dcd0162fb41e9b3b653d0af68fad5ec.
|
|
||||||
---
|
|
||||||
drivers/video/fbdev/core/fbcon.c | 4 ++++
|
|
||||||
1 file changed, 4 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
|
|
||||||
index cf9ac4da0a82..0636d05c519c 100644
|
|
||||||
--- a/drivers/video/fbdev/core/fbcon.c
|
|
||||||
+++ b/drivers/video/fbdev/core/fbcon.c
|
|
||||||
@@ -1760,6 +1760,8 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b,
|
|
||||||
case SM_UP:
|
|
||||||
if (count > vc->vc_rows) /* Maximum realistic size */
|
|
||||||
count = vc->vc_rows;
|
|
||||||
+ if (logo_shown >= 0)
|
|
||||||
+ goto redraw_up;
|
|
||||||
switch (fb_scrollmode(p)) {
|
|
||||||
case SCROLL_MOVE:
|
|
||||||
fbcon_redraw_blit(vc, info, p, t, b - t - count,
|
|
||||||
@@ -1848,6 +1850,8 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b,
|
|
||||||
case SM_DOWN:
|
|
||||||
if (count > vc->vc_rows) /* Maximum realistic size */
|
|
||||||
count = vc->vc_rows;
|
|
||||||
+ if (logo_shown >= 0)
|
|
||||||
+ goto redraw_down;
|
|
||||||
switch (fb_scrollmode(p)) {
|
|
||||||
case SCROLL_MOVE:
|
|
||||||
fbcon_redraw_blit(vc, info, p, b - 1, b - t - count,
|
|
||||||
--
|
|
||||||
2.25.1
|
|
||||||
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
From 34329038e08a285761f74d454c2a050788b9323c Mon Sep 17 00:00:00 2001
|
|
||||||
From: Igor Pecovnik <igor.pecovnik@gmail.com>
|
|
||||||
Date: Mon, 5 Sep 2022 08:37:35 +0200
|
|
||||||
Subject: [PATCH] Revert "fbdev: fbcon: Properly revert changes when
|
|
||||||
vc_resize() failed"
|
|
||||||
|
|
||||||
This reverts commit f08ccb792d3eaf1dc62d8cbf6a30d6522329f660.
|
|
||||||
---
|
|
||||||
drivers/video/fbdev/core/fbcon.c | 27 ++-------------------------
|
|
||||||
1 file changed, 2 insertions(+), 25 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
|
|
||||||
index 2efaed36a3ad..b89075f3b6ab 100644
|
|
||||||
--- a/drivers/video/fbdev/core/fbcon.c
|
|
||||||
+++ b/drivers/video/fbdev/core/fbcon.c
|
|
||||||
@@ -2402,21 +2402,15 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h, int charcount,
|
|
||||||
struct fb_info *info = fbcon_info_from_console(vc->vc_num);
|
|
||||||
struct fbcon_ops *ops = info->fbcon_par;
|
|
||||||
struct fbcon_display *p = &fb_display[vc->vc_num];
|
|
||||||
- int resize, ret, old_userfont, old_width, old_height, old_charcount;
|
|
||||||
+ int resize;
|
|
||||||
char *old_data = NULL;
|
|
||||||
|
|
||||||
resize = (w != vc->vc_font.width) || (h != vc->vc_font.height);
|
|
||||||
if (p->userfont)
|
|
||||||
old_data = vc->vc_font.data;
|
|
||||||
vc->vc_font.data = (void *)(p->fontdata = data);
|
|
||||||
- old_userfont = p->userfont;
|
|
||||||
if ((p->userfont = userfont))
|
|
||||||
REFCOUNT(data)++;
|
|
||||||
-
|
|
||||||
- old_width = vc->vc_font.width;
|
|
||||||
- old_height = vc->vc_font.height;
|
|
||||||
- old_charcount = vc->vc_font.charcount;
|
|
||||||
-
|
|
||||||
vc->vc_font.width = w;
|
|
||||||
vc->vc_font.height = h;
|
|
||||||
vc->vc_font.charcount = charcount;
|
|
||||||
@@ -2432,9 +2426,7 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h, int charcount,
|
|
||||||
rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
|
|
||||||
cols /= w;
|
|
||||||
rows /= h;
|
|
||||||
- ret = vc_resize(vc, cols, rows);
|
|
||||||
- if (ret)
|
|
||||||
- goto err_out;
|
|
||||||
+ vc_resize(vc, cols, rows);
|
|
||||||
} else if (con_is_visible(vc)
|
|
||||||
&& vc->vc_mode == KD_TEXT) {
|
|
||||||
fbcon_clear_margins(vc, 0);
|
|
||||||
@@ -2444,21 +2436,6 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h, int charcount,
|
|
||||||
if (old_data && (--REFCOUNT(old_data) == 0))
|
|
||||||
kfree(old_data - FONT_EXTRA_WORDS * sizeof(int));
|
|
||||||
return 0;
|
|
||||||
-
|
|
||||||
-err_out:
|
|
||||||
- p->fontdata = old_data;
|
|
||||||
- vc->vc_font.data = (void *)old_data;
|
|
||||||
-
|
|
||||||
- if (userfont) {
|
|
||||||
- p->userfont = old_userfont;
|
|
||||||
- REFCOUNT(data)--;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- vc->vc_font.width = old_width;
|
|
||||||
- vc->vc_font.height = old_height;
|
|
||||||
- vc->vc_font.charcount = old_charcount;
|
|
||||||
-
|
|
||||||
- return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
--
|
|
||||||
2.34.1
|
|
||||||
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
From 729b2d566888ddc24edd9887098b80af3fc4269f Mon Sep 17 00:00:00 2001
|
|
||||||
From: Igor Pecovnik <igor.pecovnik@gmail.com>
|
|
||||||
Date: Sat, 31 Dec 2022 14:27:32 +0100
|
|
||||||
Subject: [PATCH] Revert "fbdev: fbcon: release buffer when fbcon_do_set_font()
|
|
||||||
failed"
|
|
||||||
|
|
||||||
This reverts commit 88ec6d11052da527eb9268831e7a9bc5bbad02f6.
|
|
||||||
---
|
|
||||||
drivers/video/fbdev/core/fbcon.c | 3 +--
|
|
||||||
1 file changed, 1 insertion(+), 2 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
|
|
||||||
index df40360e04ff..1f37904b0405 100644
|
|
||||||
--- a/drivers/video/fbdev/core/fbcon.c
|
|
||||||
+++ b/drivers/video/fbdev/core/fbcon.c
|
|
||||||
@@ -2462,8 +2462,7 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h, int charcount,
|
|
||||||
|
|
||||||
if (userfont) {
|
|
||||||
p->userfont = old_userfont;
|
|
||||||
- if (--REFCOUNT(data) == 0)
|
|
||||||
- kfree(data - FONT_EXTRA_WORDS * sizeof(int));
|
|
||||||
+ REFCOUNT(data)--;
|
|
||||||
}
|
|
||||||
|
|
||||||
vc->vc_font.width = old_width;
|
|
||||||
--
|
|
||||||
2.34.1
|
|
||||||
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
--- a/arch/arm/kernel/asm-offsets.c
|
|
||||||
+++ b/arch/arm/kernel/asm-offsets.c
|
|
||||||
@@ -10,6 +10,7 @@
|
|
||||||
* it under the terms of the GNU General Public License version 2 as
|
|
||||||
* published by the Free Software Foundation.
|
|
||||||
*/
|
|
||||||
+#include <linux/compiler.h>
|
|
||||||
#include <linux/sched.h>
|
|
||||||
#include <linux/mm.h>
|
|
||||||
#include <linux/dma-mapping.h>
|
|
||||||
@@ -39,10 +40,19 @@
|
|
||||||
* GCC 3.2.x: miscompiles NEW_AUX_ENT in fs/binfmt_elf.c
|
|
||||||
* (http://gcc.gnu.org/PR8896) and incorrect structure
|
|
||||||
* initialisation in fs/jffs2/erase.c
|
|
||||||
+ * GCC 4.8.0-4.8.2: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58854
|
|
||||||
+ * miscompiles find_get_entry(), and can result in EXT3 and EXT4
|
|
||||||
+ * filesystem corruption (possibly other FS too).
|
|
||||||
*/
|
|
||||||
+#ifdef __GNUC__
|
|
||||||
#if (__GNUC__ == 3 && __GNUC_MINOR__ < 3)
|
|
||||||
#error Your compiler is too buggy; it is known to miscompile kernels.
|
|
||||||
-#error Known good compilers: 3.3
|
|
||||||
+#error Known good compilers: 3.3, 4.x
|
|
||||||
+#endif
|
|
||||||
+#if GCC_VERSION >= 40800 && GCC_VERSION < 40803
|
|
||||||
+#error Your compiler is too buggy; it is known to miscompile kernels
|
|
||||||
+#error and result in filesystem corruption and oopses.
|
|
||||||
+#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int main(void)
|
|
||||||
@@ -1,82 +0,0 @@
|
|||||||
diff --git a/drivers/staging/fbtft/fb_st7789v.c b/drivers/staging/fbtft/fb_st7789v.c
|
|
||||||
index 3c3f38793..3a280cc18 100644
|
|
||||||
--- a/drivers/staging/fbtft/fb_st7789v.c
|
|
||||||
+++ b/drivers/staging/fbtft/fb_st7789v.c
|
|
||||||
@@ -20,6 +20,12 @@
|
|
||||||
"70 2C 2E 15 10 09 48 33 53 0B 19 18 20 25\n" \
|
|
||||||
"70 2C 2E 15 10 09 48 33 53 0B 19 18 20 25"
|
|
||||||
|
|
||||||
+#define HSD20_IPS_GAMMA \
|
|
||||||
+ "D0 05 0A 09 08 05 2E 44 45 0F 17 16 2B 33\n" \
|
|
||||||
+ "D0 05 0A 09 08 05 2E 43 45 0F 16 16 2B 33"
|
|
||||||
+
|
|
||||||
+#define HSD20_IPS 1
|
|
||||||
+
|
|
||||||
/**
|
|
||||||
* enum st7789v_command - ST7789V display controller commands
|
|
||||||
*
|
|
||||||
@@ -82,14 +88,20 @@ static int init_display(struct fbtft_par *par)
|
|
||||||
|
|
||||||
/* set pixel format to RGB-565 */
|
|
||||||
write_reg(par, MIPI_DCS_SET_PIXEL_FORMAT, MIPI_DCS_PIXEL_FMT_16BIT);
|
|
||||||
+ if (HSD20_IPS)
|
|
||||||
+ write_reg(par, PORCTRL, 0x05, 0x05, 0x00, 0x33, 0x33);
|
|
||||||
|
|
||||||
- write_reg(par, PORCTRL, 0x08, 0x08, 0x00, 0x22, 0x22);
|
|
||||||
+ else
|
|
||||||
+ write_reg(par, PORCTRL, 0x08, 0x08, 0x00, 0x22, 0x22);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* VGH = 13.26V
|
|
||||||
* VGL = -10.43V
|
|
||||||
*/
|
|
||||||
- write_reg(par, GCTRL, 0x35);
|
|
||||||
+ if (HSD20_IPS)
|
|
||||||
+ write_reg(par, GCTRL, 0x75);
|
|
||||||
+ else
|
|
||||||
+ write_reg(par, GCTRL, 0x35);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* VDV and VRH register values come from command write
|
|
||||||
@@ -101,13 +113,19 @@ static int init_display(struct fbtft_par *par)
|
|
||||||
* VAP = 4.1V + (VCOM + VCOM offset + 0.5 * VDV)
|
|
||||||
* VAN = -4.1V + (VCOM + VCOM offset + 0.5 * VDV)
|
|
||||||
*/
|
|
||||||
- write_reg(par, VRHS, 0x0B);
|
|
||||||
+ if (HSD20_IPS)
|
|
||||||
+ write_reg(par, VRHS, 0x13);
|
|
||||||
+ else
|
|
||||||
+ write_reg(par, VRHS, 0x0B);
|
|
||||||
|
|
||||||
/* VDV = 0V */
|
|
||||||
write_reg(par, VDVS, 0x20);
|
|
||||||
|
|
||||||
/* VCOM = 0.9V */
|
|
||||||
- write_reg(par, VCOMS, 0x20);
|
|
||||||
+ if (HSD20_IPS)
|
|
||||||
+ write_reg(par, VCOMS, 0x22);
|
|
||||||
+ else
|
|
||||||
+ write_reg(par, VCOMS, 0x20);
|
|
||||||
|
|
||||||
/* VCOM offset = 0V */
|
|
||||||
write_reg(par, VCMOFSET, 0x20);
|
|
||||||
@@ -120,6 +138,10 @@ static int init_display(struct fbtft_par *par)
|
|
||||||
write_reg(par, PWCTRL1, 0xA4, 0xA1);
|
|
||||||
|
|
||||||
write_reg(par, MIPI_DCS_SET_DISPLAY_ON);
|
|
||||||
+
|
|
||||||
+ if (HSD20_IPS)
|
|
||||||
+ write_reg(par, MIPI_DCS_ENTER_INVERT_MODE);
|
|
||||||
+
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -234,7 +256,7 @@ static struct fbtft_display display = {
|
|
||||||
.height = 320,
|
|
||||||
.gamma_num = 2,
|
|
||||||
.gamma_len = 14,
|
|
||||||
- .gamma = DEFAULT_GAMMA,
|
|
||||||
+ .gamma = HSD20_IPS_GAMMA,
|
|
||||||
.fbtftops = {
|
|
||||||
.init_display = init_display,
|
|
||||||
.set_var = set_var,
|
|
||||||
@@ -1,250 +0,0 @@
|
|||||||
diff --git a/Documentation/networking/device_drivers/atm/cxacru-cf.py b/Documentation/networking/device_drivers/atm/cxacru-cf.py
|
|
||||||
index b41d298398c8..413b97579405 100644
|
|
||||||
--- a/Documentation/networking/device_drivers/atm/cxacru-cf.py
|
|
||||||
+++ b/Documentation/networking/device_drivers/atm/cxacru-cf.py
|
|
||||||
@@ -1,4 +1,4 @@
|
|
||||||
-#!/usr/bin/env python
|
|
||||||
+#!/usr/bin/env python2
|
|
||||||
# Copyright 2009 Simon Arlott
|
|
||||||
#
|
|
||||||
# This program is free software; you can redistribute it and/or modify it
|
|
||||||
diff --git a/Documentation/sphinx/maintainers_include.py b/Documentation/sphinx/maintainers_include.py
|
|
||||||
index dc8fed48d3c2..395a5728d86f 100755
|
|
||||||
--- a/Documentation/sphinx/maintainers_include.py
|
|
||||||
+++ b/Documentation/sphinx/maintainers_include.py
|
|
||||||
@@ -1,4 +1,4 @@
|
|
||||||
-#!/usr/bin/env python
|
|
||||||
+#!/usr/bin/env python2
|
|
||||||
# SPDX-License-Identifier: GPL-2.0
|
|
||||||
# -*- coding: utf-8; mode: python -*-
|
|
||||||
# pylint: disable=R0903, C0330, R0914, R0912, E0401
|
|
||||||
diff --git a/Documentation/target/tcm_mod_builder.py b/Documentation/target/tcm_mod_builder.py
|
|
||||||
index 54492aa813b9..277e24566923 100755
|
|
||||||
--- a/Documentation/target/tcm_mod_builder.py
|
|
||||||
+++ b/Documentation/target/tcm_mod_builder.py
|
|
||||||
@@ -1,4 +1,4 @@
|
|
||||||
-#!/usr/bin/env python
|
|
||||||
+#!/usr/bin/env python2
|
|
||||||
# The TCM v4 multi-protocol fabric module generation script for drivers/target/$NEW_MOD
|
|
||||||
#
|
|
||||||
# Copyright (c) 2010 Rising Tide Systems
|
|
||||||
diff --git a/Documentation/trace/postprocess/decode_msr.py b/Documentation/trace/postprocess/decode_msr.py
|
|
||||||
index aa9cc7abd5c2..7c9efdc5c353 100644
|
|
||||||
--- a/Documentation/trace/postprocess/decode_msr.py
|
|
||||||
+++ b/Documentation/trace/postprocess/decode_msr.py
|
|
||||||
@@ -1,4 +1,4 @@
|
|
||||||
-#!/usr/bin/env python
|
|
||||||
+#!/usr/bin/env python2
|
|
||||||
# add symbolic names to read_msr / write_msr in trace
|
|
||||||
# decode_msr msr-index.h < trace
|
|
||||||
import sys
|
|
||||||
diff --git a/Makefile b/Makefile
|
|
||||||
index 6bbc15bea093..09063da45379 100644
|
|
||||||
--- a/Makefile
|
|
||||||
+++ b/Makefile
|
|
||||||
@@ -468,7 +468,7 @@ AWK = awk
|
|
||||||
INSTALLKERNEL := installkernel
|
|
||||||
DEPMOD = depmod
|
|
||||||
PERL = perl
|
|
||||||
-PYTHON = python
|
|
||||||
+PYTHON = python2
|
|
||||||
PYTHON3 = python3
|
|
||||||
CHECK = sparse
|
|
||||||
BASH = bash
|
|
||||||
diff --git a/arch/ia64/scripts/unwcheck.py b/arch/ia64/scripts/unwcheck.py
|
|
||||||
index bfd1b671e35f..5f998048d68c 100644
|
|
||||||
--- a/arch/ia64/scripts/unwcheck.py
|
|
||||||
+++ b/arch/ia64/scripts/unwcheck.py
|
|
||||||
@@ -1,4 +1,4 @@
|
|
||||||
-#!/usr/bin/env python
|
|
||||||
+#!/usr/bin/env python2
|
|
||||||
# SPDX-License-Identifier: GPL-2.0
|
|
||||||
#
|
|
||||||
# Usage: unwcheck.py FILE
|
|
||||||
diff --git a/drivers/staging/greybus/tools/lbtest b/drivers/staging/greybus/tools/lbtest
|
|
||||||
index 47c481239e98..4b3773b97794 100755
|
|
||||||
--- a/drivers/staging/greybus/tools/lbtest
|
|
||||||
+++ b/drivers/staging/greybus/tools/lbtest
|
|
||||||
@@ -1,4 +1,4 @@
|
|
||||||
-#!/usr/bin/env python
|
|
||||||
+#!/usr/bin/env python2
|
|
||||||
# SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
|
|
||||||
# Copyright (c) 2015 Google, Inc.
|
|
||||||
diff --git a/scripts/bmpconvert b/scripts/bmpconvert
|
|
||||||
index 9863444da093..2d5b9b3bfe2c 100755
|
|
||||||
--- a/scripts/bmpconvert
|
|
||||||
+++ b/scripts/bmpconvert
|
|
||||||
@@ -1,4 +1,4 @@
|
|
||||||
-#!/usr/bin/env python
|
|
||||||
+#!/usr/bin/env python2
|
|
||||||
# SPDX-License-Identifier: GPL-2.0 */
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
|
|
||||||
index 0ad235ee96f9..3c2f0c1f0bac 100755
|
|
||||||
--- a/scripts/checkpatch.pl
|
|
||||||
+++ b/scripts/checkpatch.pl
|
|
||||||
@@ -910,10 +910,10 @@ sub is_maintained_obsolete {
|
|
||||||
sub is_SPDX_License_valid {
|
|
||||||
my ($license) = @_;
|
|
||||||
|
|
||||||
- return 1 if (!$tree || which("python") eq "" || !(-e "$root/scripts/spdxcheck.py") || !(-e "$gitroot"));
|
|
||||||
+ return 1 if (!$tree || which("python2") eq "" || !(-e "$root/scripts/spdxcheck.py") || !(-e "$gitroot"));
|
|
||||||
|
|
||||||
my $root_path = abs_path($root);
|
|
||||||
- my $status = `cd "$root_path"; echo "$license" | python scripts/spdxcheck.py -`;
|
|
||||||
+ my $status = `cd "$root_path"; echo "$license" | python2 scripts/spdxcheck.py -`;
|
|
||||||
return 0 if ($status ne "");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
diff --git a/scripts/clang-wrapper.py b/scripts/clang-wrapper.py
|
|
||||||
index 871aa5080bad..c5520905dab0 100755
|
|
||||||
--- a/scripts/clang-wrapper.py
|
|
||||||
+++ b/scripts/clang-wrapper.py
|
|
||||||
@@ -1,4 +1,4 @@
|
|
||||||
-#! /usr/bin/env python
|
|
||||||
+#! /usr/bin/env python2
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
# Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
|
|
||||||
diff --git a/scripts/gcc-wrapper.py b/scripts/gcc-wrapper.py
|
|
||||||
index ea74ea852242..c6853b5ee8b4 100755
|
|
||||||
--- a/scripts/gcc-wrapper.py
|
|
||||||
+++ b/scripts/gcc-wrapper.py
|
|
||||||
@@ -1,4 +1,4 @@
|
|
||||||
-#! /usr/bin/env python
|
|
||||||
+#! /usr/bin/env python2
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
# Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
|
|
||||||
diff --git a/scripts/jobserver-exec b/scripts/jobserver-exec
|
|
||||||
index 0fdb31a790a8..1dd35a8a277d 100755
|
|
||||||
--- a/scripts/jobserver-exec
|
|
||||||
+++ b/scripts/jobserver-exec
|
|
||||||
@@ -1,4 +1,4 @@
|
|
||||||
-#!/usr/bin/env python
|
|
||||||
+#!/usr/bin/env python2
|
|
||||||
# SPDX-License-Identifier: GPL-2.0+
|
|
||||||
#
|
|
||||||
# This determines how many parallel tasks "make" is expecting, as it is
|
|
||||||
diff --git a/scripts/mkbootimg b/scripts/mkbootimg
|
|
||||||
index 0c6093e19416..0d3464e8bbca 100755
|
|
||||||
--- a/scripts/mkbootimg
|
|
||||||
+++ b/scripts/mkbootimg
|
|
||||||
@@ -1,4 +1,4 @@
|
|
||||||
-#!/usr/bin/env python
|
|
||||||
+#!/usr/bin/env python2
|
|
||||||
# Copyright 2015, The Android Open Source Project
|
|
||||||
#
|
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
diff --git a/scripts/mkmultidtb.py b/scripts/mkmultidtb.py
|
|
||||||
index 81b814acd304..44ade858a8d0 100755
|
|
||||||
--- a/scripts/mkmultidtb.py
|
|
||||||
+++ b/scripts/mkmultidtb.py
|
|
||||||
@@ -1,4 +1,4 @@
|
|
||||||
-#!/usr/bin/env python
|
|
||||||
+#!/usr/bin/env python2
|
|
||||||
# SPDX-License-Identifier: (GPL-2.0+ OR MIT)
|
|
||||||
# Copyright (c) 2018 Fuzhou Rockchip Electronics Co., Ltd
|
|
||||||
#
|
|
||||||
diff --git a/scripts/show_delta b/scripts/show_delta
|
|
||||||
index 28e67e178194..a613571dad27 100755
|
|
||||||
--- a/scripts/show_delta
|
|
||||||
+++ b/scripts/show_delta
|
|
||||||
@@ -1,4 +1,4 @@
|
|
||||||
-#!/usr/bin/env python
|
|
||||||
+#!/usr/bin/env python2
|
|
||||||
# SPDX-License-Identifier: GPL-2.0-only
|
|
||||||
#
|
|
||||||
# show_deltas: Read list of printk messages instrumented with
|
|
||||||
diff --git a/scripts/spdxcheck.py b/scripts/spdxcheck.py
|
|
||||||
index bc87200f9c7c..9747c64288c4 100755
|
|
||||||
--- a/scripts/spdxcheck.py
|
|
||||||
+++ b/scripts/spdxcheck.py
|
|
||||||
@@ -1,4 +1,4 @@
|
|
||||||
-#!/usr/bin/env python
|
|
||||||
+#!/usr/bin/env python2
|
|
||||||
# SPDX-License-Identifier: GPL-2.0
|
|
||||||
# Copyright Thomas Gleixner <tglx@linutronix.de>
|
|
||||||
|
|
||||||
diff --git a/scripts/tracing/draw_functrace.py b/scripts/tracing/draw_functrace.py
|
|
||||||
index 7011fbe003ff..72001a9a9c76 100755
|
|
||||||
--- a/scripts/tracing/draw_functrace.py
|
|
||||||
+++ b/scripts/tracing/draw_functrace.py
|
|
||||||
@@ -1,4 +1,4 @@
|
|
||||||
-#!/usr/bin/env python
|
|
||||||
+#!/usr/bin/env python2
|
|
||||||
# SPDX-License-Identifier: GPL-2.0-only
|
|
||||||
|
|
||||||
"""
|
|
||||||
diff --git a/scripts/unpack_bootimg b/scripts/unpack_bootimg
|
|
||||||
index 83c2bbe33d7d..cca9338cacd6 100755
|
|
||||||
--- a/scripts/unpack_bootimg
|
|
||||||
+++ b/scripts/unpack_bootimg
|
|
||||||
@@ -1,4 +1,4 @@
|
|
||||||
-#!/usr/bin/env python
|
|
||||||
+#!/usr/bin/env python2
|
|
||||||
# Copyright 2018, The Android Open Source Project
|
|
||||||
#
|
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
diff --git a/tools/hv/lsvmbus b/tools/hv/lsvmbus
|
|
||||||
index 099f2c44dbed..cb2f7e27ea37 100644
|
|
||||||
--- a/tools/hv/lsvmbus
|
|
||||||
+++ b/tools/hv/lsvmbus
|
|
||||||
@@ -1,4 +1,4 @@
|
|
||||||
-#!/usr/bin/env python
|
|
||||||
+#!/usr/bin/env python2
|
|
||||||
# SPDX-License-Identifier: GPL-2.0
|
|
||||||
|
|
||||||
import os
|
|
||||||
diff --git a/tools/perf/python/tracepoint.py b/tools/perf/python/tracepoint.py
|
|
||||||
index 461848c7f57d..ed8377178830 100755
|
|
||||||
--- a/tools/perf/python/tracepoint.py
|
|
||||||
+++ b/tools/perf/python/tracepoint.py
|
|
||||||
@@ -1,4 +1,4 @@
|
|
||||||
-#! /usr/bin/env python
|
|
||||||
+#! /usr/bin/env python2
|
|
||||||
# SPDX-License-Identifier: GPL-2.0
|
|
||||||
# -*- python -*-
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
diff --git a/tools/perf/python/twatch.py b/tools/perf/python/twatch.py
|
|
||||||
index 04f3db29b9bc..ab0a2970b3fb 100755
|
|
||||||
--- a/tools/perf/python/twatch.py
|
|
||||||
+++ b/tools/perf/python/twatch.py
|
|
||||||
@@ -1,4 +1,4 @@
|
|
||||||
-#! /usr/bin/env python
|
|
||||||
+#! /usr/bin/env python2
|
|
||||||
# SPDX-License-Identifier: GPL-2.0-only
|
|
||||||
# -*- python -*-
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
diff --git a/tools/perf/scripts/python/exported-sql-viewer.py b/tools/perf/scripts/python/exported-sql-viewer.py
|
|
||||||
index 711d4f9f5645..e27e7a92fdac 100755
|
|
||||||
--- a/tools/perf/scripts/python/exported-sql-viewer.py
|
|
||||||
+++ b/tools/perf/scripts/python/exported-sql-viewer.py
|
|
||||||
@@ -1,4 +1,4 @@
|
|
||||||
-#!/usr/bin/env python
|
|
||||||
+#!/usr/bin/env python2
|
|
||||||
# SPDX-License-Identifier: GPL-2.0
|
|
||||||
# exported-sql-viewer.py: view data from sql database
|
|
||||||
# Copyright (c) 2014-2018, Intel Corporation.
|
|
||||||
diff --git a/tools/power/x86/intel_pstate_tracer/intel_pstate_tracer.py b/tools/power/x86/intel_pstate_tracer/intel_pstate_tracer.py
|
|
||||||
index e15e20696d17..c8159fe6d2e8 100755
|
|
||||||
--- a/tools/power/x86/intel_pstate_tracer/intel_pstate_tracer.py
|
|
||||||
+++ b/tools/power/x86/intel_pstate_tracer/intel_pstate_tracer.py
|
|
||||||
@@ -1,4 +1,4 @@
|
|
||||||
-#!/usr/bin/env python
|
|
||||||
+#!/usr/bin/env python2
|
|
||||||
# SPDX-License-Identifier: GPL-2.0-only
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
#
|
|
||||||
diff --git a/tools/testing/selftests/drivers/net/mlxsw/sharedbuffer_configuration.py b/tools/testing/selftests/drivers/net/mlxsw/sharedbuffer_configuration.py
|
|
||||||
index 2223337eed0c..81c538732185 100755
|
|
||||||
--- a/tools/testing/selftests/drivers/net/mlxsw/sharedbuffer_configuration.py
|
|
||||||
+++ b/tools/testing/selftests/drivers/net/mlxsw/sharedbuffer_configuration.py
|
|
||||||
@@ -1,4 +1,4 @@
|
|
||||||
-#!/usr/bin/env python
|
|
||||||
+#!/usr/bin/env python2
|
|
||||||
# SPDX-License-Identifier: GPL-2.0
|
|
||||||
|
|
||||||
import subprocess
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
--- a/net/mac80211/cfg.c
|
|
||||||
+++ b/net/mac80211/cfg.c
|
|
||||||
@@ -784,7 +784,8 @@ static int ieee80211_set_monitor_channel
|
|
||||||
ret = ieee80211_vif_use_channel(sdata, chandef,
|
|
||||||
IEEE80211_CHANCTX_EXCLUSIVE);
|
|
||||||
}
|
|
||||||
- } else if (local->open_count == local->monitors) {
|
|
||||||
+ // Patch: Always allow channel change, even if a normal virtual interface is present
|
|
||||||
+ } else /*if (local->open_count == local->monitors)*/ {
|
|
||||||
local->_oper_chandef = *chandef;
|
|
||||||
ieee80211_hw_config(local, 0);
|
|
||||||
}
|
|
||||||
--- a/net/mac80211/tx.c
|
|
||||||
+++ b/net/mac80211/tx.c
|
|
||||||
@@ -803,11 +803,19 @@ ieee80211_tx_h_sequence(struct ieee80211
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Packet injection may want to control the sequence
|
|
||||||
- * number, if we have no matching interface then we
|
|
||||||
- * neither assign one ourselves nor ask the driver to.
|
|
||||||
+ * number, so if an injected packet is found, skip
|
|
||||||
+ * renumbering it. Also make the packet NO_ACK to avoid
|
|
||||||
+ * excessive retries (ACKing and retrying should be
|
|
||||||
+ * handled by the injecting application).
|
|
||||||
+ * FIXME This may break hostapd and some other injectors.
|
|
||||||
+ * This should be done using a radiotap flag.
|
|
||||||
*/
|
|
||||||
- if (unlikely(info->control.vif->type == NL80211_IFTYPE_MONITOR))
|
|
||||||
+ if (unlikely((info->flags & IEEE80211_TX_CTL_INJECTED) &&
|
|
||||||
+ !(tx->sdata->u.mntr.flags & MONITOR_FLAG_COOK_FRAMES))) {
|
|
||||||
+ if (!ieee80211_has_morefrags(hdr->frame_control))
|
|
||||||
+ info->flags |= IEEE80211_TX_CTL_NO_ACK;
|
|
||||||
return TX_CONTINUE;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
if (unlikely(ieee80211_is_ctl(hdr->frame_control)))
|
|
||||||
return TX_CONTINUE;
|
|
||||||
@@ -2012,7 +2020,10 @@ void ieee80211_xmit(struct ieee80211_sub
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- ieee80211_set_qos_hdr(sdata, skb);
|
|
||||||
+ // Don't overwrite QoS header in monitor mode
|
|
||||||
+ if (likely(info->control.vif->type != NL80211_IFTYPE_MONITOR)) {
|
|
||||||
+ ieee80211_set_qos_hdr(sdata, skb);
|
|
||||||
+ }
|
|
||||||
ieee80211_tx(sdata, sta, skb, false, txdata_flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
--- a/net/wireless/chan.c
|
|
||||||
+++ b/net/wireless/chan.c
|
|
||||||
@@ -1148,8 +1148,10 @@ int cfg80211_set_monitor_channel(struct
|
|
||||||
{
|
|
||||||
if (!rdev->ops->set_monitor_channel)
|
|
||||||
return -EOPNOTSUPP;
|
|
||||||
- if (!cfg80211_has_monitors_only(rdev))
|
|
||||||
- return -EBUSY;
|
|
||||||
+ // Always allow user to change channel, even if there is another normal
|
|
||||||
+ // virtual interface using the device.
|
|
||||||
+ //if (!cfg80211_has_monitors_only(rdev))
|
|
||||||
+ // return -EBUSY;
|
|
||||||
|
|
||||||
return rdev_set_monitor_channel(rdev, chandef);
|
|
||||||
}
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
--- a/net/mac80211/cfg.c
|
|
||||||
+++ b/net/mac80211/cfg.c
|
|
||||||
@@ -784,7 +784,8 @@ static int ieee80211_set_monitor_channel
|
|
||||||
ret = ieee80211_vif_use_channel(sdata, chandef,
|
|
||||||
IEEE80211_CHANCTX_EXCLUSIVE);
|
|
||||||
}
|
|
||||||
- } else if (local->open_count == local->monitors) {
|
|
||||||
+ // Patch: Always allow channel change, even if a normal virtual interface is present
|
|
||||||
+ } else /*if (local->open_count == local->monitors)*/ {
|
|
||||||
local->_oper_chandef = *chandef;
|
|
||||||
ieee80211_hw_config(local, 0);
|
|
||||||
}
|
|
||||||
--- a/net/mac80211/tx.c
|
|
||||||
+++ b/net/mac80211/tx.c
|
|
||||||
@@ -810,11 +810,19 @@
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Packet injection may want to control the sequence
|
|
||||||
- * number, if we have no matching interface then we
|
|
||||||
- * neither assign one ourselves nor ask the driver to.
|
|
||||||
+ * number, so if an injected packet is found, skip
|
|
||||||
+ * renumbering it. Also make the packet NO_ACK to avoid
|
|
||||||
+ * excessive retries (ACKing and retrying should be
|
|
||||||
+ * handled by the injecting application).
|
|
||||||
+ * FIXME This may break hostapd and some other injectors.
|
|
||||||
+ * This should be done using a radiotap flag.
|
|
||||||
*/
|
|
||||||
- if (unlikely(info->control.vif->type == NL80211_IFTYPE_MONITOR))
|
|
||||||
+ if (unlikely((info->flags & IEEE80211_TX_CTL_INJECTED) &&
|
|
||||||
+ !(tx->sdata->u.mntr.flags & MONITOR_FLAG_COOK_FRAMES))) {
|
|
||||||
+ if (!ieee80211_has_morefrags(hdr->frame_control))
|
|
||||||
+ info->flags |= IEEE80211_TX_CTL_NO_ACK;
|
|
||||||
return TX_CONTINUE;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
if (unlikely(ieee80211_is_ctl(hdr->frame_control)))
|
|
||||||
return TX_CONTINUE;
|
|
||||||
@@ -2011,7 +2019,10 @@
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- ieee80211_set_qos_hdr(sdata, skb);
|
|
||||||
+ // Don't overwrite QoS header in monitor mode
|
|
||||||
+ if (likely(info->control.vif->type != NL80211_IFTYPE_MONITOR)) {
|
|
||||||
+ ieee80211_set_qos_hdr(sdata, skb);
|
|
||||||
+ }
|
|
||||||
ieee80211_tx(sdata, sta, skb, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
--- a/net/wireless/chan.c
|
|
||||||
+++ b/net/wireless/chan.c
|
|
||||||
@@ -1148,8 +1148,10 @@ int cfg80211_set_monitor_channel(struct
|
|
||||||
{
|
|
||||||
if (!rdev->ops->set_monitor_channel)
|
|
||||||
return -EOPNOTSUPP;
|
|
||||||
- if (!cfg80211_has_monitors_only(rdev))
|
|
||||||
- return -EBUSY;
|
|
||||||
+ // Always allow user to change channel, even if there is another normal
|
|
||||||
+ // virtual interface using the device.
|
|
||||||
+ //if (!cfg80211_has_monitors_only(rdev))
|
|
||||||
+ // return -EBUSY;
|
|
||||||
|
|
||||||
return rdev_set_monitor_channel(rdev, chandef);
|
|
||||||
}
|
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
--- a/drivers/net/wireless/zydas/zd1211rw/zd_mac.c
|
|
||||||
+++ b/drivers/net/wireless/zydas/zd1211rw/zd_mac.c
|
|
||||||
@@ -229,14 +229,19 @@ void zd_mac_clear(struct zd_mac *mac)
|
|
||||||
static int set_rx_filter(struct zd_mac *mac)
|
|
||||||
{
|
|
||||||
unsigned long flags;
|
|
||||||
- u32 filter = STA_RX_FILTER;
|
|
||||||
+ struct zd_ioreq32 ioreqs[] = {
|
|
||||||
+ {CR_RX_FILTER, STA_RX_FILTER},
|
|
||||||
+ { CR_SNIFFER_ON, 0U },
|
|
||||||
+ };
|
|
||||||
|
|
||||||
spin_lock_irqsave(&mac->lock, flags);
|
|
||||||
- if (mac->pass_ctrl)
|
|
||||||
- filter |= RX_FILTER_CTRL;
|
|
||||||
+ if (mac->pass_ctrl) {
|
|
||||||
+ ioreqs[0].value |= 0xFFFFFFFF;
|
|
||||||
+ ioreqs[1].value = 0x1;
|
|
||||||
+ }
|
|
||||||
spin_unlock_irqrestore(&mac->lock, flags);
|
|
||||||
|
|
||||||
- return zd_iowrite32(&mac->chip, CR_RX_FILTER, filter);
|
|
||||||
+ return zd_iowrite32a(&mac->chip, ioreqs, ARRAY_SIZE(ioreqs));
|
|
||||||
}
|
|
||||||
|
|
||||||
static int set_mac_and_bssid(struct zd_mac *mac)
|
|
||||||
@@ -1043,7 +1048,8 @@ int zd_mac_rx(struct ieee80211_hw *hw, c
|
|
||||||
/* Caller has to ensure that length >= sizeof(struct rx_status). */
|
|
||||||
status = (struct rx_status *)
|
|
||||||
(buffer + (length - sizeof(struct rx_status)));
|
|
||||||
- if (status->frame_status & ZD_RX_ERROR) {
|
|
||||||
+ if ((status->frame_status & ZD_RX_ERROR) ||
|
|
||||||
+ (status->frame_status & ~0x21)) {
|
|
||||||
if (mac->pass_failed_fcs &&
|
|
||||||
(status->frame_status & ZD_RX_CRC32_ERROR)) {
|
|
||||||
stats.flag |= RX_FLAG_FAILED_FCS_CRC;
|
|
||||||
@@ -1386,7 +1392,7 @@ struct ieee80211_hw *zd_mac_alloc_hw(str
|
|
||||||
ieee80211_hw_set(hw, MFP_CAPABLE);
|
|
||||||
ieee80211_hw_set(hw, HOST_BROADCAST_PS_BUFFERING);
|
|
||||||
ieee80211_hw_set(hw, RX_INCLUDES_FCS);
|
|
||||||
- ieee80211_hw_set(hw, SIGNAL_UNSPEC);
|
|
||||||
+ ieee80211_hw_set(hw, SIGNAL_DBM);
|
|
||||||
|
|
||||||
hw->wiphy->interface_modes =
|
|
||||||
BIT(NL80211_IFTYPE_MESH_POINT) |
|
|
||||||
--- a/drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c
|
|
||||||
+++ b/drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c
|
|
||||||
@@ -248,8 +248,17 @@ static void rtl8187_tx(struct ieee80211_
|
|
||||||
flags |= RTL818X_TX_DESC_FLAG_NO_ENC;
|
|
||||||
|
|
||||||
flags |= ieee80211_get_tx_rate(dev, info)->hw_value << 24;
|
|
||||||
+
|
|
||||||
+ // When this flag is set the firmware waits untill ALL fragments have
|
|
||||||
+ // reached the USB device. Then it sends the first fragment and waits
|
|
||||||
+ // for ACKS's. Of course in monitor mode it won't detect these ACK's.
|
|
||||||
if (ieee80211_has_morefrags(tx_hdr->frame_control))
|
|
||||||
- flags |= RTL818X_TX_DESC_FLAG_MOREFRAG;
|
|
||||||
+ {
|
|
||||||
+ // If info->control.vif is NULL it's most likely in monitor mode
|
|
||||||
+ if (likely(info->control.vif != NULL && info->control.vif->type != NL80211_IFTYPE_MONITOR)) {
|
|
||||||
+ flags |= RTL818X_TX_DESC_FLAG_MOREFRAG;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
|
|
||||||
/* HW will perform RTS-CTS when only RTS flags is set.
|
|
||||||
* HW will perform CTS-to-self when both RTS and CTS flags are set.
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
From c46a994dd78befbe94e66771db41c18351be2aae Mon Sep 17 00:00:00 2001
|
|
||||||
From: Steve deRosier <derosier@cal-sierra.com>
|
|
||||||
Date: Fri, 29 Sep 2017 10:48:19 -0700
|
|
||||||
Subject: [PATCH] wireless: carl9170: Enable sniffer mode promisc flag to fix
|
|
||||||
injection
|
|
||||||
|
|
||||||
The removal of the AR9170_MAC_SNIFFER_ENABLE_PROMISC flag to fix an issue
|
|
||||||
many years ago caused the AR9170 to not be able to pass probe response
|
|
||||||
packets with different MAC addresses back up to the driver. In general
|
|
||||||
operation, this doesn't matter, but in the case of packet injection with
|
|
||||||
aireplay-ng it is important. aireplay-ng specifically injects packets with
|
|
||||||
spoofed MAC addresses on the probe requests and looks for probe responses
|
|
||||||
back to those addresses. No other combination of filter flags seem to fix
|
|
||||||
this issue and so AR9170_MAC_SNIFFER_ENABLE is required to get these packets.
|
|
||||||
|
|
||||||
This was originally caused by commit e0509d3bdd7365d06c9bf570bf9f11 which
|
|
||||||
removed this flag in order to avoid spurious ack noise from the hardware.
|
|
||||||
In testing for this issue, keeping this flag but not restoring the
|
|
||||||
AR9170_MAC_RX_CTRL_ACK_IN_SNIFFER flag on the rc_ctrl seems to solve this
|
|
||||||
issue, at least with the most current firmware v1.9.9.
|
|
||||||
|
|
||||||
Signed-off-by: Steve deRosier <derosier@cal-sierra.com>
|
|
||||||
---
|
|
||||||
drivers/net/wireless/ath/carl9170/mac.c | 5 +++++
|
|
||||||
1 file changed, 5 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/drivers/net/wireless/ath/carl9170/mac.c b/drivers/net/wireless/ath/carl9170/mac.c
|
|
||||||
index 7d4a72dc98db..c617e883f47a 100644
|
|
||||||
--- a/drivers/net/wireless/ath/carl9170/mac.c
|
|
||||||
+++ b/drivers/net/wireless/ath/carl9170/mac.c
|
|
||||||
@@ -309,6 +309,7 @@ int carl9170_set_operating_mode(struct ar9170 *ar)
|
|
||||||
u32 rx_ctrl = AR9170_MAC_RX_CTRL_DEAGG |
|
|
||||||
AR9170_MAC_RX_CTRL_SHORT_FILTER;
|
|
||||||
u32 sniffer = AR9170_MAC_SNIFFER_DEFAULTS;
|
|
||||||
+ u32 mac_ftf = AR9170_MAC_FTF_DEFAULTS;
|
|
||||||
int err = 0;
|
|
||||||
|
|
||||||
rcu_read_lock();
|
|
||||||
@@ -373,6 +374,9 @@ int carl9170_set_operating_mode(struct ar9170 *ar)
|
|
||||||
|
|
||||||
if (ar->sniffer_enabled) {
|
|
||||||
enc_mode |= AR9170_MAC_ENCRYPTION_RX_SOFTWARE;
|
|
||||||
+ mac_ftf = AR9170_MAC_FTF_MONITOR;
|
|
||||||
+ sniffer |= AR9170_MAC_SNIFFER_ENABLE_PROMISC;
|
|
||||||
+ mac_addr = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = carl9170_set_mac_reg(ar, AR9170_MAC_REG_MAC_ADDR_L, mac_addr);
|
|
||||||
@@ -384,6 +388,7 @@ int carl9170_set_operating_mode(struct ar9170 *ar)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
carl9170_regwrite_begin(ar);
|
|
||||||
+ carl9170_regwrite(AR9170_MAC_REG_FRAMETYPE_FILTER, mac_ftf);
|
|
||||||
carl9170_regwrite(AR9170_MAC_REG_SNIFFER, sniffer);
|
|
||||||
carl9170_regwrite(AR9170_MAC_REG_CAM_MODE, cam_mode);
|
|
||||||
carl9170_regwrite(AR9170_MAC_REG_ENCRYPTION, enc_mode);
|
|
||||||
--
|
|
||||||
2.14.1
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user