529 lines
24 KiB
Python
529 lines
24 KiB
Python
"""
|
|
SPDX-FileCopyrightText: 2023-2025 PeppermintOS Team
|
|
(peppermintosteam@proton.me)
|
|
|
|
SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
This module handles the creation of bootloaders for different architectures and boot methods.
|
|
|
|
Credits:
|
|
- PeppermintOS Team (peppermintosteam@proton.me) - Development and maintenance of the project.
|
|
|
|
License:
|
|
This code is distributed under the GNU General Public License version 3 or later (GPL-3.0-or-later).
|
|
For more details, please refer to the LICENSE file included in the project or visit:
|
|
https://www.gnu.org/licenses/gpl-3.0.html
|
|
"""
|
|
import os
|
|
import shutil
|
|
import subprocess
|
|
import tempfile
|
|
import logging
|
|
import sys
|
|
import contextlib
|
|
|
|
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|
sys.path.insert(0, BASE_DIR)
|
|
|
|
try:
|
|
from builder.core.bootstrap.paths import paths
|
|
from builder.configs import logger_config
|
|
from builder.core.copy_customizations import copy_grub_theme
|
|
except ImportError as e:
|
|
print(f"Error importing necessary modules: {e}. Ensure your environment is set up correctly. Details: {e}")
|
|
sys.exit(1)
|
|
|
|
logger = logger_config.setup_logger('bootloaders')
|
|
|
|
|
|
|
|
def create_isolinux_boot(architecture, kernel_version, keymap="us", locale="en_US.UTF-8", boot_title="Peppermint OS pep", boot_cmdline="", Volume_ID=""):
|
|
"""Generates Isolinux bootloader for BIOS."""
|
|
logger.info("=> Starting Isolinux bootloader generation...")
|
|
|
|
isolinux_dir = os.path.join(paths['IMAGEDIR'], 'boot', 'isolinux')
|
|
boot_dir = os.path.join(paths['IMAGEDIR'], 'boot')
|
|
os.makedirs(isolinux_dir, exist_ok=True)
|
|
|
|
# Create boot.cat - usually created by mkisofs/xorriso
|
|
boot_cat_path = os.path.join(isolinux_dir, "boot.cat")
|
|
open(boot_cat_path, 'w').close()
|
|
logger.info(f"=> Created empty boot.cat file: {boot_cat_path} (will be populated by mkisofs/xorriso)")
|
|
|
|
syslinux_data_dir = os.path.join(paths['PEPTARGETDIR'], "usr/lib/syslinux")
|
|
SPLASH_DIR = paths['SPLASH_DIR']
|
|
TEMPLATES_DIR = paths['TEMPLATES_DIR']
|
|
splash_image_path = os.path.join(SPLASH_DIR, "splash.png")
|
|
|
|
logger.info(f"=> Destination Isolinux directory: {isolinux_dir}")
|
|
logger.info(f"=> Syslinux data source directory: {syslinux_data_dir}")
|
|
logger.info(f"=> Splash image path: {splash_image_path}")
|
|
|
|
# 1. Copy Syslinux files
|
|
syslinux_files = [
|
|
"isolinux.bin", "ldlinux.c32", "libcom32.c32", "vesamenu.c32",
|
|
"libutil.c32", "chain.c32", "reboot.c32", "poweroff.c32"
|
|
]
|
|
logger.info("=> Copying Syslinux files...")
|
|
for file in syslinux_files:
|
|
source_file = os.path.join(syslinux_data_dir, file)
|
|
destination_file = os.path.join(isolinux_dir, file)
|
|
if os.path.exists(source_file):
|
|
shutil.copy2(source_file, destination_file)
|
|
logger.debug(f" Copied: {file}")
|
|
else:
|
|
logger.warning(f" Syslinux file not found: {source_file}. Ignoring.")
|
|
|
|
# 2. Copy and configure isolinux.cfg
|
|
logger.info("=> Copying and configuring isolinux.cfg...")
|
|
isolinux_cfg_in_path = os.path.join(TEMPLATES_DIR, "isolinux", "isolinux.cfg.in")
|
|
isolinux_cfg_path = os.path.join(isolinux_dir, "isolinux.cfg")
|
|
try:
|
|
with open(isolinux_cfg_in_path, 'r') as f_in:
|
|
isolinux_cfg_content = f_in.read()
|
|
|
|
# Perform replacements - consolidated replacements
|
|
replacements = {
|
|
"@@SPLASHIMAGE@@": os.path.basename(splash_image_path),
|
|
"@@KERNVER@@": kernel_version,
|
|
"@@KEYMAP@@": keymap,
|
|
"@@ARCH@@": architecture,
|
|
"@@LOCALE@@": locale,
|
|
"@@BOOT_TITLE@@": boot_title,
|
|
"@@BOOT_CMDLINE@@": boot_cmdline,
|
|
"@@Volume_ID@@": Volume_ID
|
|
}
|
|
for placeholder, value in replacements.items():
|
|
isolinux_cfg_content = isolinux_cfg_content.replace(placeholder, value)
|
|
with open(isolinux_cfg_path, 'w') as f_out:
|
|
f_out.write(isolinux_cfg_content)
|
|
logger.debug(f" isolinux.cfg file created at: {isolinux_cfg_path}")
|
|
except FileNotFoundError:
|
|
logger.error(f" isolinux.cfg.in template file not found: {isolinux_cfg_in_path}. Failed to create isolinux.cfg")
|
|
return None
|
|
except Exception as e:
|
|
logger.error(f" Error processing or creating isolinux.cfg: {e}")
|
|
return None
|
|
|
|
# 3. Copy splash image
|
|
logger.info("=> Copying splash image...")
|
|
if os.path.exists(splash_image_path):
|
|
splash_destination_path = os.path.join(isolinux_dir, os.path.basename(splash_image_path))
|
|
shutil.copy2(splash_image_path, splash_destination_path)
|
|
logger.debug(f" Splash image copied to: {splash_destination_path}")
|
|
else:
|
|
logger.warning(f" Splash image not found: {splash_image_path}. Ignoring.")
|
|
|
|
# 4 & 5. Copy memtest86+ and memtest86+ EFI (if exist) - Combined similar logic
|
|
memtest_files = {
|
|
"memtest.bin": os.path.join(paths['PEPTARGETDIR'], "boot", "memtest86+", "memtest.bin"),
|
|
"memtest.efi": os.path.join(paths['PEPTARGETDIR'], "boot", "memtest86+", "memtest.efi")
|
|
}
|
|
for filename, source_path in memtest_files.items():
|
|
dest_path = os.path.join(boot_dir, filename)
|
|
if os.path.exists(source_path):
|
|
logger.info(f"=> Copying {filename}...")
|
|
shutil.copy2(source_path, dest_path)
|
|
logger.debug(f" {filename} copied to: {dest_path}")
|
|
else:
|
|
logger.info(f"=> {filename} not found in PEPTARGETDIR. Ignoring.")
|
|
logger.info("=> Isolinux bootloader generated successfully.")
|
|
return isolinux_dir
|
|
|
|
def create_grub_efi_boot(architecture, paths, grub_cfg_template_dir, memtest_wanted, config, logger, pep_target_path, platform_cmdline, splash_image, grub_themes, grub_modules, boot_dir, kernel_version, boot_cmdline="", boot_title="Peppermint OS pep", keymap="us", locale="en_US.UTF-8"):
|
|
"""Generates GRUB EFI bootloader."""
|
|
logger.info("=> Starting GRUB EFI bootloader generation...")
|
|
|
|
grub_platform = f"{architecture}-efi"
|
|
grub_dir = os.path.join(paths['IMAGEDIR'], 'boot', 'grub')
|
|
pep_target_path = paths['PEPTARGETDIR']
|
|
iso_image_boot_dir = paths['IMAGEDIR']
|
|
grub_data_dir = pep_target_path + "/usr/share/grub"
|
|
TEMPLATES_DIR = paths['TEMPLATES_DIR']
|
|
SPLASH_DIR = paths['SPLASH_DIR']
|
|
SPLASH_THEMES_DIR = os.path.join(BASE_DIR, "peppermint/grub/themes")
|
|
iso_boot_path = os.path.join(paths['IMAGEDIR'], 'boot')
|
|
copy_grub_theme(SPLASH_THEMES_DIR, iso_boot_path)
|
|
|
|
os.makedirs(grub_dir, exist_ok=True)
|
|
|
|
# 1. Copy additional files from TEMPLATES_DIR
|
|
logger.info("=> Copying additional template files to the GRUB directory...")
|
|
|
|
# Source directory for templates
|
|
templates_grub_dir = os.path.join(TEMPLATES_DIR, "grub")
|
|
|
|
# List of files to copy
|
|
files_to_copy = ["grub.cfg"]
|
|
|
|
logger.info("=> Copying template files to the GRUB directory...")
|
|
|
|
for filename in files_to_copy:
|
|
source_path = os.path.join(templates_grub_dir, filename)
|
|
dest_path = os.path.join(grub_dir, filename)
|
|
if os.path.exists(source_path):
|
|
shutil.copy2(source_path, dest_path)
|
|
logger.debug(f" Copied template file: {filename} to: {dest_path}")
|
|
else:
|
|
logger.warning(f" Template file not found: {filename} in: {source_path}")
|
|
|
|
# Copy splash image from SPLASH_DIR to grub_dir
|
|
splash_source = os.path.join(SPLASH_DIR, "splash.png")
|
|
splash_dest = os.path.join(grub_dir, "splash.png")
|
|
|
|
if os.path.exists(splash_source):
|
|
shutil.copy2(splash_source, splash_dest)
|
|
logger.debug(f" Copied splash image from: {splash_source} to: {splash_dest}")
|
|
else:
|
|
logger.warning(f" Splash image not found in: {splash_source}")
|
|
|
|
kernel_img_name = "vmlinuz"
|
|
want_memtest = True
|
|
if architecture == "aarch64":
|
|
kernel_img_name = "vmlinux"
|
|
want_memtest = False
|
|
elif architecture == "x86_64":
|
|
kernel_img_name = "vmlinuz"
|
|
|
|
logger.info(f"=> Destination GRUB directory: {grub_dir}")
|
|
logger.info(f"=> GRUB data source directory: {grub_data_dir}")
|
|
logger.info(f"=> Kernel image name: {kernel_img_name}")
|
|
logger.info(f"=> Want memtest86+: {want_memtest}")
|
|
|
|
# 1. Prepare GRUB directory and copy font
|
|
logger.info("=> Preparing GRUB directory and copying fonts...")
|
|
os.makedirs(os.path.join(grub_dir, "fonts"), exist_ok=True)
|
|
unicode_pf2_source = os.path.join(grub_data_dir, "unicode.pf2")
|
|
unicode_pf2_dest = os.path.join(grub_dir, "fonts", "unicode.pf2")
|
|
if os.path.exists(unicode_pf2_source):
|
|
shutil.copy2(unicode_pf2_source, unicode_pf2_dest)
|
|
logger.debug(f" Copied unicode.pf2 font to: {unicode_pf2_dest}")
|
|
else:
|
|
logger.warning(f" unicode.pf2 font not found in: {unicode_pf2_source}. Ignoring.")
|
|
|
|
|
|
# 2. Create EFI vfat image
|
|
logger.info("=> Creating EFI vfat image...")
|
|
efi_img_path = os.path.join(grub_dir, "efiboot.img")
|
|
try:
|
|
subprocess.run(["truncate", "-s", "32M", efi_img_path], check=True, text=True)
|
|
subprocess.run(["mkfs.vfat", "-F12", "-S", "512", "-n", "grub_uefi", efi_img_path], check=True, text=True)
|
|
logger.debug(f" EFI vfat image created: {efi_img_path}")
|
|
except subprocess.CalledProcessError as e:
|
|
logger.error(f" Error creating EFI vfat image: {e.stderr}")
|
|
return None
|
|
|
|
|
|
# 3. Mount vfat image and build GRUB image function
|
|
grub_efi_tmpdir = tempfile.mkdtemp(dir=paths['BUILDDIR'], prefix="grub-efi.")
|
|
loop_device = None
|
|
try:
|
|
loop_device_output = subprocess.run(["losetup", "--show", "--find", efi_img_path], check=True, text=True, capture_output=True)
|
|
|
|
# Check if loop_device_output is None or has an error
|
|
if loop_device_output is None or loop_device_output.returncode != 0:
|
|
logger.error(f" Error: loop_device_output is None or has an error. losetup command failed? Stderr: {loop_device_output.stderr.decode()}")
|
|
return None
|
|
|
|
loop_device = loop_device_output.stdout.strip()
|
|
subprocess.run(["mount", "-o", "rw,loop,offset=0", loop_device, grub_efi_tmpdir], check=True, text=True)
|
|
logger.debug(f" EFI vfat image mounted at: {grub_efi_tmpdir}, loop device: {loop_device}")
|
|
|
|
# Copy boot dir
|
|
logger.info("=> Copying boot directory and building GRUB images for architecture...")
|
|
copy_boot_directory_contents(os.path.join(iso_image_boot_dir, 'boot'), os.path.join(pep_target_path, 'boot'))
|
|
logger.debug(f" => Boot directory copied to: {os.path.join(pep_target_path, 'boot')}")
|
|
|
|
# Generate the content of grub_pep.cfg
|
|
desktop_environment = config.get("desktop", "XFCE")
|
|
kernel_flavor_name = config.get("kernel_flavor", "current")
|
|
|
|
logger.debug(f" Value of boot_cmdline being passed to generate_grub_pep_cfg: '{boot_cmdline}'")
|
|
|
|
grub_pep_cfg_content = generate_grub_pep_cfg(
|
|
kernel_version=kernel_version,
|
|
boot_cmdline=boot_cmdline,
|
|
boot_title=boot_title,
|
|
keymap=keymap,
|
|
locale=locale,
|
|
architecture=architecture,
|
|
want_memtest=want_memtest,
|
|
splash_image=splash_image,
|
|
SPLASH_DIR=paths['SPLASH_DIR']
|
|
)
|
|
|
|
# Write the content to the grub_pep.cfg file
|
|
grub_pep_cfg_path = os.path.join(grub_dir, "grub_pep.cfg")
|
|
with open(grub_pep_cfg_path, "w") as f:
|
|
f.write(grub_pep_cfg_content)
|
|
logger.info(f" grub_pep.cfg generated at: {grub_pep_cfg_path}")
|
|
|
|
def build_grub_image(architecture, grub_arch, efi_arch, grub_platform):
|
|
"""Internal function to build the GRUB EFI image for an architecture."""
|
|
logger.info(f"Building GRUB EFI image for architecture: {architecture}")
|
|
logger.info(f" => Building GRUB EFI image for GRUB arch: {grub_arch}, EFI: {efi_arch}...")
|
|
efi_file_tmp_path = os.path.join("/tmp", f"boot{efi_arch.lower()}.efi")
|
|
|
|
grub_mkstandalone_command = [
|
|
"xbps-uchroot",
|
|
pep_target_path,
|
|
"grub-mkstandalone",
|
|
"--",
|
|
f"--directory=/usr/lib/grub/{grub_platform}",
|
|
f"--format={grub_platform}",
|
|
f"--format={grub_platform}",
|
|
f"--output={efi_file_tmp_path}",
|
|
f"boot/grub/grub.cfg"
|
|
]
|
|
try:
|
|
logger.debug(f" => Creating EFI/BOOT directory in: {os.path.join(grub_efi_tmpdir, 'EFI', 'BOOT')}")
|
|
subprocess.run(["mkdir", "-p", os.path.join(grub_efi_tmpdir, "EFI", "BOOT")], check=True)
|
|
logger.debug(f" EFI/BOOT directory created successfully.")
|
|
|
|
logger.debug(f" => Executing grub-mkstandalone command [CHROOT: {pep_target_path}]: {' '.join(grub_mkstandalone_command)}")
|
|
subprocess.run(grub_mkstandalone_command, check=True,text=True)
|
|
logger.debug(f" grub-mkstandalone command executed successfully.")
|
|
|
|
efi_boot_dir_in_tmpfs = os.path.join(grub_efi_tmpdir, "EFI", "BOOT")
|
|
os.makedirs(efi_boot_dir_in_tmpfs, exist_ok=True)
|
|
|
|
efi_source_path_on_host = os.path.join(pep_target_path, "tmp", f"boot{efi_arch.lower()}.efi")
|
|
efi_file_destination = os.path.join(efi_boot_dir_in_tmpfs, f"BOOT{efi_arch.upper()}.EFI")
|
|
shutil.copy2(efi_source_path_on_host, efi_file_destination)
|
|
logger.debug(f" EFI loader copied to: {efi_file_destination}")
|
|
|
|
except subprocess.CalledProcessError as e:
|
|
logger.error(f" Error generating EFI loader (grub-mkstandalone): {e}")
|
|
raise
|
|
except OSError as e:
|
|
logger.error(f" OSError during grub-mkstandalone: {e}")
|
|
raise
|
|
except Exception as e:
|
|
logger.error(f" Unexpected error during grub-mkstandalone: {e}")
|
|
raise
|
|
efi_images = {}
|
|
|
|
if architecture in ["i686", "x86_64"]:
|
|
for arch in ["i686", "x86_64"]:
|
|
if arch == "i686":
|
|
grub_arch = "i386"
|
|
efi_arch = "ia32"
|
|
grub_platform = "i386-efi"
|
|
elif arch == "x86_64":
|
|
grub_arch = "x86_64"
|
|
efi_arch = "x64"
|
|
grub_platform = "x86_64-efi"
|
|
|
|
efi_images[arch] = build_grub_image(architecture, grub_arch, efi_arch, grub_platform)
|
|
|
|
elif architecture == "aarch64":
|
|
grub_platform = "arm64-efi"
|
|
build_grub_image(architecture, "arm64", "aa64", grub_platform)
|
|
|
|
logger.info("=> Copying EFI boot files from efiboot.img to ISO root...")
|
|
efi_boot_dest_in_iso = os.path.join(paths['IMAGEDIR'], 'EFI', 'BOOT')
|
|
os.makedirs(efi_boot_dest_in_iso, exist_ok=True)
|
|
|
|
try:
|
|
mount_point = tempfile.mkdtemp(dir=paths['BUILDDIR'], prefix="efi-img-mnt.")
|
|
subprocess.run(["mount", "-o", "loop", efi_img_path, mount_point], check=True, text=True)
|
|
logger.debug(f" efiboot.img mounted at: {mount_point}")
|
|
|
|
efi_boot_source_in_img = os.path.join(mount_point, 'EFI', 'BOOT')
|
|
if os.path.exists(efi_boot_source_in_img):
|
|
for item in os.listdir(efi_boot_source_in_img):
|
|
source = os.path.join(efi_boot_source_in_img, item)
|
|
destination = os.path.join(efi_boot_dest_in_iso, item)
|
|
if os.path.isdir(source):
|
|
shutil.copytree(source, destination, dirs_exist_ok=True)
|
|
logger.debug(f" Copied EFI directory: {source} to {destination}")
|
|
else:
|
|
shutil.copy2(source, destination)
|
|
logger.debug(f" Copied EFI file: {source} to {destination}")
|
|
else:
|
|
logger.warning(f" EFI/BOOT directory not found in {efi_boot_source_in_img}")
|
|
|
|
except subprocess.CalledProcessError as e:
|
|
logger.error(f" Error mounting or copying files from efiboot.img: {e}")
|
|
except FileNotFoundError as e:
|
|
logger.error(f" File not found: {e}")
|
|
except Exception as e:
|
|
logger.error(f" Unexpected error while copying EFI files: {e}")
|
|
finally:
|
|
if 'mount_point' in locals():
|
|
subprocess.run(["umount", mount_point], check=True, text=True)
|
|
os.rmdir(mount_point)
|
|
logger.debug(f" efiboot.img unmounted from: {mount_point} and directory removed.")
|
|
|
|
logger.info("=> GRUB EFI bootloader generated successfully.")
|
|
return grub_dir
|
|
|
|
except subprocess.CalledProcessError as e:
|
|
logger.error(f"Error executing subprocess commands for GRUB EFI: {e}")
|
|
return None
|
|
except Exception as e:
|
|
logger.error(f"Unexpected error while generating GRUB EFI: {e}")
|
|
return None
|
|
finally:
|
|
if grub_efi_tmpdir:
|
|
try:
|
|
subprocess.run(["umount", grub_efi_tmpdir], check=True)
|
|
logger.debug(f" EFI vfat image unmounted from: {grub_efi_tmpdir}")
|
|
except subprocess.CalledProcessError as e:
|
|
logger.warning(f" Warning: Failed to unmount EFI vfat image: {e}")
|
|
if loop_device:
|
|
try:
|
|
subprocess.run(["losetup", "--detach", loop_device], check=True)
|
|
logger.debug(f" Loop device {loop_device} detached.")
|
|
except subprocess.CalledProcessError as e:
|
|
logger.warning(f" Warning: Failed to detach loop device {loop_device}: {e}")
|
|
if grub_efi_tmpdir:
|
|
shutil.rmtree(grub_efi_tmpdir, ignore_errors=True)
|
|
logger.debug(f" Temporary directory {grub_efi_tmpdir} removed.")
|
|
|
|
def copy_boot_directory_contents(source_boot_dir, dest_boot_dir):
|
|
"""Copies contents of source boot dir to dest boot dir, merging if necessary."""
|
|
logger.info(f" => Copying boot directory contents from: {source_boot_dir} to: {dest_boot_dir} (merge)...")
|
|
os.makedirs(dest_boot_dir, exist_ok=True)
|
|
|
|
for item in os.listdir(source_boot_dir):
|
|
s_item = os.path.join(source_boot_dir, item)
|
|
d_item = os.path.join(dest_boot_dir, item)
|
|
if os.path.isdir(s_item):
|
|
logger.debug(f" Merging directory: {item}")
|
|
shutil.copytree(s_item, d_item, dirs_exist_ok=True)
|
|
else:
|
|
logger.debug(f" Copying file: {item}")
|
|
shutil.copy2(s_item, d_item)
|
|
|
|
logger.debug(" => Boot directory contents copied/merged successfully.")
|
|
|
|
def generate_grub_pep_cfg(kernel_version, boot_cmdline, boot_title, keymap, locale, architecture, want_memtest, splash_image, SPLASH_DIR):
|
|
"""Generates the content of grub_pep.cfg using the provided template."""
|
|
grub_pep_cfg_template = """
|
|
|
|
set pager="1"
|
|
set locale_dir="(${peppermintos})/boot/grub/locale"
|
|
set theme="(${peppermintos})/boot/grub/themes/peppermint/theme.txt"
|
|
|
|
if [ -e "${prefix}/${grub_cpu}-${grub_platform}/all_video.mod" ]; then
|
|
insmod all_video
|
|
else
|
|
insmod efi_gop
|
|
insmod efi_uga
|
|
insmod video_bochs
|
|
insmod video_cirrus
|
|
fi
|
|
|
|
insmod font
|
|
|
|
if loadfont "(${peppermintos})/boot/grub/fonts/unicode.pf2" ; then
|
|
insmod gfxterm
|
|
set gfxmode="auto"
|
|
|
|
terminal_input console
|
|
terminal_output gfxterm
|
|
|
|
insmod png
|
|
background_image "(${peppermintos})/boot/isolinux/@@SPLASHIMAGE@@"
|
|
fi
|
|
|
|
# Set default menu entry
|
|
default=linux
|
|
timeout=15
|
|
timeout_style=menu
|
|
|
|
# GRUB init tune for accessibility
|
|
play 600 988 1 1319 4
|
|
|
|
if [ cpuid -l ]; then
|
|
menuentry "@@BOOT_TITLE@@ @@KERNVER@@ (@@ARCH@@)" --id "linux" {
|
|
set gfxpayload="keep"
|
|
linux (${peppermintos})/boot/vmlinuz \\
|
|
root=live:CDLABEL=PEPPERMINTOS ro init=/sbin/init \\
|
|
rd.luks=0 rd.md=0 rd.dm=0 loglevel=4 gpt add_efi_memmap \\
|
|
vconsole.unicode=1 vconsole.keymap=@@KEYMAP@@ \\
|
|
locale.LANG=@@LOCALE@@ @@BOOT_CMDLINE@@
|
|
initrd (${peppermintos})/boot/initrd
|
|
}
|
|
menuentry "@@BOOT_TITLE@@ @@KERNVER@@ (@@ARCH@@) (RAM)" --id "linuxram" {
|
|
set gfxpayload="keep"
|
|
linux (${peppermintos})/boot/vmlinuz \\
|
|
root=live:CDLABEL=PEPPERMINTOS ro init=/sbin/init \\
|
|
rd.luks=0 rd.md=0 rd.dm=0 loglevel=4 gpt add_efi_memmap \\
|
|
vconsole.unicode=1 vconsole.keymap=@@KEYMAP@@ \\
|
|
locale.LANG=@@LOCALE@@ @@BOOT_CMDLINE@@ rd.live.ram
|
|
initrd (${peppermintos})/boot/initrd
|
|
}
|
|
menuentry "@@BOOT_TITLE@@ @@KERNVER@@ (@@ARCH@@) (graphics disabled)" --id "linuxnogfx" {
|
|
set gfxpayload="keep"
|
|
linux (${peppermintos})/boot/vmlinuz \\
|
|
root=live:CDLABEL=PEPPERMINTOS ro init=/sbin/init \\
|
|
rd.luks=0 rd.md=0 rd.dm=0 loglevel=4 gpt add_efi_memmap \\
|
|
vconsole.unicode=1 vconsole.keymap=@@KEYMAP@@ \\
|
|
locale.LANG=@@LOCALE@@ @@BOOT_CMDLINE@@ nomodeset
|
|
initrd (${peppermintos})/boot/initrd
|
|
}
|
|
menuentry "@@BOOT_TITLE@@ @@KERNVER@@ (@@ARCH@@)" with speech --hotkey s --id "linuxa11y" {
|
|
set gfxpayload="keep"
|
|
linux (${peppermintos})/boot/vmlinuz \\
|
|
root=live:CDLABEL=PEPPERMINTOS ro init=/sbin/init \\
|
|
rd.luks=0 rd.md=0 rd.dm=0 loglevel=4 gpt add_efi_memmap \\
|
|
vconsole.unicode=1 vconsole.keymap=@@KEYMAP@@ \\
|
|
locale.LANG=@@LOCALE@@ @@BOOT_CMDLINE@@ live.accessibility live.autologin
|
|
initrd (${peppermintos})/boot/initrd
|
|
}
|
|
menuentry "@@BOOT_TITLE@@ @@KERNVER@@ (@@ARCH@@) with speech (RAM)" --hotkey r --id "linuxa11yram" {
|
|
set gfxpayload="keep"
|
|
linux (${peppermintos})/boot/vmlinuz \\
|
|
root=live:CDLABEL=PEPPERMINTOS ro init=/sbin/init \\
|
|
rd.luks=0 rd.md=0 rd.dm=0 loglevel=4 gpt add_efi_memmap \\
|
|
vconsole.unicode=1 vconsole.keymap=@@KEYMAP@@ \\
|
|
locale.LANG=@@LOCALE@@ @@BOOT_CMDLINE@@ live.accessibility live.autologin rd.live.ram
|
|
initrd (${peppermintos})/boot/initrd
|
|
}
|
|
menuentry "@@BOOT_TITLE@@ @@KERNVER@@ (@@ARCH@@) with speech (graphics disabled)" --hotkey g --id "linuxa11ynogfx" {
|
|
set gfxpayload="keep"
|
|
linux (${peppermintos})/boot/vmlinuz \\
|
|
root=live:CDLABEL=PEPPERMINTOS ro init=/sbin/init \\
|
|
rd.luks=0 rd.md=0 rd.dm=0 loglevel=4 gpt add_efi_memmap \\
|
|
vconsole.unicode=1 vconsole.keymap=@@KEYMAP@@ \\
|
|
locale.LANG=@@LOCALE@@ @@BOOT_CMDLINE@@ live.accessibility live.autologin nomodeset
|
|
initrd (${peppermintos})/boot/initrd
|
|
}
|
|
if [ "${grub_platform}" == "efi" ]; then
|
|
menuentry "Run Memtest86+ (RAM test)" --hotkey m --id memtest {
|
|
set gfxpayload="keep"
|
|
linux (${peppermintos})/boot/memtest.efi
|
|
}
|
|
menuentry 'UEFI Firmware Settings' --hotkey f --id uefifw {
|
|
fwsetup
|
|
}
|
|
else
|
|
menuentry "Run Memtest86+ (RAM test)" --id memtest {
|
|
set gfxpayload="keep"
|
|
linux (${peppermintos})/boot/memtest.bin
|
|
}
|
|
fi
|
|
|
|
menuentry "System restart" --hotkey b --id restart {
|
|
echo "System rebooting..."
|
|
reboot
|
|
}
|
|
|
|
menuentry "System shutdown" --hotkey p --id poweroff {
|
|
echo "System shutting down..."
|
|
halt
|
|
}
|
|
fi
|
|
"""
|
|
splash_image_path = os.path.join(SPLASH_DIR, "splash.png") if SPLASH_DIR else " "
|
|
grub_pep_cfg_content = grub_pep_cfg_template.replace("@@BOOT_TITLE@@", boot_title)
|
|
grub_pep_cfg_content = grub_pep_cfg_content.replace("@@KERNVER@@", kernel_version)
|
|
grub_pep_cfg_content = grub_pep_cfg_content.replace("@@ARCH@@", architecture)
|
|
grub_pep_cfg_content = grub_pep_cfg_content.replace("@@KEYMAP@@", keymap)
|
|
grub_pep_cfg_content = grub_pep_cfg_content.replace("@@LOCALE@@", locale)
|
|
grub_pep_cfg_content = grub_pep_cfg_content.replace("@@BOOT_CMDLINE@@", boot_cmdline)
|
|
grub_pep_cfg_content = grub_pep_cfg_content.replace("@@SPLASHIMAGE@@", os.path.basename(splash_image_path) if splash_image_path and os.path.exists(splash_image_path) else " ")
|
|
|
|
return grub_pep_cfg_content |