Advanced OS Customizations & Bootloaders

GRUB2 Scripting Masterclass: Crafting Dynamic Boot Menus for Android Dual-Boot

Google AdSense Native Placement - Horizontal Top-Post banner

Introduction to GRUB2 and Dynamic Boot Menus

GRUB2 (Grand Unified Bootloader, Version 2) is the cornerstone of modern Linux boot processes, offering immense flexibility and power. While its default configuration often suffices, truly advanced users can leverage GRUB2’s scripting capabilities to create dynamic boot menus. This masterclass will delve into crafting such menus, specifically focusing on automatically detecting and configuring Android-x86 installations for a seamless dual-boot experience, eliminating the need for manual updates to grub.cfg.

Why Dynamic Menus?

Static boot entries in grub.cfg are brittle. Any change to a partition layout, kernel version, or even the addition/removal of an OS necessitates manual editing and regeneration. Dynamic menus, however, automate this. By writing shell scripts that GRUB2 executes during configuration generation, we can detect available operating systems, their versions, and their locations, and then automatically create appropriate boot entries. This is particularly useful for volatile environments like Android-x86, which might reside on a separate partition or a loopback file system.

GRUB2’s Architecture: The /etc/grub.d Scripts

GRUB2’s configuration is primarily managed through scripts located in the /etc/grub.d/ directory. Instead of directly editing /boot/grub/grub.cfg, which is overwritten by update-grub (or grub-mkconfig), we interact with these scripts.

The Role of update-grub

The update-grub command is a wrapper for grub-mkconfig -o /boot/grub/grub.cfg. When executed, it sequentially runs all executable scripts in /etc/grub.d/. The output of these scripts is then concatenated into the final grub.cfg file. The order of execution is determined by the numeric prefix of the script filenames (e.g., 05_debian_theme runs before 10_linux).

Key Script Files

  • 00_header: Sets global GRUB2 variables like timeout and default entry.
  • 10_linux: Detects Linux kernels on the current system and generates entries.
  • 20_linux_xen: For Xen hypervisor entries.
  • 30_os-prober: Uses os-prober to detect other OS installations (Windows, macOS, other Linux distributions). This is often where Android-x86 might be detected, but not always reliably or with optimal parameters.
  • 40_custom: An empty script provided for users to add custom, static entries.
  • 41_custom: A variant of 40_custom for custom entries that appear after those generated by 30_os-prober.

Fundamentals of GRUB2 Scripting

The scripts in /etc/grub.d/ are BASH scripts. They can use standard shell commands, but critically, they must output GRUB2 configuration commands. These GRUB2 commands are what get written into grub.cfg.

GRUB2 Commands vs. Shell Commands

When writing a script in /etc/grub.d/, you are essentially writing a shell script that prints GRUB2 commands. For instance, to set a variable within the shell script, you use variable="value". To output a GRUB2 command that sets a GRUB2 variable, you would use echo "set grub_variable='value'".

Variables and Conditionals

Shell variables (e.g., ANDROID_ROOT_UUID) and conditionals (if [ -d "$ANDROID_DIR" ]) are essential for dynamic detection. GRUB2 itself also supports variables (set root=...) and conditionals, but for the detection logic, we rely on the shell script’s capabilities.

Detecting Android-x86 Installations

The core of our dynamic menu is reliably finding the Android-x86 installation. Android-x86 typically resides in a directory named /android-x86 (or similar, like /Android) containing a kernel and an initrd.img. It’s often on a separate partition.

Locating Partitions with GRUB2’s ls Command

While the detection happens within our shell script, it’s useful to understand how GRUB2 sees partitions. In the GRUB2 rescue shell, ls can list available disks and partitions (e.g., (hd0,msdos1) or (hd0,gpt1)).

Identifying Android Root with search.file

Within our script, we can leverage the search.file GRUB2 command. This command searches for a specific file across all available partitions and sets the root variable to the partition containing it. This is more robust than relying on static UUIDs or device names.

search.file --set=root_android /android-x86/kernel --hint-bios=hd0,msdos1 --hint-efi=hd0,gpt1 --hint-baremetal=ahci0,msdos1

The --hint-* parameters are optional but can speed up the search by providing likely locations.

Crafting the Dynamic Android Boot Script

Let’s create a script that automatically finds and configures Android-x86. We’ll assume Android-x86 is installed in a directory named /android-x86 on a partition.

Step 1: Create a New Script File

Create a new executable file in /etc/grub.d/. We’ll name it 42_android_auto so it runs after default OS probing but before 40_custom.

sudo nano /etc/grub.d/42_android_auto

Step 2: Script Content – The Core Logic

Paste the following script content. This script will try to locate /android-x86/kernel and generate a GRUB2 menu entry if found.

#!/bin/sh -e

# Source some GRUB2 utility functions
. /usr/share/grub/grub-helpers.sh

# Define Android installation directory name
ANDROID_DIR_NAME="android-x86"

# Define the kernel file to search for
ANDROID_KERNEL_FILE="/${ANDROID_DIR_NAME}/kernel"

# Check if an Android kernel exists on any partition
if grub_file_is_not_empty "${ANDROID_KERNEL_FILE}"; then
    echo "Found Android-x86 installation."

    # Use search.file to find the partition containing the kernel
    # and set the root_android variable to its GRUB device name.
    # Using --no-floppy and --fs-uuid is often more reliable.
    GRUB_ANDROID_ROOT_DEVICE="`grub_get_device_from_file "${ANDROID_KERNEL_FILE}"`"

    if [ -n "$GRUB_ANDROID_ROOT_DEVICE" ]; then
        # Output the menuentry for GRUB2
        cat << EOF
menuentry "Android-x86 (Dynamic)" {
    insmod gzio
    insmod part_msdos
    insmod part_gpt
    insmod ext2

    set root='${GRUB_ANDROID_ROOT_DEVICE}'
    search --no-floppy --fs-uuid --set=root_uuid ${GRUB_ANDROID_ROOT_DEVICE_UUID}
    # Assuming the kernel is in /android-x86/kernel relative to the root
    linux /${ANDROID_DIR_NAME}/kernel root=/dev/ram0 androidboot.hardware=android_x86 SRC=/${ANDROID_DIR_NAME} quiet CMDLINE_FORCE_PROBE=sata,usb video=-10:1920x1080
    initrd /${ANDROID_DIR_NAME}/initrd.img
}
EOF
    else
        echo "Warning: Could not determine GRUB device for Android-x86. Skipping entry."
    fi
else
    echo "No Android-x86 installation found."
fi

Explanation of the Script

  • #!/bin/sh -e: Standard shebang for a POSIX-compliant shell script.
  • . /usr/share/grub/grub-helpers.sh: Sources GRUB2’s helper functions, providing powerful tools like grub_file_is_not_empty and grub_get_device_from_file to simplify partition detection.
  • ANDROID_DIR_NAME, ANDROID_KERNEL_FILE: Variables for easy customization.
  • if grub_file_is_not_empty "${ANDROID_KERNEL_FILE}"; then: This is the critical detection step. It uses the helper function to check if the specified kernel file exists on any mounted partition.
  • GRUB_ANDROID_ROOT_DEVICE="`grub_get_device_from_file "${ANDROID_KERNEL_FILE}"`": If the kernel is found, this helper function determines the GRUB2-style device identifier (e.g., (hd0,msdos1)) for the partition containing the file.
  • cat << EOF ... EOF: This is a "here document" that outputs the actual GRUB2 menuentry block.
  • insmod gzio ... ext2: Loads necessary GRUB2 modules for file system and compression support. Adjust if your Android partition uses a different filesystem (e.g., ntfs, fat).
  • set root='${GRUB_ANDROID_ROOT_DEVICE}': Sets the root partition for the subsequent linux and initrd commands to the dynamically found device.
  • search --no-floppy --fs-uuid --set=root_uuid ${GRUB_ANDROID_ROOT_DEVICE_UUID}: This line is a powerful GRUB2 command for robust partition identification. The grub_get_device_from_file helper provides the UUID, making this extremely reliable across reboots or disk changes.
  • linux /${ANDROID_DIR_NAME}/kernel ...: The actual kernel path and boot parameters. SRC=/${ANDROID_DIR_NAME} is crucial for Android-x86 to find its system files. Adjust video= as needed for your display.
  • initrd /${ANDROID_DIR_NAME}/initrd.img: Specifies the initial RAM disk.

Step 3: Make the Script Executable

For GRUB2 to process your script, it must have execute permissions:

sudo chmod +x /etc/grub.d/42_android_auto

Step 4: Update GRUB Configuration

Finally, regenerate your grub.cfg:

sudo update-grub

You should see output indicating that your script was run and potentially found Android.

Testing and Troubleshooting Your Dynamic Menu

Rebooting and Verification

Reboot your system. You should now see "Android-x86 (Dynamic)" in your GRUB2 boot menu. Select it and verify that Android boots correctly.

Common Issues and Debugging Tips

  • Script Not Executing: Ensure /etc/grub.d/42_android_auto has execute permissions (chmod +x).
  • Android Not Found: Double-check the ANDROID_DIR_NAME and ANDROID_KERNEL_FILE variables in your script. Verify the exact path to your Android-x86 kernel.
  • Wrong Boot Parameters: Android-x86 is sensitive to kernel parameters. If it fails to boot, try booting into a working Linux OS, mount the Android partition, and examine its boot/grub/grub.cfg (if it has one) or documentation for correct SRC and other parameters.
  • GRUB2 Rescue Shell: If your system fails to boot, use the GRUB2 rescue shell (often accessed by pressing ‘c’ during boot) to debug. Use commands like ls, search.file, and cat to verify paths and file existence manually.
  • Syntax Errors: Shell script syntax errors or incorrect GRUB2 commands in your echo statements will lead to errors during update-grub or a broken grub.cfg. Carefully review your script.

Conclusion

By mastering GRUB2 scripting, you gain unparalleled control over your boot environment. This masterclass has equipped you with the knowledge to craft dynamic boot menu entries for Android-x86, making your dual-boot setup more robust and maintainable. The principles learned here can be extended to dynamically manage other operating systems, custom kernel builds, or specific system utilities, transforming your GRUB2 menu into an intelligent, self-configuring boot manager.

Android Mobile Specs & Compare Directory

Are you researching mobile hardware properties, processor SoCs, GPU chipsets, or RAM configurations? Access our complete specs catalog to compare up to 5 devices side-by-side!

Compare Devices Specs →
Google AdSense Inline Placement - Content Footer banner