提交 3332c5ce 编写于 作者: O openeuler-ci-bot 提交者: Gitee

!1 构建镜像脚本

Merge pull request !1 from woqidaideshi/master
# raspberrypi-build
#### Description
Scripts of building images for Raspberry Pi
Scripts of building images for Raspberry Pi.
#### Software Architecture
Software architecture description
AArch64
#### Installation
1. xxxx
2. xxxx
3. xxxx
There are two approaches to fetch the scripts:
1. Download the source code of this repository.
2. You can install raspberrypi-build using `rpm` or `dnf` command based on openEuler 20.09 repository.
`dnf install raspberrypi-build`
After installing raspberrypi-build, you can find the scripts and related files for building openEuler image of Raspberry Pi in `/opt/raspberrypi-build`.
#### Instructions
1. xxxx
2. xxxx
3. xxxx
Run the following command to build an image:
`sudo bash build-image.sh -d DIR -r REPO -n IMAGE_NAME`
The meaning of each parameter:
1. -d, --dir DIR
The directory for storing the image and other temporary files, which defaults to be the directory in which the script resides. If the `DIR` does not exist, it will be created automatically.
After building the image, you can find the image in `DIR/raspi_output/img/` as shown in the script output.
2. -r, --repo REPO_INFO
Required! The URL/path of target repo file, or the list of repositories' baseurls. Note that, the baseurls should be separated by space and enclosed in double quotes.
Examples are as follows:
- The URL of target repo file: *currently unavailable*
- The path of target repo file: `./openEuler-20.09.repo`
The content of the repo file is as follows:
```
[MAINLINE]
name=MAINLINE
baseurl=http://119.3.219.20:82/openEuler:/Mainline/standard_aarch64/
enabled=1
gpgcheck=0
[EPOL]
name=EPOL
baseurl=http://119.3.219.20:82/openEuler:/Epol/standard_aarch64/
enabled=1
gpgcheck=0
```
- List of repo's baseurls: `"http://119.3.219.20:82/openEuler:/Mainline/standard_aarch64/ http://119.3.219.20:82/openEuler:/Epol/standard_aarch64/"`
3. -n, --name IMAGE_NAME
The image name to be built.
For example, `openEuler-20.09-RaspberryPi.aarch64.img`. The default is `openEuler-RaspberryPi.aarch64.img`, or it is automatically generated based on parameter: `-r, --repo REPO_INFO`.
4. -h, --help
Display help information.
#### Contribution
......
# raspberrypi-build
#### 介绍
Scripts of building images for Raspberry Pi
构建树莓派镜像的脚本程序。
#### 软件架构
软件架构说明
AArch64
#### 安装教程
1. xxxx
2. xxxx
3. xxxx
有两种方式获取该脚本:
1. 下载该仓库源码。
2. 基于 openEuler 20.09 的源仓库,使用 `rpm``dnf` 软件包管理命令安装 raspberrypi-build。
`dnf install raspberrypi-build`
安装 raspberrypi-build 后,树莓派镜像构建的脚本及相关文件会保存在 `/opt/raspberrypi-build`。
#### 使用说明
1. xxxx
2. xxxx
3. xxxx
构建镜像需执行命令:
`sudo bash build-image.sh -d DIR -r REPO -n IMAGE_NAME`
各个参数意义:
1. -d, --dir DIR
构建镜像和临时文件的输出目录,默认为脚本所在目录。如果 `DIR` 不存在则会自动创建。
脚本运行结束后,会提示镜像的存储位置,默认保存在 `DIR/raspi_output/img/` 下。
2. -r, --repo REPO_INFO
必要参数!开发源 repo 文件的 URL 或者路径,也可以是开发源中资源库的 baseurl 列表。注意,如果该参数为资源库的 baseurl 列表,该参数需要使用双引号,各个 baseurl 之间以空格隔开。
下面分别举例:
- 开发源 repo 文件的 URL:*暂无*
- 开发源的 repo 文件路径:`./openEuler-20.09.repo`
该文件的内容如下:
```
[MAINLINE]
name=MAINLINE
baseurl=http://119.3.219.20:82/openEuler:/Mainline/standard_aarch64/
enabled=1
gpgcheck=0
[EPOL]
name=EPOL
baseurl=http://119.3.219.20:82/openEuler:/Epol/standard_aarch64/
enabled=1
gpgcheck=0
```
- 资源库的 baseurl 列表:`"http://119.3.219.20:82/openEuler:/Mainline/standard_aarch64/ http://119.3.219.20:82/openEuler:/Epol/standard_aarch64/"`
3. -n, --name IMAGE_NAME
构建的镜像名称。
例如,`openEuler-20.09-RaspberryPi.aarch64.img`。默认为`openEuler-RaspberryPi.aarch64.img`,或者根据 `-r, --repo REPO_INFO` 参数自动生成。
4. -h, --help
显示帮助信息。
#### 参与贡献
......
#!/bin/bash
set -e
__usage="
Usage: build-image [OPTIONS]
Build raspberrypi image.
Options:
-d, --dir DIR The directory for storing the image and other temporary files, which defaults to be the directory in which the script resides. If the DIR does not exist, it will be created automatically.
-r, --repo REPO_INFO Required! The URL/path of target repo file or list of repo's baseurls which should be a space separated list.
-n, --name IMAGE_NAME The raspberrypi image name to be built.
-h, --help Show command help.
"
help()
{
echo "$__usage"
exit $1
}
parseargs()
{
if [ "x$#" == "x0" ]; then
return 1
fi
while [ "x$#" != "x0" ];
do
if [ "x$1" == "x-h" -o "x$1" == "x--help" ]; then
return 1
elif [ "x$1" == "x" ]; then
shift
elif [ "x$1" == "x-r" -o "x$1" == "x--repo" ]; then
repo_file=`echo $2`
shift
shift
elif [ "x$1" == "x-n" -o "x$1" == "x--name" ]; then
img_name=`echo $2`
shift
shift
elif [ "x$1" == "x-d" -o "x$1" == "x--dir" ]; then
workdir=`echo $2`
shift
shift
else
echo `date` - ERROR, UNKNOWN params "$@"
return 2
fi
done
}
ERROR(){
echo `date` - ERROR, $* | tee -a ${log_dir}/${builddate}.log
}
LOG(){
echo `date` - INFO, $* | tee -a ${log_dir}/${builddate}.log
}
prepare(){
if [ ! -d ${tmp_dir} ]; then
mkdir -p ${tmp_dir}
else
rm -rf ${tmp_dir}/*
fi
if [ "x$repo_file" == "x" ] ; then
echo `date` - ERROR, \"-r REPO_INFO or --repo REPO_INFO\" missing.
help 2
elif [ "x${repo_file:0:4}" == "xhttp" ]; then
if [ "x${repo_file:0-5}" == "x.repo" ]; then
wget ${repo_file} -P ${tmp_dir}/
repo_file_name=${repo_file##*/}
repo_file=${tmp_dir}/${repo_file_name}
else
repo_file_name=tmp.repo
repo_file_tmp=${tmp_dir}/${repo_file_name}
index=1
for baseurl in ${repo_file// / }
do
echo [repo${index}] >> ${repo_file_tmp}
echo name=repo${index} to build raspi image >> ${repo_file_tmp}
echo baseurl=${baseurl} >> ${repo_file_tmp}
echo enabled=1 >> ${repo_file_tmp}
echo gpgcheck=0 >> ${repo_file_tmp}
echo >> ${repo_file_tmp}
index=$(($index+1))
done
repo_file=${repo_file_tmp}
fi
else
if [ ! -f $repo_file ]; then
echo `date` - ERROR, repo file $repo_file can not be found.
exit 2
else
cp $repo_file ${tmp_dir}/
repo_file_name=${repo_file##*/}
repo_file=${tmp_dir}/${repo_file_name}
fi
fi
repo_suffix=${repo_file_name%.*}
if [ "x$img_name" == "x" ]; then
if [[ "${repo_suffix}" =~ ^${OS_NAME}.* ]]; then
img_name=${repo_suffix}
else
img_name=${OS_NAME}
fi
img_name=${img_name}-RaspberryPi.aarch64.img
else
if [ "x${img_name:0-4}" != "x.img" ]; then
img_name=${img_name}.img
fi
fi
img_file=${img_dir}/${img_name}
if [ ! -d ${log_dir} ]; then
mkdir -p ${log_dir}
fi
LOG "prepare begin..."
# dnf makecache
# dnf install -y dnf-plugins-core tar parted dosfstools
if [ -d ${rootfs_dir} ]; then
rm -rf ${rootfs_dir}
fi
if [ ! -d ${img_dir} ]; then
mkdir -p ${img_dir}
fi
repo_info_names=`cat ${repo_file} | grep "^\["`
repo_baseurls=`cat ${repo_file} | grep "^baseurl="`
index=1
for repo_name in ${repo_info_names}
do
repo_name_list[$index]=${repo_name:1:-1}
index=$((index+1))
done
index=1
for baseurl in ${repo_baseurls}
do
repo_info="${repo_info} --repofrompath ${repo_name_list[$index]}-tmp,${baseurl:8}"
index=$((index+1))
done
set +e
os_release_name=${OS_NAME}-release
# yumdownloader --downloaddir=${tmp_dir} ${os_release_name} -c ${repo_file}
dnf ${repo_info} --disablerepo="*" --downloaddir=${tmp_dir}/ download ${os_release_name}
if [ $? != 0 ]; then
ERROR "Fail to download ${os_release_name}!"
exit 2
fi
os_release_name=`ls -r ${tmp_dir}/${os_release_name}*.rpm 2>/dev/null| head -n 1`
if [ -z "${os_release_name}" ]; then
ERROR "${os_release_name} can not be found!"
exit 2
fi
set -e
LOG "prepare end."
}
make_rootfs(){
LOG "make rootfs for ${repo_file} begin..."
if [[ -d ${rootfs_dir} ]]; then
if [[ -d ${rootfs_dir}/dev && `ls ${rootfs_dir}/dev | wc -l` -gt 1 ]]; then
umount -l ${rootfs_dir}/dev
fi
if [[ -d ${rootfs_dir}/proc && `ls ${rootfs_dir}/proc | wc -l` -gt 0 ]]; then
umount -l ${rootfs_dir}/proc
fi
if [[ -d ${rootfs_dir}/sys && `ls ${rootfs_dir}/sys | wc -l` -gt 0 ]]; then
umount -l ${rootfs_dir}/sys
fi
rm -rf ${rootfs_dir}
fi
mkdir -p ${rootfs_dir}
mkdir -p ${rootfs_dir}/var/lib/rpm
rpm --root ${rootfs_dir} --initdb
rpm -ivh --nodeps --root ${rootfs_dir}/ ${os_release_name}
mkdir -p ${rootfs_dir}/etc/rpm
chmod a+rX ${rootfs_dir}/etc/rpm
echo "%_install_langs en_US" > ${rootfs_dir}/etc/rpm/macros.image-language-conf
if [[ ! -d ${rootfs_dir}/etc/yum.repos.d ]]; then
mkdir -p ${rootfs_dir}/etc/yum.repos.d
fi
cp ${repo_file} ${rootfs_dir}/etc/yum.repos.d/tmp.repo
# dnf --installroot=${rootfs_dir}/ install dnf --nogpgcheck -y # --repofrompath=tmp,${rootfs_dir}/etc/yum.repos.d/tmp.repo --disablerepo="*"
dnf --installroot=${rootfs_dir}/ makecache
# dnf --installroot=${rootfs_dir}/ install -y alsa-utils wpa_supplicant vim net-tools iproute iputils NetworkManager openssh-server passwd hostname ntp bluez pulseaudio-module-bluetooth
# dnf --installroot=${rootfs_dir}/ install -y raspberrypi-kernel raspberrypi-firmware openEuler-repos
set +e
for item in $(cat $CONFIG_RPM_LIST)
do
dnf --installroot=${rootfs_dir}/ install -y $item
if [ $? == 0 ]; then
LOG install $item.
else
ERROR can not install $item.
fi
done
cat ${rootfs_dir}/etc/ntp.conf | grep "^server*"
if [ $? -ne 0 ]; then
echo -e "\nserver 0.cn.pool.ntp.org\nserver 1.asia.pool.ntp.org\nserver 2.asia.pool.ntp.org\nserver 127.0.0.1">>${rootfs_dir}/etc/ntp.conf
fi
cat ${rootfs_dir}/etc/ntp.conf | grep "^fudge*"
if [ $? -ne 0 ]; then
echo -e "\nfudge 127.0.0.1 stratum 10">>${rootfs_dir}/etc/ntp.conf
fi
set -e
cp ${euler_dir}/hosts ${rootfs_dir}/etc/hosts
if [ ! -d $rootfs_dir/etc/sysconfig/network-scripts ]; then
mkdir -p $rootfs_dir/etc/sysconfig/network-scripts
fi
cp ${euler_dir}/ifup-eth0 $rootfs_dir/etc/sysconfig/network-scripts/ifup-eth0
mkdir -p ${rootfs_dir}/usr/bin ${rootfs_dir}/lib/udev/rules.d ${rootfs_dir}/lib/systemd/system
cp ${euler_dir}/*.rules ${rootfs_dir}/lib/udev/rules.d/
cp ${euler_dir}/chroot.sh ${rootfs_dir}/chroot.sh
chmod +x ${rootfs_dir}/chroot.sh
mount --bind /dev ${rootfs_dir}/dev
mount -t proc /proc ${rootfs_dir}/proc
mount -t sysfs /sys ${rootfs_dir}/sys
chroot ${rootfs_dir} /bin/bash -c "echo 'Y' | /chroot.sh"
umount -l ${rootfs_dir}/dev
umount -l ${rootfs_dir}/proc
umount -l ${rootfs_dir}/sys
rm ${rootfs_dir}/etc/yum.repos.d/tmp.repo
rm ${rootfs_dir}/chroot.sh
LOG "make rootfs for ${repo_file} end."
}
make_img(){
LOG "make ${img_file} begin..."
size=`du -sh --block-size=1MiB ${rootfs_dir} | cut -f 1 | xargs`
size=$(($size+1100))
losetup -D
dd if=/dev/zero of=${img_file} bs=1MiB count=$size && sync
parted ${img_file} mklabel msdos mkpart primary fat32 8192s 593919s
parted ${img_file} -s set 1 boot
parted ${img_file} mkpart primary linux-swap 593920s 1593343s
parted ${img_file} mkpart primary ext4 1593344s 100%
device=`losetup -f --show -P ${img_file}`
LOG "after losetup: ${device}"
LOG "image ${img_file} created and mounted as ${device}"
# loopX=`kpartx -va ${device} | sed -E 's/.*(loop[0-9])p.*/\1/g' | head -1`
# LOG "after kpartx: ${loopX}"
kpartx -va ${device}
loopX=${device##*\/}
partprobe ${device}
bootp=/dev/mapper/${loopX}p1
swapp=/dev/mapper/${loopX}p2
rootp=/dev/mapper/${loopX}p3
LOG "bootp: " ${bootp} "rootp: " ${rootp}
mkfs.vfat -n boot ${bootp}
mkswap ${swapp}
mkfs.ext4 ${rootp}
set +e
if [ -d ${root_mnt} ]; then
df -lh | grep ${root_mnt}
if [ $? -eq 0 ]; then
umount ${root_mnt}
fi
rm -rf ${root_mnt}
fi
if [ -d ${boot_mnt} ]; then
df -lh | grep ${boot_mnt}
if [ $? -eq 0 ]; then
umount ${boot_mnt}
fi
rm -rf ${boot_mnt}
fi
set -e
mkdir -p ${root_mnt} ${boot_mnt}
mount -t vfat -o uid=root,gid=root,umask=0000 ${bootp} ${boot_mnt}
mount -t ext4 ${rootp} ${root_mnt}
fstab_array=("" "" "" "")
for line in `blkid | grep /dev/mapper/${loopX}p`
do
uuid=${line#*UUID=\"}
fstab_array[${line:18:1}]=${uuid%%\"*}
done
echo "UUID=${fstab_array[3]} / ext4 defaults,noatime 0 0" > ${rootfs_dir}/etc/fstab
echo "UUID=${fstab_array[1]} /boot vfat defaults,noatime 0 0" >> ${rootfs_dir}/etc/fstab
echo "UUID=${fstab_array[2]} swap swap defaults,noatime 0 0" >> ${rootfs_dir}/etc/fstab
cp -a ${rootfs_dir}/boot/* ${boot_mnt}/
cp ${euler_dir}/config.txt ${boot_mnt}/
echo "console=serial0,115200 console=tty1 root=/dev/mmcblk0p3 rootfstype=ext4 elevator=deadline rootwait" > ${boot_mnt}/cmdline.txt
if [ -f ${tmp_dir}/rootfs.tar ]; then
rm ${tmp_dir}/rootfs.tar
fi
pushd ${rootfs_dir}
rm -rf boot
tar cpf ${tmp_dir}/rootfs.tar .
popd
pushd ${root_mnt}
tar xpf ${tmp_dir}/rootfs.tar -C .
popd
sync
sleep 10
umount ${root_mnt}
umount ${boot_mnt}
kpartx -d ${device}
losetup -d ${device}
rm ${tmp_dir}/rootfs.tar
rm -rf ${rootfs_dir}
losetup -D
pushd ${img_dir}
if [ -f ${img_file} ]; then
sha256sum $(basename ${img_file}) > ${img_file}.sha256sum
xz -T 20 -z -c ${img_file} > ${img_file}.xz
sha256sum $(basename ${img_file}.xz) > ${img_file}.xz.sha256sum
LOG "made sum files for ${img_file}"
fi
popd
LOG "write ${img_file} done."
LOG "make ${img_file} end."
}
if [ "$EUID" -ne 0 ]; then
echo `date` - ERROR, Please run as root!
exit
fi
cur_dir=$(cd $(dirname $0);pwd)
workdir=${cur_dir}
parseargs "$@" || help $?
if [ "x$workdir" == "x" ]; then
echo `date` - ERROR, \"-d DIR or --dir DIR\" missing.
help 2
elif [ ! -d ${workdir} ]; then
echo `date` - INFO, output dir ${workdir} does not exists.
mkdir -p ${workdir}
echo `date` - INFO, output dir: ${workdir} created.
fi
OS_NAME=openEuler
workdir=$(cd "$(dirname $workdir)"; pwd)/$(basename $workdir)
rootfs_dir=${workdir}/raspi_output/rootfs
root_mnt=${workdir}/raspi_output/root
boot_mnt=${workdir}/raspi_output/boot
tmp_dir=${workdir}/raspi_output/tmp
log_dir=${workdir}/raspi_output/log
img_dir=${workdir}/raspi_output/img
euler_dir=${cur_dir}/config
CONFIG_RPM_LIST=${euler_dir}/rpmlist
builddate=$(date +%Y%m%d)
prepare
IFS=$'\n'
make_rootfs
make_img
\ No newline at end of file
SUBSYSTEM=="input", GROUP="input", MODE="0660"
SUBSYSTEM=="i2c-dev", GROUP="i2c", MODE="0660"
SUBSYSTEM=="spidev", GROUP="spi", MODE="0660"
SUBSYSTEM=="bcm2835-gpiomem", GROUP="gpio", MODE="0660"
SUBSYSTEM=="rpivid-*", GROUP="video", MODE="0660"
KERNEL=="vcsm-cma", GROUP="video", MODE="0660"
SUBSYSTEM=="gpio", GROUP="gpio", MODE="0660"
SUBSYSTEM=="gpio*", PROGRAM="/bin/sh -c '\
chown -R root:gpio /sys/class/gpio && chmod -R 770 /sys/class/gpio;\
chown -R root:gpio /sys/devices/virtual/gpio && chmod -R 770 /sys/devices/virtual/gpio;\
chown -R root:gpio /sys$devpath && chmod -R 770 /sys$devpath\
'"
SUBSYSTEM=="pwm*", PROGRAM="/bin/sh -c '\
chown -R root:gpio /sys/class/pwm && chmod -R 770 /sys/class/pwm;\
chown -R root:gpio /sys/devices/platform/soc/*.pwm/pwm/pwmchip* && chmod -R 770 /sys/devices/platform/soc/*.pwm/pwm/pwmchip*\
'"
KERNEL=="ttyAMA0", PROGRAM="/bin/sh -c '\
ALIASES=/proc/device-tree/aliases; \
if cmp -s $ALIASES/uart0 $ALIASES/serial0; then \
echo 0;\
elif cmp -s $ALIASES/uart0 $ALIASES/serial1; then \
echo 1; \
else \
exit 1; \
fi\
'", SYMLINK+="serial%c"
KERNEL=="ttyAMA1", PROGRAM="/bin/sh -c '\
ALIASES=/proc/device-tree/aliases; \
if [ -e /dev/ttyAMA0 ]; then \
exit 1; \
elif cmp -s $ALIASES/uart0 $ALIASES/serial0; then \
echo 0;\
elif cmp -s $ALIASES/uart0 $ALIASES/serial1; then \
echo 1; \
else \
exit 1; \
fi\
'", SYMLINK+="serial%c"
KERNEL=="ttyS0", PROGRAM="/bin/sh -c '\
ALIASES=/proc/device-tree/aliases; \
if cmp -s $ALIASES/uart1 $ALIASES/serial0; then \
echo 0; \
elif cmp -s $ALIASES/uart1 $ALIASES/serial1; then \
echo 1; \
else \
exit 1; \
fi \
'", SYMLINK+="serial%c"
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: raspberrypi-sys-mods
Source: https://github.com/RPi-Distro/raspberrypi-sys-mods
Files: *
Copyright: 2015 Raspberry Pi Foundation
License: BSD-3-Clause
License: BSD-3-Clause
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE HOLDERS OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#!/bin/bash
systemctl enable sshd
systemctl enable ntpd
systemctl enable hciuart
echo openEuler > /etc/hostname
echo "openEuler12#$" | passwd --stdin root
if [ -f /usr/share/zoneinfo/Asia/Shanghai ]; then
if [ -f /etc/localtime ]; then
rm -f /etc/localtime
fi
ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
fi
if [ -f /etc/rc.d/rc.local ]; then
chmod +x /etc/rc.d/rc.local
fi
\ No newline at end of file
# For more options and information see
# http://rpf.io/configtxt
# Some settings may impact device functionality. See link above for details
# uncomment if you get no picture on HDMI for a default "safe" mode
#hdmi_safe=1
# uncomment this if your display has a black border of unused pixels visible
# and your display can output without overscan
#disable_overscan=1
# uncomment the following to adjust overscan. Use positive numbers if console
# goes off screen, and negative if there is too much border
#overscan_left=16
#overscan_right=16
#overscan_top=16
#overscan_bottom=16
# uncomment to force a console size. By default it will be display's size minus
# overscan.
#framebuffer_width=1280
#framebuffer_height=720
# uncomment if hdmi display is not detected and composite is being output
#hdmi_force_hotplug=1
# uncomment to force a specific HDMI mode (this will force VGA)
#hdmi_group=1
#hdmi_mode=1
# uncomment to force a HDMI mode rather than DVI. This can make audio work in
# DMT (computer monitor) modes
#hdmi_drive=2