How to change the keymap (keyboard layout) used by the GRUB shell in Gentoo Linux
April 21, 2019 Leave a comment
The default keymap in the GRUB shell is US English. Because Linux has not yet been booted, the GRUB keymap is not governed by the keymap for the Linux console specified in /etc/conf.d/keymaps
in the case of OpenRC, or in /etc/vconsole.conf
in the case of systemd. This can be inconvenient if your keyboard has a different layout and you need to use the GRUB Rescue Shell. Below I explain how I configured my Gentoo Linux installation to be able to use a different keyboard layout in the GRUB shell.
There are, however, certain limitations to the keymap in the GRUB shell. The official GRUB documentation states the following:
17.4 Input terminal
Firmware console on BIOS, IEEE1275 and ARC doesn’t allow you to enter non-ASCII characters. EFI specification allows for such but author is unaware of any actual implementations. Serial input is currently limited for latin1 (unlikely to change). Own keyboard implementations (at_keyboard and usb_keyboard) supports any key but work on one-char-per-keystroke. So no dead keys or advanced input method. Also there is no keymap change hotkey. In practice it makes difficult to enter any text using non-Latin alphabet. Moreover all current input consumers are limited to ASCII.
Note that the GRUB documentation states ‘ASCII’, not ‘Extended ASCII’. ASCII is limited to codes 000 to 127 (see the character table in e.g. http://www.asciitable.com/).
Some Linux distributions have the utility grub-kbdcomp
to generate a GRUB keyboard layout file. grub-kbdcomp
is simply a shell script that is a wrapper for the Debian ckbcomp
utility and grub-mklayout
. There is a Gentoo Portage ebuild for ckbcomp
:
root # eix ckbcomp
[I] sys-apps/ckbcomp
Available versions: (~)1.164
Homepage: https://anonscm.debian.org/cgit/d-i/console-setup.git
Description: Compile an XKB keymap for loadkeys
However, I noticed that the latest version currently available in Debian is 1.191 (https://salsa.debian.org/installer-team/console-setup.git), so I created an ebuild ckbcomp-1.191.ebuild
in a local overlay on one of my laptops running Gentoo Linux Stable Branch, and I installed ckbcomp-1.191.
# Copyright 1999-2019 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 EAPI=6 DESCRIPTION="Compile an XKB keymap for loadkeys" HOMEPAGE="https://salsa.debian.org/installer-team/console-setup.git" if [[ ${PV} == 9999 ]]; then inherit git-r3 EGIT_REPO_URI="https://salsa.debian.org/installer-team/console-setup.git" else SRC_URI="https://salsa.debian.org/installer-team/console-setup/-/archive/${PV}/${P}.tar.gz -> ${P}.tar.gz" KEYWORDS="~amd64" S="${WORKDIR}" fi LICENSE="GPL-2" SLOT="0" DEPEND="" RDEPEND=" dev-lang/perl:* sys-apps/kbd x11-misc/xkeyboard-config" src_compile() { : } src_install() { dobin console-setup-${PV}-*/Keyboard/ckbcomp }
I have tried the above-mentioned ckbcomp
command on my PC BIOS Core i7 laptop running Gentoo Stable with OpenRC and GRUB Version 2.02-r3:
root # eix -I grub
[I] sys-boot/grub
Available versions: (2) 2.02-r3(2/2.02-r3)^st **9999(2/9999)^st
{debug device-mapper doc efiemu +fonts libzfs mount multislot nls sdl static test +themes truetype GRUB_PLATFORMS="coreboot efi-32 efi-64 emu ieee1275 loongson multiboot pc qemu qemu-mips uboot xen xen-32"}
Installed versions: 2.02-r3(2/2.02-r3)^st(02:33:36 23/03/19)(fonts nls sdl themes truetype -debug -device-mapper -doc -efiemu -libzfs -mount -multislot -static -test GRUB_PLATFORMS="pc -coreboot -efi-32 -efi-64 -emu -ieee1275 -loongson -multiboot -qemu -qemu-mips -uboot -xen -xen-32")
Homepage: https://www.gnu.org/software/grub/
Description: GNU GRUB boot loader
I used the following steps:
1. Installed sys-apps/ckbcomp.
root # emerge ckbcomp
root # eix ckbcomp
[I] sys-apps/ckbcomp
Available versions: (~)1.164 (~)1.191[1]
Installed versions: 1.191[1](22:09:15 20/04/19)
Homepage: https://salsa.debian.org/installer-team/console-setup.git
Description: Compile an XKB keymap for loadkeys
[1] "local_overlay" /usr/local/portage
2. Created a new sub-directory to store the GRUB keyboard layout files.
root # mkdir /boot/grub/layouts
3. Converted the X11 keymap to the GRUB keymap. The option for ckbcomp
must exist in the directory /usr/share/X11/xkb/symbols/
for this to work.
root # ckbcomp gb extd | grub-mklayout -o /boot/grub/layouts/gb.gkb
Unknown keyboard scan identifier Meta_Tab
Unknown keyboard scan identifier Meta_Tab
Unknown keyboard scan code 0x54
Unknown keyboard scan code 0x65
Unknown keyboard scan code 0x7f
I used the following commands to generate a br.gkb
(Brazilian Portuguese keymap) file and a us.gkb
(US English keymap) as well, as it is possible to switch keyboard layouts from the GRUB command line using the keymap
command, as I show further on:
root # ckbcomp br nodeadkeys | grub-mklayout -o /boot/grub/layouts/br.gkb
Unknown keyboard scan identifier Meta_Tab
Unknown keyboard scan identifier Meta_Tab
Unknown keyboard scan identifier KP_Comma
Unknown keyboard scan identifier KP_Comma
Unknown keyboard scan identifier KP_Comma
Unknown keyboard scan identifier KP_Comma
Unknown keyboard scan code 0x54
Unknown keyboard scan code 0x65
Unknown keyboard scan code 0x7f
root # ckbcomp us | grub-mklayout -o /boot/grub/layouts/us.gkb
Unknown keyboard scan identifier Meta_Tab
Unknown keyboard scan identifier Meta_Tab
Unknown keyboard scan code 0x54
Unknown keyboard scan code 0x65
Unknown keyboard scan code 0x7f
The resulting files can be seen in the directory /boot/grub/layouts/
:
root # ls -la /boot/grub/layouts
total 11
drwxr-xr-x 2 root root 1024 Apr 21 21:20 .
drwxr-xr-x 7 root root 1024 Nov 26 00:01 ..
-rw-r--r-- 1 root root 2572 Apr 21 21:29 br.gkb
-rw-r--r-- 1 root root 2572 Apr 21 21:29 gb.gkb
-rw-r--r-- 1 root root 2572 Apr 21 21:30 us.gkb
4. Append ‘GRUB_TERMINAL_INPUT=at_keyboard
‘ to /etc/default/grub
.
root # grep GRUB_TERMINAL_INPUT /etc/default/grub
GRUB_TERMINAL_INPUT="at_keyboard"
5. Add ‘insmod
‘ and ‘keymap
‘ lines to /etc/grub.d/40_custom
as shown below.
root # tail -n 2 /etc/grub.d/40_custom
insmod keylayouts
keymap $prefix/layouts/gb.gkb
6. Check what locales are available for the keymap.
root # locale --all-locales | grep -i gb
en_GB
en_GB.iso88591
en_GB.utf8
7. Add ‘locale=en_GB
‘ to GRUB_CMDLINE_LINUX
.
root # grep locale /etc/default/grub
GRUB_CMDLINE_LINUX_DEFAULT="locale=en_GB i915.modeset=1 rcutree.rcu_idle_gp_delay=1 acpi_enforce_resources=lax reboot=force raid=noautodetect resume=/dev/sda2"
8. Regenerate the grub.cfg
file.
root # grub-mkconfig -o /boot/grub/grub.cfg
root # grep terminal_input /boot/grub/grub.cfg
terminal_input at_keyboard
root # grep gkb /boot/grub/grub.cfg
keymap $prefix/layouts/gb.gkb
root # grep layouts /boot/grub/grub.cfg
insmod keylayouts
keymap $prefix/layouts/gb.gkb
9. If the machine uses UEFI rather than PC BIOS, update the GRUB files in the EFI directory.
root # grub-install --efi-directory=/boot/efi
10. Reboot to check if the gb
keymap has been loaded for the GRUB shell.
root # reboot
When I press ‘c
‘ when the GRUB menu appears, I now see the following if I press each key on the second-to-last row of keys on the keyboard:
grub> \zxcvbnm,./
That corresponds to a British English keyboard layout. As I mentioned before, due to GRUB’s limitations only standard ASCII chars are possible, so it is not possible to type characters such as é
and è
, or symbols such as £
and €
etc. on the GRUB command line, whatever the keymap.
You can tell if the GRUB keylayouts
module is loaded by entering the following command on the GRUB command line:
lsmod
Below is what I then see on the screen of a PC BIOS machine running up-to-date Gentoo Linux (Stable Branch) when I press ‘c
‘ when the GRUB menu is displayed.
GNU GRUB version 2.02~beta3
Minimal BASH-like line editing is supported. For the first word, TAB lists possible command completions. Anywhere else TAB lists possible device or file completions. ESC at any time exits.
grub> lsmod
Name Ref Count Dependencies
minicmd 1
gfxterm_background 1 bitmap,video,extcmd,gfxterm,bitmap_scale,video_colors
bitmap_scale 2 bitmap
video_colors 2
png 1 bitmap,bufio
bitmap 7
search 1 search_label,extcmd,search_fs_file,search_fs_uuid
search_label 2
search_fs_file 2
search_fs_uuid 2
at_keyboard 1 boot,keylayouts
keylayouts 3
gfxterm 3 video,font
all_video 1 video_cirrus,video_bochs,vga,vbe
video_cirrus 2 video_fb,pci,video
video_bochs 2 video_fb,pci,video
pci 6
vga 2 video_fb,video
vbe 2 video_fb,video
video_fb 12
font 5 video,bufio
video 24
loadenv 1 extcmd,disk
disk 2
test 1
normal 1 gettext,boot,extcmd,bufio,crypto,terminal
gzio 0
gettext 3
boot 4
extcmd 8
bufio 10
crypto 2
terminal 2
biosdisk 1
part_msdos 2
ext2 4 fshelp
fshelp 5
grub>
Shown below is what I see when I perform the following steps on the GRUB command line:
- press each key on the second-to-last line of keys on the keyboard and press Enter;
- check which GRUB terminal input module is loaded;
- change from the British English keyboard layout to the Brazilian Portuguese keyboard layout;
- press each key on the second-to-last line of keys on the keyboard and press Enter;
- switch back to the British English keyboard layout;
- press each key on the second-to-last line of keys on the keyboard and press Enter;
- switch to the US English keyboard layout;
- press each key on the second-to-last line of keys on the keyboard and press Enter;
- switch back to the British English keyboard layout.
In each case the output on the screen is correct for the keyboard layout selected:
grub> \zxcvbnm,./
error: can't find command `zxcvbnm,./'.
grub> terminal_input
Active input terminals:
at_keyboard
Available input terminals:
console serial_* serial
grub> keymap br
grub> \zxcvbnm,.;
error: can't find command `zxcvbnm,.;'.
grub> keymap gb
grub> \zxcvbnm,./
error: can't find command `zxcvbnm,./'.
grub> keymap us
grub> <zxcvbnm,./
error: syntax error.
error: Incorrect command.
error: syntax error.
grub> keymap gb
grub>
There is one more caveat…
When the GRUB menu first appears at boot, the following lines are still displayed at the bottom of the GRUB menu:
Use the ↑ and ↓ keys to select which entry is highlighted.
Press enter to boot the selected OS, `e' to edit the commands before booting or `c' for a command-line.
The highlighted entry will be executed automatically in 4s.
However, the highlighted entry on the GRUB menu is no longer executed automatically and I have to press ENTER in order to get GRUB to boot Linux. That is not a big deal in my case.