diff --git a/_base.py b/_base.py index c35b2ca..d551975 100644 --- a/_base.py +++ b/_base.py @@ -4,6 +4,7 @@ import os import pathlib import shutil import subprocess +import tempfile ## import psutil import requests @@ -95,15 +96,20 @@ class BaseUpdater(object): req_chk = requests.head(self.iso_url, headers = {'User-Agent': 'curl/7.74.0'}) if not req_chk.ok: raise RuntimeError('Received non-200/30x {0} for {1}'.format(req_chk.status_code, self.iso_url)) - os.makedirs(os.path.dirname(self.dest_iso), exist_ok = True) + _tmpfile = tempfile.mkstemp()[1] with requests.get(self.iso_url, stream = True, headers = {'User-Agent': 'curl/7.74.0'}) as req: req.raise_for_status() - with open(self.dest_iso, 'wb') as fh: + with open(_tmpfile, 'wb') as fh: for chunk in req.iter_content(chunk_size = 8192): fh.write(chunk) realhash = self.getISOHash() if realhash != self.new_hash: + os.remove(_tmpfile) raise RuntimeError('Hash mismatch: {0} (LOCAL), {1} (REMOTE)'.format(realhash, self.new_hash)) + os.makedirs(os.path.dirname(self.dest_iso), exist_ok = True) + pathlib.Path(self.dest_iso).touch(mode = 0o0644, exist_ok = True) + shutil.copyfile(_tmpfile, self.dest_iso) + os.remove(_tmpfile) self.updateVer() return(None) diff --git a/arch.py b/arch.py index 7219c5b..0a15b10 100755 --- a/arch.py +++ b/arch.py @@ -1,6 +1,5 @@ #!/usr/bin/env python3 -# TODO: logging # Example .arch.json: # { # "date": "Fri, 01 Jan 2021 00:00:00 +0000", @@ -215,6 +214,7 @@ class Updater(_base.BaseUpdater): with open(self.dest_ver, 'w') as fh: fh.write(j) fh.write('\n') + os.chmod(self.dest_ver, 0o0644) return(None) diff --git a/grml.py b/grml.py index fb4b5de..95e8d23 100755 --- a/grml.py +++ b/grml.py @@ -79,7 +79,6 @@ class Updater(_base.BaseUpdater): self.do_update = True self.force_update = True self.old_ver = 0.00 - self.variant = 'full' return(None) with open(self.dest_ver, 'rb') as fh: ver_info = json.load(fh) @@ -153,6 +152,7 @@ class Updater(_base.BaseUpdater): with open(self.dest_ver, 'w') as fh: fh.write(j) fh.write('\n') + os.chmod(self.dest_ver, 0o0644) return(None) diff --git a/ipxe.py b/ipxe.py new file mode 100644 index 0000000..d4c00fe --- /dev/null +++ b/ipxe.py @@ -0,0 +1,179 @@ +#!/usr/bin/env python3 + +# Example .ipxe.json: +# { +# "date": "Thu, 21 Jan 2021 06:42:21 +0000", +# "variant": "efi", +# "sha512": "b4d2e517c69224bf14f79e155(...)" +# } +# They don't version the ISO, so we use the file date on the mirror listing. + +import datetime +import json +import os +import re +## +import requests +from bs4 import BeautifulSoup +## +import _base + +try: + import lxml + _has_lxml = True +except ImportError: + _has_lxml = False + + +class Updater(_base.BaseUpdater): + _fname_re = re.compile(r'^(?:.*/)?ipxe\.' + r'(?P(iso|efi))$') + _allowed_variants = ('iso', 'efi') + _tpl_file = 'ipxe_grub.conf.j2' + + def __init__(self, + variant = 'full', + dest_dir = '/boot/iso', # Should be subdir of boot_dir + dest_file = 'ipxe.iso', + ver_file = '.ipxe.json', + lock_path = '/tmp/.ipxe.lck', + dl_base = 'https://boot.ipxe.org/', + do_grub_cfg = True, + boot_dir = '/boot', # ESP or boot partition mount; where GRUB files are installed *under* + grub_cfg = '/etc/grub.d/40_custom_ipxe', + # check_gpg = True, # TODO: GPG sig checking, http://mirror.rit.edu/grml//gnupg-michael-prokop.txt + # hash_type = 'sha512'): + ): + if variant not in self._allowed_variants: + raise ValueError('variant must be one of: {0}'.format(', '.join(self._allowed_variants))) + else: + self.variant = variant.lower() + if self.variant == 'efi': + dest_file = dest_file.replace('.iso', '.efi') + super().__init__(dest_dir, + dest_file, + ver_file, + lock_path, + do_grub_cfg, + boot_dir, + grub_cfg, + hash_type = 'sha512') + self.dl_base = dl_base + self._init_vars() + + def _init_vars(self): + if self.getRunning(): + return(None) + self.getCurVer() + self.getNewVer() + return(None) + + def getCurVer(self): + if self.getRunning(): + return(None) + if not os.path.isfile(self.dest_ver): + self.do_update = True + self.force_update = True + return(None) + with open(self.dest_ver, 'rb') as fh: + ver_info = json.load(fh) + self.old_date = datetime.datetime.strptime(ver_info['date'], self._date_fmt) + self.old_hash = ver_info.get(self.hash_type) + self.variant = ver_info.get('variant', self.variant) + self.new_hash = self.old_hash + self.new_date = self.old_date + if ver_info.get('arch') != self.arch: + self.do_update = True + self.force_update = True + return(None) + if not os.path.isfile(self.dest_iso): + self.do_update = True + self.force_update = True + return(None) + realhash = self.getISOHash() + if self.old_hash != realhash: + self.do_update = True + self.force_update = True + return(None) + return(None) + + def getNewVer(self): + if self.getRunning(): + return(None) + req = requests.get(self.dl_base, headers = {'User-Agent': 'curl/7.74.0'}) + if not req.ok: + raise RuntimeError('Received non-200/30x {0} for {1}'.format(req.status_code, self.dl_base)) + html = BeautifulSoup(req.content.decode('utf-8'), ('lxml' if _has_lxml else 'html.parser')) + # This is a little hacky. + filelist = html.find('table') + # Get the header, and the index for the proper columns. + file_col = 0 + date_col = 0 + file_len = 0 + file_html = None + header = filelist.find('tr') + # Icon, Name, Modified, Size, Description + file_len = len(header.find_all('th')) + if header is None: + raise RuntimeError('Could not find header row') + for idx, cell in enumerate(header.find_all('th')): + link = cell.find('a') + if link is None: + continue + # At least the header columns have predictable links (for sorting). + if link['href'] == '?C=N;O=D': # Name + file_col = idx + continue + if link['href'] == '?C=M;O=A': # Last Modified + date_col = idx + for idx, row in enumerate(filelist.find('tr')): + if idx == 0: # Header; skip. + continue + cells = row.find_all('td') + if len(cells) != file_len: + continue + name_html = cells[file_col] + date_html = cells[date_col] + + for link in filelist.find_all(): + fname_r = self._fname_re.search(link['href']) + if not fname_r: + continue + ver_info = fname_r.groupdict() + if ver_info['variant'] != self.variant: + continue + new_date = float(ver_info.get('version', self.old_ver)) + iso_url = os.path.join(self.dl_base, link['href'].replace(self.dl_base, '')) + hash_url = '{0}.{1}'.format(iso_url, self.hash_type) + newver_info = (hash_url, iso_url) + versions[new_ver] = newver_info + self.new_ver = sorted(list(versions.keys()))[-1] + if not all((self.old_ver, self.old_date)) or \ + (self.new_ver > self.old_ver): + self.do_update = True + self.new_date = datetime.datetime.now(datetime.timezone.utc) + hash_url, self.iso_url = versions[self.new_ver] + req = requests.get(hash_url, headers = {'User-Agent': 'curl/7.74.0'}) + if not req.ok: + raise RuntimeError('Received non-200/30x {0} for {1}'.format(req.status_code, hash_url)) + self.new_hash = req.content.decode('utf-8').lower().split()[0] + return(None) + + def updateVer(self): + if self.getRunning(): + return(None) + d = { + 'date': self.new_date.strftime(self._date_fmt), + 'variant': self.variant, + self.hash_type: self.new_hash} + j = json.dumps(d, indent = 4) + with open(self.dest_ver, 'w') as fh: + fh.write(j) + fh.write('\n') + os.chmod(self.dest_ver, 0o0644) + return(None) + + +if __name__ == '__main__': + u = Updater() + u.main() diff --git a/sysresccd.py b/sysresccd.py index 8002430..fa1c5f9 100755 --- a/sysresccd.py +++ b/sysresccd.py @@ -139,6 +139,7 @@ class Updater(_base.BaseUpdater): with open(self.dest_ver, 'w') as fh: fh.write(j) fh.write('\n') + os.chmod(self.dest_ver, 0o0644) return(None) diff --git a/tpl/arch_grub.conf.j2 b/tpl/arch_grub.conf.j2 index 79947bf..472f358 100644 --- a/tpl/arch_grub.conf.j2 +++ b/tpl/arch_grub.conf.j2 @@ -6,19 +6,20 @@ exec tail -n +3 $0 # Details: # https://wiki.archlinux.org/index.php/Multiboot_USB_drive#Arch_Linux_monthly_release # https://git.archlinux.org/archiso.git/tree/docs/README.bootparams -submenu 'Arch Install ISO' { +submenu 'Arch Install ISO >' { + + load_video + insmod gzio + insmod part_gpt + insmod part_msdos + insmod ext2 + insmod loopback + search --no-floppy --fs-uuid {{ disk_uuid }} --set=root + set isofile='{{ iso_path }}' + set imgdevpath="/dev/disk/by-uuid/{{ disk_uuid }}" + loopback loop (${root})/${isofile} menuentry 'Default Options' { - load_video - insmod gzio - insmod part_gpt - insmod part_msdos - insmod ext2 - insmod loopback - search --no-floppy --fs-uuid {{ disk_uuid }} --set=root - set isofile='{{ iso_path }}' - set imgdevpath="/dev/disk/by-uuid/{{ disk_uuid }}" - loopback loop (${root})/${isofile} linux (loop)/arch/boot/x86_64/vmlinuz-linux \ archisobasedir=arch \ img_dev=$imgdevpath \ @@ -30,16 +31,6 @@ submenu 'Arch Install ISO' { } menuentry 'Accessibility mode' { - load_video - insmod gzio - insmod part_gpt - insmod part_msdos - insmod ext2 - insmod loopback - search --no-floppy --fs-uuid {{ disk_uuid }} --set=root - set isofile='{{ iso_path }}' - set imgdevpath="/dev/disk/by-uuid/{{ disk_uuid }}" - loopback loop (${root})/${isofile} linux (loop)/arch/boot/x86_64/vmlinuz-linux \ archisobasedir=arch \ img_dev=$imgdevpath \ diff --git a/tpl/grml_grub.conf.j2 b/tpl/grml_grub.conf.j2 index c0eb994..df34fd7 100644 --- a/tpl/grml_grub.conf.j2 +++ b/tpl/grml_grub.conf.j2 @@ -1,5 +1,4 @@ #!/bin/sh -# TODO: other entries # Copy this file to /etc/grub.d/40_custom_grml with mode 0755 and run grub-mkconfig -o /boot/grub/grub.cfg exec tail -n +3 $0 # GRML @@ -7,9 +6,8 @@ exec tail -n +3 $0 # Details: # https://grml.org/docs/ # http://grml.org/cheatcodes/ -submenu 'GRML' { +submenu 'GRML >' { - # Does this work? load_video insmod gzio insmod part_gpt @@ -19,187 +17,226 @@ submenu 'GRML' { set gfxpayload=keep search --no-floppy --fs-uuid {{ disk_uuid }} --set=root set isofile='{{ iso_path }}' - set variant={{ variant }} - set ver={{ ver_str }} - set arch={{ arch }} - set bootid=grml${arch}${variant}${ver} - set imgdevpath="/dev/disk/by-uuid/{{ disk_uuid }}" + loopback loop (${root})/${isofile} + + submenu 'GRML Rescue >' { + + set variant={{ variant }} + set ver={{ ver_str }} + set arch={{ arch }} + set bootid=grml${arch}${variant}${ver} + set imgdevpath="/dev/disk/by-uuid/{{ disk_uuid }}" + + menuentry 'Default options' { + linux (loop)/boot/grml${arch}${variant}/vmlinuz \ + apm=power-off \ + boot=live \ + live-media-path=/live/grml${arch}-${variant}/ \ + bootid=${bootid} \ + findiso=${isofile} \ + nomce \ + net.ifnames=0 + initrd (loop)/boot/grml${arch}${variant}/initrd.img + } + + menuentry 'Predictable network interface names' { + linux (loop)/boot/grml${arch}${variant}/vmlinuz \ + apm=power-off \ + boot=live \ + live-media-path=/live/grml${arch}-${variant}/ \ + bootid=${bootid} \ + findiso=${isofile} \ + nomce + initrd (loop)/boot/grml${arch}${variant}/initrd.img + } + + menuentry 'Enable persistency' { + linux (loop)/boot/grml${arch}${variant}/vmlinuz \ + apm=power-off \ + boot=live \ + live-media-path=/live/grml${arch}-${variant}/ \ + bootid=${bootid} \ + findiso=${isofile} \ + nomce \ + net.ifnames=0 \ + persistence + initrd (loop)/boot/grml${arch}${variant}/initrd.img + } + + menuentry 'Run from RAM' { + linux (loop)/boot/grml${arch}${variant}/vmlinuz \ + apm=power-off \ + boot=live \ + live-media-path=/live/grml${arch}-${variant}/ \ + bootid=${bootid} \ + findiso=${isofile} \ + nomce \ + net.ifnames=0 \ + toram=grml64-full.squashfs + initrd (loop)/boot/grml${arch}${variant}/initrd.img + } + + menuentry 'Copy entire ISO to RAM' { + linux (loop)/boot/grml${arch}${variant}/vmlinuz \ + apm=power-off \ + boot=live \ + live-media-path=/live/grml${arch}-${variant}/ \ + bootid=${bootid} \ + findiso=${isofile} \ + nomce \ + net.ifnames=0 \ + toram + initrd (loop)/boot/grml${arch}${variant}/initrd.img + } + + menuentry 'Start X' { + linux (loop)/boot/grml${arch}${variant}/vmlinuz \ + apm=power-off \ + boot=live \ + live-media-path=/live/grml${arch}-${variant}/ \ + bootid=${bootid} \ + findiso=${isofile} \ + nomce \ + net.ifnames=0 \ + startx + initrd (loop)/boot/grml${arch}${variant}/initrd.img + } + + menuentry 'No framebuffer' { + linux (loop)/boot/grml${arch}${variant}/vmlinuz \ + apm=power-off \ + boot=live \ + live-media-path=/live/grml${arch}-${variant}/ \ + bootid=${bootid} \ + findiso=${isofile} \ + nomce \ + net.ifnames=0 \ + video=ofonly \ + radeon.modeset=0 \ + i915.modeset=0 \ + nouveau.modeset=0 \ + cirrus.modeset=0 \ + mgag200.modeset=0 \ + nomodeset + initrd (loop)/boot/grml${arch}${variant}/initrd.img + } + + menuentry 'No kernel modeset' { + linux (loop)/boot/grml${arch}${variant}/vmlinuz \ + apm=power-off \ + boot=live \ + live-media-path=/live/grml${arch}-${variant}/ \ + bootid=${bootid} \ + findiso=${isofile} \ + nomce \ + net.ifnames=0 \ + radeon.modeset=0 \ + i915.modeset=0 \ + nouveau.modeset=0 \ + cirrus.modeset=0 \ + mgag200.modeset=0 \ + nomodeset + initrd (loop)/boot/grml${arch}${variant}/initrd.img + } + + menuentry 'Forensic mode' { + linux (loop)/boot/grml${arch}${variant}/vmlinuz \ + apm=power-off \ + boot=live \ + live-media-path=/live/grml${arch}-${variant}/ \ + bootid=${bootid} \ + findiso=${isofile} \ + nomce \ + net.ifnames=0 \ + read-only \ + nofstab \ + noraid \ + nodmraid \ + nolvm \ + noautoconfig \ + noswap \ + raid=noautodetect + initrd (loop)/boot/grml${arch}${variant}/initrd.img + } + + menuentry 'Debug mode' { + linux (loop)/boot/grml${arch}${variant}/vmlinuz \ + apm=power-off \ + boot=live \ + live-media-path=/live/grml${arch}-${variant}/ \ + bootid=${bootid} \ + findiso=${isofile} \ + nomce \ + net.ifnames=0 \ + initcall \ + verbose \ + debug=vc \ + systemd.log_level=debug \ + systemd.log_target=kmsg \ + log_buf_len=1M + initrd (loop)/boot/grml${arch}${variant}/initrd.img + } + + menuentry 'Serial mode' { + linux (loop)/boot/grml${arch}${variant}/vmlinuz \ + apm=power-off \ + boot=live \ + live-media-path=/live/grml${arch}-${variant}/ \ + bootid=${bootid} \ + findiso=${isofile} \ + nomce \ + net.ifnames=0 \ + video=vesafb:off \ + console=tty1 \ + console=ttyS0,9600n8 + initrd (loop)/boot/grml${arch}${variant}/initrd.img + } - menuentry 'Default options' { - loopback loop (${root})/${isofile} - linux (loop)/boot/grml${arch}${variant}/vmlinuz \ - apm=power-off \ - boot=live \ - live-media-path=/live/grml${arch}-${variant}/ \ - bootid=${bootid} \ - findiso=${isofile} \ - nomce \ - net.ifnames=0 - initrd (loop)/boot/grml${arch}${variant}/initrd.img } - menuentry 'Predictable network interface names' { - loopback loop (${root})/${isofile} - linux (loop)/boot/grml${arch}${variant}/vmlinuz \ - apm=power-off \ - boot=live \ - live-media-path=/live/grml${arch}-${variant}/ \ - bootid=${bootid} \ - findiso=${isofile} \ - nomce - initrd (loop)/boot/grml${arch}${variant}/initrd.img - } + submenu 'GRML Addons >' { - menuentry 'Enable persistency' { - loopback loop (${root})/${isofile} - linux (loop)/boot/grml${arch}${variant}/vmlinuz \ - apm=power-off \ - boot=live \ - live-media-path=/live/grml${arch}-${variant}/ \ - bootid=${bootid} \ - findiso=${isofile} \ - nomce \ - net.ifnames=0 \ - persistence - initrd (loop)/boot/grml${arch}${variant}/initrd.img - } + insmod linux16 - menuentry 'Run from RAM' { - loopback loop (${root})/${isofile} - linux (loop)/boot/grml${arch}${variant}/vmlinuz \ - apm=power-off \ - boot=live \ - live-media-path=/live/grml${arch}-${variant}/ \ - bootid=${bootid} \ - findiso=${isofile} \ - nomce \ - net.ifnames=0 \ - toram=grml64-full.squashfs - initrd (loop)/boot/grml${arch}${variant}/initrd.img - } + menuentry 'Memtest86+' { + linux16 (loop)/boot/addons/memtest + } - menuentry 'Copy entire ISO to RAM' { - loopback loop (${root})/${isofile} - linux (loop)/boot/grml${arch}${variant}/vmlinuz \ - apm=power-off \ - boot=live \ - live-media-path=/live/grml${arch}-${variant}/ \ - bootid=${bootid} \ - findiso=${isofile} \ - nomce \ - net.ifnames=0 \ - toram - initrd (loop)/boot/grml${arch}${variant}/initrd.img - } + menuentry 'iPXE' { + linux16 (loop)/boot/addons/ipxe.lkrn + } - menuentry 'Start X' { - loopback loop (${root})/${isofile} - linux (loop)/boot/grml${arch}${variant}/vmlinuz \ - apm=power-off \ - boot=live \ - live-media-path=/live/grml${arch}-${variant}/ \ - bootid=${bootid} \ - findiso=${isofile} \ - nomce \ - net.ifnames=0 \ - startx - initrd (loop)/boot/grml${arch}${variant}/initrd.img - } + menuentry 'Netboot.XYZ' { + linux16 (loop)/boot/addons/netboot.xyz.lkrn + } - menuentry 'No framebuffer' { - loopback loop (${root})/${isofile} - linux (loop)/boot/grml${arch}${variant}/vmlinuz \ - apm=power-off \ - boot=live \ - live-media-path=/live/grml${arch}-${variant}/ \ - bootid=${bootid} \ - findiso=${isofile} \ - nomce \ - net.ifnames=0 \ - video=ofonly \ - radeon.modeset=0 \ - i915.modeset=0 \ - nouveau.modeset=0 \ - cirrus.modeset=0 \ - mgag200.modeset=0 \ - nomodeset - initrd (loop)/boot/grml${arch}${variant}/initrd.img - } + menuentry 'Grub All-In-One' { + linux16 (loop)/boot/addons/allinone.img + } - menuentry 'No kernel modeset' { - loopback loop (${root})/${isofile} - linux (loop)/boot/grml${arch}${variant}/vmlinuz \ - apm=power-off \ - boot=live \ - live-media-path=/live/grml${arch}-${variant}/ \ - bootid=${bootid} \ - findiso=${isofile} \ - nomce \ - net.ifnames=0 \ - radeon.modeset=0 \ - i915.modeset=0 \ - nouveau.modeset=0 \ - cirrus.modeset=0 \ - mgag200.modeset=0 \ - nomodeset - initrd (loop)/boot/grml${arch}${variant}/initrd.img - } + menuentry 'FreeDOS' { + linux16 (loop)/boot/addons/memdisk + loopback balder (loop)/boot/addons/balder10.imz + initrd (balder)+2880 + } - menuentry 'Forensic mode' { - loopback loop (${root})/${isofile} - linux (loop)/boot/grml${arch}${variant}/vmlinuz \ - apm=power-off \ - boot=live \ - live-media-path=/live/grml${arch}-${variant}/ \ - bootid=${bootid} \ - findiso=${isofile} \ - nomce \ - net.ifnames=0 \ - read-only \ - nofstab \ - noraid \ - nodmraid \ - nolvm \ - noautoconfig \ - noswap \ - raid=noautodetect - initrd (loop)/boot/grml${arch}${variant}/initrd.img - } + menuentry 'MirOS bsd4grml' { + multiboot (loop)/boot/addons/bsd4grml/ldbsd.com + module (loop)/boot/addons/bsd4grml/bsd.rd bsd.rd + module (loop)/boot/addons/bsd4grml/boot.1 boot.1 + module (loop)/boot/addons/bsd4grml/boot.2 boot.2 + module (loop)/boot/addons/bsd4grml/boot.3 boot.3 + module (loop)/boot/addons/bsd4grml/boot.4 boot.4 + module (loop)/boot/addons/bsd4grml/boot.5 boot.5 + module (loop)/boot/addons/bsd4grml/boot.6 boot.6 + module (loop)/boot/addons/bsd4grml/boot.cfg boot.cfg + module (loop)/boot/grub/grub.img grub.img + } - menuentry 'Debug mode' { - loopback loop (${root})/${isofile} - linux (loop)/boot/grml${arch}${variant}/vmlinuz \ - apm=power-off \ - boot=live \ - live-media-path=/live/grml${arch}-${variant}/ \ - bootid=${bootid} \ - findiso=${isofile} \ - nomce \ - net.ifnames=0 \ - initcall \ - verbose \ - debug=vc \ - systemd.log_level=debug \ - systemd.log_target=kmsg \ - log_buf_len=1M - initrd (loop)/boot/grml${arch}${variant}/initrd.img - } + # We don't include the "Boot from first disk" option because presumably you have that in the main menu. - menuentry 'Serial mode' { - loopback loop (${root})/${isofile} - linux (loop)/boot/grml${arch}${variant}/vmlinuz \ - apm=power-off \ - boot=live \ - live-media-path=/live/grml${arch}-${variant}/ \ - bootid=${bootid} \ - findiso=${isofile} \ - nomce \ - net.ifnames=0 \ - video=vesafb:off \ - console=tty1 \ - console=ttyS0,9600n8 - initrd (loop)/boot/grml${arch}${variant}/initrd.img } } + diff --git a/tpl/ipxe_grub.conf.j2 b/tpl/ipxe_grub.conf.j2 new file mode 100644 index 0000000..1b85b63 --- /dev/null +++ b/tpl/ipxe_grub.conf.j2 @@ -0,0 +1,25 @@ +#!/bin/sh +# Copy this file to /etc/grub.d/40_custom_ipxe with mode 0755 and run grub-mkconfig -o /boot/grub/grub.cfg +exec tail -n +3 $0 +# iPXE +# Project: https://ipxe.org/ +# Details: https://ipxe.org/docs +menuentry 'iPXE' { + + insmod linux16 + insmod loopback + search --no-floppy --fs-uuid {{ disk_uuid }} --set=root +{%- if variant == 'iso' %} + set isofile='{{ iso_path }}' + loopback loop (${root})/${isofile} + + linux16 (loop)/ipxe.lkrn +{%- else %} + insmod fat + insmod chain + terminal_output console + + chainloader (${root})/{{ iso_path }} +{%- fi %} + +} diff --git a/tpl/sysresccd_grub.conf.j2 b/tpl/sysresccd_grub.conf.j2 index 907afd8..eb62f41 100644 --- a/tpl/sysresccd_grub.conf.j2 +++ b/tpl/sysresccd_grub.conf.j2 @@ -6,19 +6,20 @@ exec tail -n +3 $0 # Details: # https://www.system-rescue.org/manual/Installing_SystemRescue_on_the_disk/#first-approach-using-grub2-with-isoloop # https://www.system-rescue.org/manual/Booting_SystemRescueCd/ -submenu 'System Rescue CD' { +submenu 'System Rescue CD >' { + + load_video + insmod gzio + insmod part_gpt + insmod part_msdos + insmod ext2 + insmod loopback + search --no-floppy --fs-uuid {{ disk_uuid }} --set=root + set isofile='{{ iso_path }}' + set imgdevpath="/dev/disk/by-uuid/{{ disk_uuid }}" + loopback loop (${root})/${isofile} menuentry 'Default options' { - load_video - insmod gzio - insmod part_gpt - insmod part_msdos - insmod ext2 - insmod loopback - search --no-floppy --fs-uuid {{ disk_uuid }} --set=root - set isofile='{{ iso_path }}' - set imgdevpath="/dev/disk/by-uuid/{{ disk_uuid }}" - loopback loop (${root})/${isofile} linux (loop)/sysresccd/boot/x86_64/vmlinuz \ archisobasedir=sysresccd \ img_dev=${imgdevpath} \ @@ -30,16 +31,6 @@ submenu 'System Rescue CD' { } menuentry 'Run from RAM' { - load_video - insmod gzio - insmod part_gpt - insmod part_msdos - insmod ext2 - insmod loopback - search --no-floppy --fs-uuid {{ disk_uuid }} --set=root - set isofile='{{ iso_path }}' - set imgdevpath="/dev/disk/by-uuid/{{ disk_uuid }}" - loopback loop (${root})/${isofile} linux (loop)/sysresccd/boot/x86_64/vmlinuz \ archisobasedir=sysresccd \ img_dev=${imgdevpath} \ @@ -52,16 +43,6 @@ submenu 'System Rescue CD' { } menuentry 'Confirm/verify checksum' { - load_video - insmod gzio - insmod part_gpt - insmod part_msdos - insmod ext2 - insmod loopback - search --no-floppy --fs-uuid {{ disk_uuid }} --set=root - set isofile='{{ iso_path }}' - set imgdevpath="/dev/disk/by-uuid/{{ disk_uuid }}" - loopback loop (${root})/${isofile} linux (loop)/sysresccd/boot/x86_64/vmlinuz \ archisobasedir=sysresccd \ img_dev=${imgdevpath} \ @@ -74,16 +55,6 @@ submenu 'System Rescue CD' { } menuentry 'Use basic display drivers' { - load_video - insmod gzio - insmod part_gpt - insmod part_msdos - insmod ext2 - insmod loopback - search --no-floppy --fs-uuid {{ disk_uuid }} --set=root - set isofile='{{ iso_path }}' - set imgdevpath="/dev/disk/by-uuid/{{ disk_uuid }}" - loopback loop (${root})/${isofile} linux (loop)/sysresccd/boot/x86_64/vmlinuz \ archisobasedir=sysresccd \ img_dev=${imgdevpath} \ @@ -96,16 +67,6 @@ submenu 'System Rescue CD' { } menuentry 'Find and boot a locally installed Linux' { - load_video - insmod gzio - insmod part_gpt - insmod part_msdos - insmod ext2 - insmod loopback - search --no-floppy --fs-uuid {{ disk_uuid }} --set=root - set isofile='{{ iso_path }}' - set imgdevpath="/dev/disk/by-uuid/{{ disk_uuid }}" - loopback loop (${root})/${isofile} linux (loop)/sysresccd/boot/x86_64/vmlinuz \ archisobasedir=sysresccd \ img_dev=${imgdevpath} \ @@ -118,16 +79,6 @@ submenu 'System Rescue CD' { } menuentry 'Stop during boot before the root filesystem is mounted' { - load_video - insmod gzio - insmod part_gpt - insmod part_msdos - insmod ext2 - insmod loopback - search --no-floppy --fs-uuid {{ disk_uuid }} --set=root - set isofile='{{ iso_path }}' - set imgdevpath="/dev/disk/by-uuid/{{ disk_uuid }}" - loopback loop (${root})/${isofile} linux (loop)/sysresccd/boot/x86_64/vmlinuz \ archisobasedir=sysresccd \ img_dev=${imgdevpath} \ @@ -139,5 +90,24 @@ submenu 'System Rescue CD' { (loop)/sysresccd/boot/x86_64/sysresccd.img } + menuentry 'EFI shell' { + insmod fat + insmod chain + terminal_output console + chainloader (loop)/EFI/shell.efi + } + + menuentry 'EFI firmware setup' { + fwsetup + } + + menuentry 'Reboot' { + reboot + } + + menuentry 'Power off' { + halt + } + }