6 Writing your own configuration file ************************************* GRUB is configured using 'grub.cfg', usually located under '/boot/grub'. This file is quite flexible, but most users will not need to write the whole thing by hand. 6.1 Simple configuration handling ================================= The program 'grub-mkconfig' (*note Invoking grub-mkconfig::) generates 'grub.cfg' files suitable for most cases. It is suitable for use when upgrading a distribution, and will discover available kernels and attempt to generate menu entries for them. 'grub-mkconfig' does have some limitations. While adding extra custom menu entries to the end of the list can be done by editing '/etc/grub.d/40_custom' or creating '/boot/grub/custom.cfg', changing the order of menu entries or changing their titles may require making complex changes to shell scripts stored in '/etc/grub.d/'. This may be improved in the future. In the meantime, those who feel that it would be easier to write 'grub.cfg' directly are encouraged to do so (*note Booting::, and *note Shell-like scripting::), and to disable any system provided by their distribution to automatically run 'grub-mkconfig'. The file '/etc/default/grub' controls the operation of 'grub-mkconfig'. It is sourced by a shell script, and so must be valid POSIX shell input; normally, it will just be a sequence of 'KEY=value' lines, but if the value contains spaces or other special characters then it must be quoted. For example: GRUB_TERMINAL_INPUT="console serial" Valid keys in '/etc/default/grub' are as follows: 'GRUB_DEFAULT' The default menu entry. This may be a number, in which case it identifies the Nth entry in the generated menu counted from zero, or the title of a menu entry, or the special string 'saved'. Using the id may be useful if you want to set a menu entry as the default even though there may be a variable number of entries before it. For example, if you have: menuentry 'Example GNU/Linux distribution' --class gnu-linux --id example-gnu-linux { ... } then you can make this the default using: GRUB_DEFAULT=example-gnu-linux Previously it was documented the way to use entry title. While this still works it's not recommended since titles often contain unstable device names and may be translated If you set this to 'saved', then the default menu entry will be that saved by 'GRUB_SAVEDEFAULT' or 'grub-set-default'. This relies on the environment block, which may not be available in all situations (*note Environment block::). The default is '0'. 'GRUB_SAVEDEFAULT' If this option is set to 'true', then, when an entry is selected, save it as a new default entry for use by future runs of GRUB. This is only useful if 'GRUB_DEFAULT=saved'; it is a separate option because 'GRUB_DEFAULT=saved' is useful without this option, in conjunction with 'grub-set-default'. Unset by default. This option relies on the environment block, which may not be available in all situations (*note Environment block::). 'GRUB_TIMEOUT' Boot the default entry this many seconds after the menu is displayed, unless a key is pressed. The default is '5'. Set to '0' to boot immediately without displaying the menu, or to '-1' to wait indefinitely. If 'GRUB_TIMEOUT_STYLE' is set to 'countdown' or 'hidden', the timeout is instead counted before the menu is displayed. 'GRUB_TIMEOUT_STYLE' If this option is unset or set to 'menu', then GRUB will display the menu and then wait for the timeout set by 'GRUB_TIMEOUT' to expire before booting the default entry. Pressing a key interrupts the timeout. If this option is set to 'countdown' or 'hidden', then, before displaying the menu, GRUB will wait for the timeout set by 'GRUB_TIMEOUT' to expire. If is pressed during that time, it will display the menu and wait for input. If a hotkey associated with a menu entry is pressed, it will boot the associated menu entry immediately. If the timeout expires before either of these happens, it will boot the default entry. In the 'countdown' case, it will show a one-line indication of the remaining time. 'GRUB_DEFAULT_BUTTON' 'GRUB_TIMEOUT_BUTTON' 'GRUB_TIMEOUT_STYLE_BUTTON' 'GRUB_BUTTON_CMOS_ADDRESS' Variants of the corresponding variables without the '_BUTTON' suffix, used to support vendor-specific power buttons. *Note Vendor power-on keys::. 'GRUB_DISTRIBUTOR' Set by distributors of GRUB to their identifying name. This is used to generate more informative menu entry titles. 'GRUB_TERMINAL_INPUT' Select the terminal input device. You may select multiple devices here, separated by spaces. Valid terminal input names depend on the platform, but may include 'console' (native platform console), 'serial' (serial terminal), 'serial_' (serial terminal with explicit port selection), 'at_keyboard' (PC AT keyboard), or 'usb_keyboard' (USB keyboard using the HID Boot Protocol, for cases where the firmware does not handle this). The default is to use the platform's native terminal input. 'GRUB_TERMINAL_OUTPUT' Select the terminal output device. You may select multiple devices here, separated by spaces. Valid terminal output names depend on the platform, but may include 'console' (native platform console), 'serial' (serial terminal), 'serial_' (serial terminal with explicit port selection), 'gfxterm' (graphics-mode output), 'vga_text' (VGA text output), 'mda_text' (MDA text output), 'morse' (Morse-coding using system beeper) or 'spkmodem' (simple data protocol using system speaker). 'spkmodem' is useful when no serial port is available. Connect the output of sending system (where GRUB is running) to line-in of receiving system (usually developer machine). On receiving system compile 'spkmodem-recv' from 'util/spkmodem-recv.c' and run: parecord --channels=1 --rate=48000 --format=s16le | ./spkmodem-recv The default is to use the platform's native terminal output. 'GRUB_TERMINAL' If this option is set, it overrides both 'GRUB_TERMINAL_INPUT' and 'GRUB_TERMINAL_OUTPUT' to the same value. 'GRUB_SERIAL_COMMAND' A command to configure the serial port when using the serial console. *Note serial::. Defaults to 'serial'. 'GRUB_CMDLINE_LINUX' Command-line arguments to add to menu entries for the Linux kernel. 'GRUB_CMDLINE_LINUX_DEFAULT' Unless 'GRUB_DISABLE_RECOVERY' is set to 'true', two menu entries will be generated for each Linux kernel: one default entry and one entry for recovery mode. This option lists command-line arguments to add only to the default menu entry, after those listed in 'GRUB_CMDLINE_LINUX'. 'GRUB_CMDLINE_NETBSD' 'GRUB_CMDLINE_NETBSD_DEFAULT' As 'GRUB_CMDLINE_LINUX' and 'GRUB_CMDLINE_LINUX_DEFAULT', but for NetBSD. 'GRUB_CMDLINE_GNUMACH' As 'GRUB_CMDLINE_LINUX', but for GNU Mach. 'GRUB_CMDLINE_XEN' 'GRUB_CMDLINE_XEN_DEFAULT' The values of these options are passed to Xen hypervisor Xen menu entries, for all respectively normal entries. 'GRUB_CMDLINE_LINUX_XEN_REPLACE' 'GRUB_CMDLINE_LINUX_XEN_REPLACE_DEFAULT' The values of these options replace the values of 'GRUB_CMDLINE_LINUX' and 'GRUB_CMDLINE_LINUX_DEFAULT' for Linux and Xen menu entries. 'GRUB_EARLY_INITRD_LINUX_CUSTOM' 'GRUB_EARLY_INITRD_LINUX_STOCK' List of space-separated early initrd images to be loaded from '/boot'. This is for loading things like CPU microcode, firmware, ACPI tables, crypto keys, and so on. These early images will be loaded in the order declared, and all will be loaded before the actual functional initrd image. 'GRUB_EARLY_INITRD_LINUX_STOCK' is for your distribution to declare images that are provided by the distribution. It should not be modified without understanding the consequences. They will be loaded first. 'GRUB_EARLY_INITRD_LINUX_CUSTOM' is for your custom created images. The default stock images are as follows, though they may be overridden by your distribution: intel-uc.img intel-ucode.img amd-uc.img amd-ucode.img early_ucode.cpio microcode.cpio 'GRUB_DISABLE_LINUX_UUID' Normally, 'grub-mkconfig' will generate menu entries that use universally-unique identifiers (UUIDs) to identify the root filesystem to the Linux kernel, using a 'root=UUID=...' kernel parameter. This is usually more reliable, but in some cases it may not be appropriate. To disable the use of UUIDs, set this option to 'true'. 'GRUB_DISABLE_LINUX_PARTUUID' If 'grub-mkconfig' cannot identify the root filesystem via its universally-unique indentifier (UUID), 'grub-mkconfig' can use the UUID of the partition containing the filesystem to identify the root filesystem to the Linux kernel via a 'root=PARTUUID=...' kernel parameter. This is not as reliable as using the filesystem UUID, but is more reliable than using the Linux device names. When 'GRUB_DISABLE_LINUX_PARTUUID' is set to 'false', the Linux kernel version must be 2.6.37 (3.10 for systems using the MSDOS partition scheme) or newer. This option defaults to 'true'. To enable the use of partition UUIDs, set this option to 'false'. 'GRUB_DISABLE_RECOVERY' If this option is set to 'true', disable the generation of recovery mode menu entries. 'GRUB_VIDEO_BACKEND' If graphical video support is required, either because the 'gfxterm' graphical terminal is in use or because 'GRUB_GFXPAYLOAD_LINUX' is set, then 'grub-mkconfig' will normally load all available GRUB video drivers and use the one most appropriate for your hardware. If you need to override this for some reason, then you can set this option. After 'grub-install' has been run, the available video drivers are listed in '/boot/grub/video.lst'. 'GRUB_GFXMODE' Set the resolution used on the 'gfxterm' graphical terminal. Note that you can only use modes which your graphics card supports via VESA BIOS Extensions (VBE), so for example native LCD panel resolutions may not be available. The default is 'auto', which tries to select a preferred resolution. *Note gfxmode::. 'GRUB_BACKGROUND' Set a background image for use with the 'gfxterm' graphical terminal. The value of this option must be a file readable by GRUB at boot time, and it must end with '.png', '.tga', '.jpg', or '.jpeg'. The image will be scaled if necessary to fit the screen. 'GRUB_THEME' Set a theme for use with the 'gfxterm' graphical terminal. 'GRUB_GFXPAYLOAD_LINUX' Set to 'text' to force the Linux kernel to boot in normal text mode, 'keep' to preserve the graphics mode set using 'GRUB_GFXMODE', 'WIDTHxHEIGHT'['xDEPTH'] to set a particular graphics mode, or a sequence of these separated by commas or semicolons to try several modes in sequence. *Note gfxpayload::. Depending on your kernel, your distribution, your graphics card, and the phase of the moon, note that using this option may cause GNU/Linux to suffer from various display problems, particularly during the early part of the boot sequence. If you have problems, set this option to 'text' and GRUB will tell Linux to boot in normal text mode. 'GRUB_DISABLE_OS_PROBER' Normally, 'grub-mkconfig' will try to use the external 'os-prober' program, if installed, to discover other operating systems installed on the same system and generate appropriate menu entries for them. Set this option to 'true' to disable this. 'GRUB_OS_PROBER_SKIP_LIST' List of space-separated FS UUIDs of filesystems to be ignored from os-prober output. For efi chainloaders it's @ 'GRUB_DISABLE_SUBMENU' Normally, 'grub-mkconfig' will generate top level menu entry for the kernel with highest version number and put all other found kernels or alternative menu entries for recovery mode in submenu. For entries returned by 'os-prober' first entry will be put on top level and all others in submenu. If this option is set to 'y', flat menu with all entries on top level will be generated instead. Changing this option will require changing existing values of 'GRUB_DEFAULT', 'fallback' (*note fallback::) and 'default' (*note default::) environment variables as well as saved default entry using 'grub-set-default' and value used with 'grub-reboot'. 'GRUB_ENABLE_CRYPTODISK' If set to 'y', 'grub-mkconfig' and 'grub-install' will check for encrypted disks and generate additional commands needed to access them during boot. Note that in this case unattended boot is not possible because GRUB will wait for passphrase to unlock encrypted container. 'GRUB_INIT_TUNE' Play a tune on the speaker when GRUB starts. This is particularly useful for users unable to see the screen. The value of this option is passed directly to *note play::. 'GRUB_BADRAM' If this option is set, GRUB will issue a *note badram:: command to filter out specified regions of RAM. 'GRUB_PRELOAD_MODULES' This option may be set to a list of GRUB module names separated by spaces. Each module will be loaded as early as possible, at the start of 'grub.cfg'. The following options are still accepted for compatibility with existing configurations, but have better replacements: 'GRUB_HIDDEN_TIMEOUT' Wait this many seconds before displaying the menu. If is pressed during that time, display the menu and wait for input according to 'GRUB_TIMEOUT'. If a hotkey associated with a menu entry is pressed, boot the associated menu entry immediately. If the timeout expires before either of these happens, display the menu for the number of seconds specified in 'GRUB_TIMEOUT' before booting the default entry. If you set 'GRUB_HIDDEN_TIMEOUT', you should also set 'GRUB_TIMEOUT=0' so that the menu is not displayed at all unless is pressed. This option is unset by default, and is deprecated in favour of the less confusing 'GRUB_TIMEOUT_STYLE=countdown' or 'GRUB_TIMEOUT_STYLE=hidden'. 'GRUB_HIDDEN_TIMEOUT_QUIET' In conjunction with 'GRUB_HIDDEN_TIMEOUT', set this to 'true' to suppress the verbose countdown while waiting for a key to be pressed before displaying the menu. This option is unset by default, and is deprecated in favour of the less confusing 'GRUB_TIMEOUT_STYLE=countdown'. 'GRUB_HIDDEN_TIMEOUT_BUTTON' Variant of 'GRUB_HIDDEN_TIMEOUT', used to support vendor-specific power buttons. *Note Vendor power-on keys::. This option is unset by default, and is deprecated in favour of the less confusing 'GRUB_TIMEOUT_STYLE=countdown' or 'GRUB_TIMEOUT_STYLE=hidden'. For more detailed customisation of 'grub-mkconfig''s output, you may edit the scripts in '/etc/grub.d' directly. '/etc/grub.d/40_custom' is particularly useful for adding entire custom menu entries; simply type the menu entries you want to add at the end of that file, making sure to leave at least the first two lines intact. 6.2 Root Identifcation Heuristics ================================= If the target operating system uses the Linux kernel, 'grub-mkconfig' attempts to identify the root file system via a heuristic algoirthm. This algorithm selects the identification method of the root file system by considering three factors. The first is if an initrd for the target operating system is also present. The second is 'GRUB_DISABLE_LINUX_UUID' and if set to 'true', prevents 'grub-mkconfig' from identifying the root file system by its UUID. The third is 'GRUB_DISABLE_LINUX_PARTUUID' and if set to 'true', prevents 'grub-mkconfig' from identifying the root file system via the UUID of its enclosing partition. If the variables are assigned any other value, that value is considered equivalent to 'false'. The variables are also considered to be set to 'false' if they are not set. When booting, the Linux kernel will delegate the task of mounting the root filesystem to the initrd. Most initrd images determine the root file system by checking the Linux kernel's command-line for the 'root' key and use its value as the identification method of the root file system. To improve the reliability of booting, most initrd images also allow the root file system to be identified by its UUID. Because of this behavior, the 'grub-mkconfig' command will set 'root' to 'root=UUID=...' to provide the initrd with the filesystem UUID of the root file system. If no initrd is detected or 'GRUB_DISABLE_LINUX_UUID' is set to 'true' then 'grub-command' will identify the root filesystem by setting the kernel command-line variable 'root' to 'root=PARTUUID=...' unless 'GRUB_DISABLE_LINUX_PARTUUID' is also set to 'true'. If 'GRUB_DISABLE_LINUX_PARTUUID' is also set to 'true', 'grub-command' will identify by its Linux device name. The following table summarizes the behavior of the 'grub-mkconfig' command. Initrd GRUB_DISABLE_LINUX_PARTUUID GRUB_DISABLE_LINUX_UUID Linux Root detected Set To Set To ID Method -------------------------------------------------------------------------------- false false false part UUID false false true part UUID false true false dev name false true true dev name true false false fs UUID true false true part UUID true true false fs UUID true true true dev name Remember, 'GRUB_DISABLE_LINUX_PARTUUID' and 'GRUB_DISABLE_LINUX_UUID' are also considered to be set to 'false' when they are unset. 6.3 Writing full configuration files directly ============================================= 'grub.cfg' is written in GRUB's built-in scripting language, which has a syntax quite similar to that of GNU Bash and other Bourne shell derivatives. Words ===== A "word" is a sequence of characters considered as a single unit by GRUB. Words are separated by "metacharacters", which are the following plus space, tab, and newline: { } | & $ ; < > Quoting may be used to include metacharacters in words; see below. Reserved words ============== Reserved words have a special meaning to GRUB. The following words are recognised as reserved when unquoted and either the first word of a simple command or the third word of a 'for' command: ! [[ ]] { } case do done elif else esac fi for function if in menuentry select then time until while Not all of these reserved words have a useful purpose yet; some are reserved for future expansion. Quoting ======= Quoting is used to remove the special meaning of certain characters or words. It can be used to treat metacharacters as part of a word, to prevent reserved words from being recognised as such, and to prevent variable expansion. There are three quoting mechanisms: the escape character, single quotes, and double quotes. A non-quoted backslash (\) is the "escape character". It preserves the literal value of the next character that follows, with the exception of newline. Enclosing characters in single quotes preserves the literal value of each character within the quotes. A single quote may not occur between single quotes, even when preceded by a backslash. Enclosing characters in double quotes preserves the literal value of all characters within the quotes, with the exception of '$' and '\'. The '$' character retains its special meaning within double quotes. The backslash retains its special meaning only when followed by one of the following characters: '$', '"', '\', or newline. A backslash-newline pair is treated as a line continuation (that is, it is removed from the input stream and effectively ignored(1) (*note Shell-like scripting-Footnote-1::)). A double quote may be quoted within double quotes by preceding it with a backslash. Variable expansion ================== The '$' character introduces variable expansion. The variable name to be expanded may be enclosed in braces, which are optional but serve to protect the variable to be expanded from characters immediately following it which could be interpreted as part of the name. Normal variable names begin with an alphabetic character, followed by zero or more alphanumeric characters. These names refer to entries in the GRUB environment (*note Environment::). Positional variable names consist of one or more digits. They represent parameters passed to function calls, with '$1' representing the first parameter, and so on. The special variable name '?' expands to the exit status of the most recently executed command. When positional variable names are active, other special variable names '@', '*' and '#' are defined and they expand to all positional parameters with necessary quoting, positional parameters without any quoting, and positional parameter count respectively. Comments ======== A word beginning with '#' causes that word and all remaining characters on that line to be ignored. Simple commands =============== A "simple command" is a sequence of words separated by spaces or tabs and terminated by a semicolon or a newline. The first word specifies the command to be executed. The remaining words are passed as arguments to the invoked command. The return value of a simple command is its exit status. If the reserved word '!' precedes the command, then the return value is instead the logical negation of the command's exit status. Compound commands ================= A "compound command" is one of the following: for NAME in WORD ...; do LIST; done The list of words following 'in' is expanded, generating a list of items. The variable NAME is set to each element of this list in turn, and LIST is executed each time. The return value is the exit status of the last command that executes. If the expansion of the items following 'in' results in an empty list, no commands are executed, and the return status is 0. if LIST; then LIST; [elif LIST; then LIST;] ... [else LIST;] fi The 'if' LIST is executed. If its exit status is zero, the 'then' LIST is executed. Otherwise, each 'elif' LIST is executed in turn, and if its exit status is zero, the corresponding 'then' LIST is executed and the command completes. Otherwise, the 'else' LIST is executed, if present. The exit status is the exit status of the last command executed, or zero if no condition tested true. while COND; do LIST; done until COND; do LIST; done The 'while' command continuously executes the 'do' LIST as long as the last command in COND returns an exit status of zero. The 'until' command is identical to the 'while' command, except that the test is negated; the 'do' LIST is executed as long as the last command in COND returns a non-zero exit status. The exit status of the 'while' and 'until' commands is the exit status of the last 'do' LIST command executed, or zero if none was executed. function NAME { COMMAND; ... } This defines a function named NAME. The "body" of the function is the list of commands within braces, each of which must be terminated with a semicolon or a newline. This list of commands will be executed whenever NAME is specified as the name of a simple command. Function definitions do not affect the exit status in '$?'. When executed, the exit status of a function is the exit status of the last command executed in the body. menuentry TITLE ['--class=class' ...] ['--users=users'] ['--unrestricted'] ['--hotkey=key'] ['--id=id'] { COMMAND; ... } *Note menuentry::. Built-in Commands ================= Some built-in commands are also provided by GRUB script to help script writers perform actions that are otherwise not possible. For example, these include commands to jump out of a loop without fully completing it, etc. break ['n'] Exit from within a 'for', 'while', or 'until' loop. If 'n' is specified, break 'n' levels. 'n' must be greater than or equal to 1. If 'n' is greater than the number of enclosing loops, all enclosing loops are exited. The return value is 0 unless 'n' is not greater than or equal to 1. continue ['n'] Resume the next iteration of the enclosing 'for', 'while' or 'until' loop. If 'n' is specified, resume at the 'n'th enclosing loop. 'n' must be greater than or equal to 1. If 'n' is greater than the number of enclosing loops, the last enclosing loop (the "top-level" loop) is resumed. The return value is 0 unless 'n' is not greater than or equal to 1. return ['n'] Causes a function to exit with the return value specified by 'n'. If 'n' is omitted, the return status is that of the last command executed in the function body. If used outside a function the return status is false. setparams ['arg'] ... Replace positional parameters starting with '$1' with arguments to 'setparams'. shift ['n'] The positional parameters from 'n'+1 ... are renamed to '$1'.... Parameters represented by the numbers '$#' down to '$#'-'n'+1 are unset. 'n' must be a non-negative number less than or equal to '$#'. If 'n' is 0, no parameters are changed. If 'n' is not given, it is assumed to be 1. If 'n' is greater than '$#', the positional parameters are not changed. The return status is greater than zero if 'n' is greater than '$#' or less than zero; otherwise 0. (1) Currently a backslash-newline pair within a variable name is not handled properly, so use this feature with some care. 6.4 Multi-boot manual config ============================ Currently autogenerating config files for multi-boot environments depends on os-prober and has several shortcomings. While fixing it is scheduled for the next release, meanwhile you can make use of the power of GRUB syntax and do it yourself. A possible configuration is detailed here, feel free to adjust to your needs. First create a separate GRUB partition, big enough to hold GRUB. Some of the following entries show how to load OS installer images from this same partition, for that you obviously need to make the partition large enough to hold those images as well. Mount this partition on/mnt/boot and disable GRUB in all OSes and manually install self-compiled latest GRUB with: 'grub-install --boot-directory=/mnt/boot /dev/sda' In all the OSes install GRUB tools but disable installing GRUB in bootsector, so you'll have menu.lst and grub.cfg available for use. Also disable os-prober use by setting: 'GRUB_DISABLE_OS_PROBER=true' in /etc/default/grub Then write a grub.cfg (/mnt/boot/grub/grub.cfg): menuentry "OS using grub2" { insmod xfs search --set=root --label OS1 --hint hd0,msdos8 configfile /boot/grub/grub.cfg } menuentry "OS using grub2-legacy" { insmod ext2 search --set=root --label OS2 --hint hd0,msdos6 legacy_configfile /boot/grub/menu.lst } menuentry "Windows XP" { insmod ntfs search --set=root --label WINDOWS_XP --hint hd0,msdos1 ntldr /ntldr } menuentry "Windows 7" { insmod ntfs search --set=root --label WINDOWS_7 --hint hd0,msdos2 ntldr /bootmgr } menuentry "FreeBSD" { insmod zfs search --set=root --label freepool --hint hd0,msdos7 kfreebsd /freebsd@/boot/kernel/kernel kfreebsd_module_elf /freebsd@/boot/kernel/opensolaris.ko kfreebsd_module_elf /freebsd@/boot/kernel/zfs.ko kfreebsd_module /freebsd@/boot/zfs/zpool.cache type=/boot/zfs/zpool.cache set kFreeBSD.vfs.root.mountfrom=zfs:freepool/freebsd set kFreeBSD.hw.psm.synaptics_support=1 } menuentry "experimental GRUB" { search --set=root --label GRUB --hint hd0,msdos5 multiboot /experimental/grub/i386-pc/core.img } menuentry "Fedora 16 installer" { search --set=root --label GRUB --hint hd0,msdos5 linux /fedora/vmlinuz lang=en_US keymap=sg resolution=1280x800 initrd /fedora/initrd.img } menuentry "Fedora rawhide installer" { search --set=root --label GRUB --hint hd0,msdos5 linux /fedora/vmlinuz repo=ftp://mirror.switch.ch/mirror/fedora/linux/development/rawhide/x86_64 lang=en_US keymap=sg resolution=1280x800 initrd /fedora/initrd.img } menuentry "Debian sid installer" { search --set=root --label GRUB --hint hd0,msdos5 linux /debian/dists/sid/main/installer-amd64/current/images/hd-media/vmlinuz initrd /debian/dists/sid/main/installer-amd64/current/images/hd-media/initrd.gz } Notes: * Argument to search after -label is FS LABEL. You can also use UUIDs with -fs-uuid UUID instead of -label LABEL. You could also use direct 'root=hd0,msdosX' but this is not recommended due to device name instability. 6.5 Embedding a configuration file into GRUB ============================================ GRUB supports embedding a configuration file directly into the core image, so that it is loaded before entering normal mode. This is useful, for example, when it is not straightforward to find the real configuration file, or when you need to debug problems with loading that file. 'grub-install' uses this feature when it is not using BIOS disk functions or when installing to a different disk from the one containing '/boot/grub', in which case it needs to use the 'search' command (*note search::) to find '/boot/grub'. To embed a configuration file, use the '-c' option to 'grub-mkimage'. The file is copied into the core image, so it may reside anywhere on the file system, and may be removed after running 'grub-mkimage'. After the embedded configuration file (if any) is executed, GRUB will load the 'normal' module (*note normal::), which will then read the real configuration file from '$prefix/grub.cfg'. By this point, the 'root' variable will also have been set to the root device name. For example, 'prefix' might be set to '(hd0,1)/boot/grub', and 'root' might be set to 'hd0,1'. Thus, in most cases, the embedded configuration file only needs to set the 'prefix' and 'root' variables, and then drop through to GRUB's normal processing. A typical example of this might look like this: search.fs_uuid 01234567-89ab-cdef-0123-456789abcdef root set prefix=($root)/boot/grub (The 'search_fs_uuid' module must be included in the core image for this example to work.) In more complex cases, it may be useful to read other configuration files directly from the embedded configuration file. This allows such things as reading files not called 'grub.cfg', or reading files from a directory other than that where GRUB's loadable modules are installed. To do this, include the 'configfile' and 'normal' modules in the core image, and embed a configuration file that uses the 'configfile' command to load another file. The following example of this also requires the 'echo', 'search_label', and 'test' modules to be included in the core image: search.fs_label grub root if [ -e /boot/grub/example/test1.cfg ]; then set prefix=($root)/boot/grub configfile /boot/grub/example/test1.cfg else if [ -e /boot/grub/example/test2.cfg ]; then set prefix=($root)/boot/grub configfile /boot/grub/example/test2.cfg else echo "Could not find an example configuration file!" fi fi The embedded configuration file may not contain menu entries directly, but may only read them from elsewhere using 'configfile'.