summaryrefslogtreecommitdiffstats
path: root/modules.d/10i18n
diff options
context:
space:
mode:
Diffstat (limited to 'modules.d/10i18n')
-rw-r--r--modules.d/10i18n/10-console.rules2
-rw-r--r--modules.d/10i18n/README124
-rwxr-xr-xmodules.d/10i18n/console_init.sh89
-rwxr-xr-xmodules.d/10i18n/module-setup.sh297
-rwxr-xr-xmodules.d/10i18n/parse-i18n.sh36
5 files changed, 548 insertions, 0 deletions
diff --git a/modules.d/10i18n/10-console.rules b/modules.d/10i18n/10-console.rules
new file mode 100644
index 0000000..640b1db
--- /dev/null
+++ b/modules.d/10i18n/10-console.rules
@@ -0,0 +1,2 @@
+# Console initialization - keyboard, font, etc.
+KERNEL=="tty0", RUN+="/sbin/initqueue --onetime --unique --name console_init_$name /lib/udev/console_init $root/$name"
diff --git a/modules.d/10i18n/README b/modules.d/10i18n/README
new file mode 100644
index 0000000..6cbbae9
--- /dev/null
+++ b/modules.d/10i18n/README
@@ -0,0 +1,124 @@
+dracut i18n module
+------------------
+
+INDEX
+
+0. Introduction
+1. Hostonly vs Generic
+2. Configuration
+ 2.1. Variables
+ 2.2. Setting up mappings
+ 2.3. Additional settings
+3. Kernel parameters
+
+~
+
+0. Introduction
+
+i18n module provides internationalization for initramfs at runtime. It
+is intended to be generic across different GNU/Linux distributions.
+
+i18n and keyboard settings are stored in different files among
+distributions. To deal with it avoiding hardcoding those differences in
+the installation script we handle it by mappings between variables used
+by dracut and the ones in the system. Package maintainer is expected to
+create those for his/her distribution and it's appreciated to share it
+with us, so we can include it in source package.
+
+
+1. Hostonly vs Generic
+
+If you invoke dracut with '-H' option, i18n module install script will
+gather variables values from your configuration files using mappings
+provided in "/etc/dracut.conf.d/<foo>.conf". Those variables will be
+put in "etc/vconsole.conf" and "etc/locale.conf" files inside initramfs
+image. Next it will install only declared font, keymaps and so.
+
+When building generic image (dracut without '-H' option), install script
+copies all content of directories: consolefonts, consoletrans, unimaps
+and keymaps to image. Take into account that's about 4 MiB.
+
+
+2. Configuration
+
+2.1. Variables
+
+The following variables are used by i18n install script and at initramfs
+runtime:
+
+ KEYMAP - keyboard translation table loaded by loadkeys
+ KEYTABLE - base name for keyboard translation table; if UNICODE is
+ true, Unicode version will be loaded. Overrides KEYMAP.
+ EXT_KEYMAPS - list of extra keymaps to bo loaded (sep. by space)
+ UNICODE - boolean, indicating UTF-8 mode
+ FONT - console font
+ FONT_MAP - see description of '-m' parameter in setfont manual
+ FONT_UNIMAP - see description of '-u' parameter in setfont manual
+
+The following are appended to EXT_KEYMAPS only during build time:
+
+ UNIKEYMAP
+ GRP_TOGGLE
+
+They were used in 10redhat-i18n module, but not sure of its purpose.
+I'm leaving it in case... The following are taken from the environment:
+
+ LANG
+ LC_ALL
+
+If UNICODE variable is not provided, script indicates if UTF-8 should be
+used on the basis of LANG value (if it ends with ".utf8" or similar).
+
+
+2.2. Setting up mappings
+
+Mappings between variables listed in 2.1. and the ones spread around
+your system are set up in /etc/dracut.conf.d/<foo>.conf. You need to
+assign mappings to i18n_vars. Here's an example:
+
+i18n_vars="/etc/conf.d/keymaps:KEYMAP,EXTENDED_KEYMAPS-EXT_KEYMAPS /etc/conf.d/consolefont:CONSOLEFONT-FONT,CONSOLETRANSLATION-FONT_MAP /etc/rc.conf:UNICODE"
+
+First we've got name of file in host file system tree. After colon
+there's mapping: <from>-<to>. If both variables have the same name you
+can enter just a single, but it's important to specify it! The module
+will source only variables you've listed.
+
+Below there's detailed description in BNF:
+
+<list> ::= <element> | <element> " " <list>
+<element> ::= <conf-file-name> ":" <map-list>
+<map-list> ::= <mapping> | <mapping> "," <map-list>
+<mapping> ::= <src-var> "-" <dst-var> | <src-var>
+
+We assume no whitespace are allowed between symbols.
+<conf-file-name> is a file holding <src-var> in your system.
+<src-var> is a variable holding value of meaning the same as <dst-var>.
+<dst-var> is a variable which will be set up inside initramfs.
+If <dst-var> has the same name as <src-var> we can omit <dst-var>.
+
+Example:
+/etc/conf.d/keymaps:KEYMAP,extended_keymaps-EXT_KEYMAPS
+<list> = /etc/conf.d/keymaps:KEYMAP,extended_keymaps-EXT_KEYMAPS
+<element> = /etc/conf.d/keymaps:KEYMAP,extended_keymaps-EXT_KEYMAPS
+<conf-file-name> = /etc/conf.d/keymaps
+<map-list> = KEYMAP,extended_keymaps-EXT_KEYMAPS
+<mapping> = KEYMAP
+<src-var> = KEYMAP
+<mapping> = extended_keymaps-EXT_KEYMAPS
+<src-var> = extended_keymaps
+<dst-var> = EXT_KEYMAPS
+
+
+2.3. Additional settings
+
+If you encounter following error message: "Directories consolefonts,
+consoletrans, keymaps, unimaps not found.", you can provide path where
+those directories lie in your system by setting kbddir in configuration
+file (the same where you put mappings).
+
+
+3. Kernel parameters
+
+If you create generic initramfs you can set up i18n by kernel
+parameters using variables listed in 2.1. (except of UNIKEYMAP
+and GRP_TOGGLE) The recommended minimum is: FONT and KEYMAP.
diff --git a/modules.d/10i18n/console_init.sh b/modules.d/10i18n/console_init.sh
new file mode 100755
index 0000000..3ca0ac1
--- /dev/null
+++ b/modules.d/10i18n/console_init.sh
@@ -0,0 +1,89 @@
+#!/bin/sh
+
+[ -n "$DRACUT_SYSTEMD" ] && exit 0
+
+if [ -x "$systemdutildir"/systemd-vconsole-setup ]; then
+ "$systemdutildir"/systemd-vconsole-setup "$@"
+fi
+
+[ -e /etc/vconsole.conf ] && . /etc/vconsole.conf
+
+DEFAULT_FONT=eurlatgr
+DEFAULT_KEYMAP=/etc/sysconfig/console/default.kmap
+
+set_keyboard() {
+ local param
+
+ [ "${UNICODE}" = 1 ] && param=-u || param=-a
+ kbd_mode ${param}
+}
+
+set_terminal() {
+ local dev="$1"
+
+ if [ "${UNICODE}" = 1 ]; then
+ printf '\033%%G' >&7
+ stty -F "${dev}" iutf8
+ else
+ printf '\033%%@' >&7
+ stty -F "${dev}" -iutf8
+ fi
+}
+
+set_keymap() {
+ local utf_switch
+
+ if [ -z "${KEYMAP}" ]; then
+ [ -f "${DEFAULT_KEYMAP}" ] && KEYMAP=${DEFAULT_KEYMAP}
+ fi
+
+ [ -n "${KEYMAP}" ] || return 1
+
+ [ "${UNICODE}" = 1 ] && utf_switch=-u
+
+ # shellcheck disable=SC2086
+ loadkeys -q ${utf_switch} ${KEYMAP} ${EXT_KEYMAPS}
+}
+
+set_font() {
+ setfont "${FONT-${DEFAULT_FONT}}" \
+ -C "${1}" \
+ ${FONT_MAP:+-m "${FONT_MAP}"} \
+ ${FONT_UNIMAP:+-u "${FONT_UNIMAP}"}
+}
+
+dev_close() {
+ exec 6>&-
+ exec 7>&-
+}
+
+dev_open() {
+ local dev="$1"
+
+ exec 6< "${dev}" \
+ && exec 7>> "${dev}"
+}
+
+dev=/dev/${1#/dev/}
+
+[ -c "${dev}" ] || {
+ echo "Usage: $0 device" >&2
+ exit 1
+}
+
+dev_open "${dev}"
+
+for fd in 6 7; do
+ if ! [ -t ${fd} ]; then
+ echo "ERROR: File descriptor not opened: ${fd}" >&2
+ dev_close
+ exit 1
+ fi
+done
+
+set_keyboard
+set_terminal "${dev}"
+set_font "${dev}"
+set_keymap
+
+dev_close
diff --git a/modules.d/10i18n/module-setup.sh b/modules.d/10i18n/module-setup.sh
new file mode 100755
index 0000000..ac45611
--- /dev/null
+++ b/modules.d/10i18n/module-setup.sh
@@ -0,0 +1,297 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ [[ "$mount_needs" ]] && return 1
+
+ require_binaries setfont loadkeys kbd_mode || return 1
+
+ return 0
+}
+
+# called by dracut
+depends() {
+ return 0
+}
+
+# called by dracut
+install() {
+ declare -A KEYMAPS
+
+ if dracut_module_included "systemd"; then
+ unset FONT
+ unset KEYMAP
+ # shellcheck disable=SC1090
+ [[ -f "$dracutsysrootdir"/etc/vconsole.conf ]] && . "$dracutsysrootdir"/etc/vconsole.conf
+ fi
+
+ KBDSUBDIRS=(consolefonts consoletrans keymaps unimaps)
+ DEFAULT_FONT="${i18n_default_font:-eurlatgr}"
+ I18N_CONF="/etc/locale.conf"
+ VCONFIG_CONF="/etc/vconsole.conf"
+
+ findkeymap() {
+ local -a MAPS
+ local MAPNAME
+ local INCLUDES
+ local MAP
+ local CMD
+ local FN
+
+ if [[ -f $dracutsysrootdir$1 ]]; then
+ MAPS=("$1")
+ else
+ MAPNAME=${1%.map*}
+
+ mapfile -t -d '' MAPS < <(
+ find "${dracutsysrootdir}${kbddir}"/keymaps/ -type f \( -name "${MAPNAME}" -o -name "${MAPNAME}.map*" \) -print0
+ )
+ fi
+
+ for MAP in "${MAPS[@]}"; do
+ [[ -f $MAP ]] || continue
+ [[ -v KEYMAPS["$MAP"] ]] && continue
+
+ KEYMAPS["$MAP"]=1
+
+ case "$MAP" in
+ *.gz) CMD="zgrep" ;;
+ *.bz2) CMD="bzgrep" ;;
+ *) CMD="grep" ;;
+ esac
+
+ readarray -t INCLUDES < <("$CMD" '^include ' "$MAP" | while read -r _ a _ || [ -n "$a" ]; do echo "${a//\"/}"; done)
+
+ for INCL in "${INCLUDES[@]}"; do
+ local -a FNS
+ mapfile -t -d '' FNS < <(find "${dracutsysrootdir}${kbddir}"/keymaps/ -type f -name "${INCL}*" -print0)
+ for FN in "${FNS[@]}"; do
+ [[ -f $FN ]] || continue
+ [[ -v KEYMAPS["$FN"] ]] || findkeymap "$FN"
+ done
+ done
+ done
+ }
+
+ # Function gathers variables from distributed files among the tree, maps to
+ # specified names and prints the result in format "new-name=value".
+ #
+ # $@ = list in format specified below (BNF notation)
+ #
+ # <list> ::= <element> | <element> " " <list>
+ # <element> ::= <conf-file-name> ":" <map-list>
+ # <map-list> ::= <mapping> | <mapping> "," <map-list>
+ # <mapping> ::= <src-var> "-" <dst-var> | <src-var>
+ #
+ # We assume no whitespace are allowed between symbols.
+ # <conf-file-name> is a file holding <src-var> in your system.
+ # <src-var> is a variable holding value of meaning the same as <dst-var>.
+ # <dst-var> is a variable which will be set up inside initramfs.
+ # If <dst-var> has the same name as <src-var> we can omit <dst-var>.
+ #
+ # Example:
+ # /etc/conf.d/keymaps:KEYMAP,extended_keymaps-EXT_KEYMAPS
+ # <list> = /etc/conf.d/keymaps:KEYMAP,extended_keymaps-EXT_KEYMAPS
+ # <element> = /etc/conf.d/keymaps:KEYMAP,extended_keymaps-EXT_KEYMAPS
+ # <conf-file-name> = /etc/conf.d/keymaps
+ # <map-list> = KEYMAP,extended_keymaps-EXT_KEYMAPS
+ # <mapping> = KEYMAP
+ # <src-var> = KEYMAP
+ # <mapping> = extended_keymaps-EXT_KEYMAPS
+ # <src-var> = extended_keymaps
+ # <dst-var> = EXT_KEYMAPS
+ gather_vars() {
+ local item map value
+
+ # FIXME: double check
+ # shellcheck disable=SC2068
+ for item in "$@"; do
+ read -r -a item <<< "${item/:/ }"
+ for map in ${item[1]//,/ }; do
+ read -r -a map <<< "${map//-/ }"
+ if [[ -f "$dracutsysrootdir${item[0]}" ]]; then
+ value=$(grep "^${map[0]}=" "$dracutsysrootdir${item[0]}")
+ value=${value#*=}
+ echo "${map[1]:-${map[0]}}=${value}"
+ fi
+ unset map
+ done
+ done
+ }
+
+ install_base() {
+ inst_multiple setfont loadkeys kbd_mode stty
+
+ if ! dracut_module_included "systemd"; then
+ inst "${moddir}"/console_init.sh /lib/udev/console_init
+ inst_rules "${moddir}"/10-console.rules
+ inst_hook cmdline 20 "${moddir}/parse-i18n.sh"
+ fi
+
+ if [[ ${kbddir} != "/usr/share" ]]; then
+ inst_dir /usr/share
+ for _src in "${KBDSUBDIRS[@]}"; do
+ [ ! -e "${initdir}/usr/share/${_src}" ] && ln -s "${kbddir}/${_src}" "${initdir}/usr/share/${_src}"
+ done
+ fi
+ }
+
+ install_all_kbd() {
+ local _src _line
+
+ for _src in "${KBDSUBDIRS[@]}"; do
+ inst_dir "${kbddir}/$_src"
+ $DRACUT_CP -L -t "${initdir}/${kbddir}/$_src" "${dracutsysrootdir}${kbddir}/$_src"/*
+ done
+
+ # remove unnecessary files
+ rm -f -- "${initdir}${kbddir}/consoletrans/utflist"
+ find "${initdir}${kbddir}/" -name README\* -delete
+ find "${initdir}${kbddir}/" -name '*.gz' -print -quit \
+ | while read -r _line || [ -n "$_line" ]; do
+ inst_multiple gzip
+ done
+
+ find "${initdir}${kbddir}/" -name '*.bz2' -print -quit \
+ | while read -r _line || [ -n "$_line" ]; do
+ inst_multiple bzip2
+ done
+ }
+
+ install_local_i18n() {
+ local map
+
+ # shellcheck disable=SC2086
+ eval "$(gather_vars ${i18n_vars})"
+ # shellcheck disable=SC1090
+ [ -f "$dracutsysrootdir"$I18N_CONF ] && . "$dracutsysrootdir"$I18N_CONF
+ # shellcheck disable=SC1090
+ [ -f "$dracutsysrootdir"$VCONFIG_CONF ] && . "$dracutsysrootdir"$VCONFIG_CONF
+
+ shopt -q -s nocasematch
+ if [[ ${UNICODE} ]]; then
+ if [[ ${UNICODE} == YES || ${UNICODE} == 1 ]]; then
+ UNICODE=1
+ elif [[ ${UNICODE} == NO || ${UNICODE} == 0 ]]; then
+ UNICODE=0
+ else
+ UNICODE=''
+ fi
+ fi
+ if [[ ! ${UNICODE} && ${LANG} =~ .*\.UTF-?8 ]]; then
+ UNICODE=1
+ fi
+ shopt -q -u nocasematch
+
+ # Gentoo user may have KEYMAP set to something like "-u pl2",
+ KEYMAP=${KEYMAP#-* }
+
+ # openSUSE user may have KEYMAP set to something like ".gz"
+ KEYMAP=${KEYMAP/.gz/}
+
+ # KEYTABLE is a bit special - it defines base keymap name and UNICODE
+ # determines whether non-UNICODE or UNICODE version is used
+
+ if [[ ${KEYTABLE} ]]; then
+ if [[ ${UNICODE} == 1 ]]; then
+ [[ ${KEYTABLE} =~ .*\.uni.* ]] || KEYTABLE=${KEYTABLE%.map*}.uni
+ fi
+ KEYMAP=${KEYTABLE}
+ fi
+
+ # I'm not sure of the purpose of UNIKEYMAP and GRP_TOGGLE. They were in
+ # original redhat-i18n module. Anyway it won't hurt.
+ EXT_KEYMAPS+=\ ${UNIKEYMAP}\ ${GRP_TOGGLE}
+
+ [[ ${KEYMAP} ]] || {
+ dinfo 'No KEYMAP configured.'
+ return 1
+ }
+
+ findkeymap "${KEYMAP}"
+
+ for map in ${EXT_KEYMAPS}; do
+ ddebug "Adding extra map: ${map}"
+ findkeymap "${map}"
+ done
+
+ for keymap in "${!KEYMAPS[@]}"; do
+ inst_opt_decompress "${keymap}"
+ done
+
+ inst_opt_decompress "${kbddir}"/consolefonts/"${DEFAULT_FONT}".*
+
+ if [[ ${FONT} ]] && [[ ${FONT} != "${DEFAULT_FONT}" ]]; then
+ if [[ -f "${kbddir}"/consolefonts/"${FONT}" ]]; then
+ inst_opt_decompress "${kbddir}"/consolefonts/"${FONT}"
+ else
+ FONT=${FONT%.psf*}
+ inst_opt_decompress "${kbddir}"/consolefonts/"${FONT}".*
+ fi
+ fi
+
+ if [[ ${FONT_MAP} ]]; then
+ FONT_MAP=${FONT_MAP%.trans}
+ # There are three different formats that setfont supports
+ inst_simple "${kbddir}"/consoletrans/"${FONT_MAP}" \
+ || inst_simple "${kbddir}"/consoletrans/"${FONT_MAP}".trans \
+ || inst_simple "${kbddir}"/consoletrans/"${FONT_MAP}"_to_uni.trans \
+ || dwarn "Could not find FONT_MAP ${FONT_MAP}!"
+ fi
+
+ if [[ ${FONT_UNIMAP} ]]; then
+ FONT_UNIMAP=${FONT_UNIMAP%.uni}
+ inst_simple "${kbddir}"/unimaps/"${FONT_UNIMAP}".uni
+ fi
+
+ if dracut_module_included "systemd" && [[ -f $dracutsysrootdir${I18N_CONF} ]]; then
+ inst_simple ${I18N_CONF}
+ else
+ mksubdirs "${initdir}"${I18N_CONF}
+ print_vars LC_ALL LANG >> "${initdir}"${I18N_CONF}
+ fi
+
+ if ! dracut_module_included "systemd"; then
+ mksubdirs "${initdir}"${VCONFIG_CONF}
+ print_vars KEYMAP EXT_KEYMAPS UNICODE FONT FONT_MAP FONT_UNIMAP >> "${initdir}"${VCONFIG_CONF}
+ fi
+
+ return 0
+ }
+
+ checks() {
+ for kbddir in ${kbddir} /usr/lib/kbd /lib/kbd /usr/share /usr/share/kbd; do
+ if [[ -d "$dracutsysrootdir${kbddir}" ]]; then
+ for dir in "${KBDSUBDIRS[@]}"; do
+ [[ -d "$dracutsysrootdir${kbddir}/${dir}" ]] && continue
+ false
+ done && break
+ fi
+ kbddir=''
+ done
+
+ [[ "$kbddir" ]] || return 1
+
+ [[ -f $dracutsysrootdir$I18N_CONF && -f $dracutsysrootdir$VCONFIG_CONF ]] \
+ || [[ ! ${hostonly} || ${i18n_vars} ]] || {
+ derror 'i18n_vars not set! Please set up i18n_vars in ' \
+ 'configuration file.'
+ }
+ return 0
+ }
+
+ if checks; then
+ install_base
+
+ # https://github.com/dracutdevs/dracut/issues/796
+ if dracut_module_included "systemd" && [[ -f $dracutsysrootdir${VCONFIG_CONF} ]]; then
+ inst_simple ${VCONFIG_CONF}
+ fi
+
+ if [[ ${hostonly} ]] && ! [[ ${i18n_install_all} == "yes" ]]; then
+ install_local_i18n || install_all_kbd
+ else
+ install_all_kbd
+ fi
+ fi
+}
diff --git a/modules.d/10i18n/parse-i18n.sh b/modules.d/10i18n/parse-i18n.sh
new file mode 100755
index 0000000..2deb2c4
--- /dev/null
+++ b/modules.d/10i18n/parse-i18n.sh
@@ -0,0 +1,36 @@
+#!/bin/sh
+
+inst_key_val() {
+ local _value
+ local _file
+ local _default
+ _file="$1"
+ shift
+ _key="$1"
+ shift
+ _default="$1"
+ shift
+ _value="$(getarg "$@")"
+ [ -z "${_value}" ] && _value=$_default
+ if [ -n "${_value}" ]; then
+ printf -- '%s="%s"\n' "${_key}" "${_value}" >> "$_file"
+ fi
+ unset _file
+ unset _value
+}
+
+inst_key_val /etc/vconsole.conf KEYMAP '' rd.vconsole.keymap KEYMAP -d KEYTABLE
+inst_key_val /etc/vconsole.conf FONT '' rd.vconsole.font FONT -d SYSFONT
+inst_key_val /etc/vconsole.conf FONT_MAP '' rd.vconsole.font.map FONT_MAP -d CONTRANS
+inst_key_val /etc/vconsole.conf FONT_UNIMAP '' rd.vconsole.font.unimap FONT_UNIMAP -d UNIMAP
+inst_key_val /etc/vconsole.conf UNICODE 1 rd.vconsole.font.unicode UNICODE vconsole.unicode
+inst_key_val /etc/vconsole.conf EXT_KEYMAP '' rd.vconsole.keymap.ext EXT_KEYMAP
+
+inst_key_val /etc/locale.conf LANG '' rd.locale.LANG LANG
+inst_key_val /etc/locale.conf LC_ALL '' rd.locale.LC_ALL LC_ALL
+
+if [ -f /etc/locale.conf ]; then
+ . /etc/locale.conf
+ export LANG
+ export LC_ALL
+fi