Skip to content

Instantly share code, notes, and snippets.

@doraeric
Last active May 19, 2025 16:47
Show Gist options
  • Save doraeric/919045bc2af9b669a5f768cb8b3c192d to your computer and use it in GitHub Desktop.
Save doraeric/919045bc2af9b669a5f768cb8b3c192d to your computer and use it in GitHub Desktop.
debug=acpi,affs,ahci,appleload,arcdisk,archelp,ata,atkeyb,badram,bsd,btrfs,cache,cbfs,chain,cros,cros_keyboard,crypt,cryptodisk,datetime,devalias,disk,diskfilter,dl,dns,drivemap,efi,efidisk,efiemu,ehci,elf,exfat,expand,fat,fdt,fdtbus,fixvideo,font,fs,geli,gpt,hostdisk,http,ieee1275,init,jpeg,keystatus,linux,loader,luks,luks2,memdisk,mmap,modules,multiboot_loader,nativedisk,net,ohci,partition,pata,plainmount,play,pmtimer,png,regions,reiserfs,reiserfs_blocktype,reiserfs_tree,relocator,scsi,sections,serial,smbios,syslinux,tftp,tga,tpm,ubootdisk,uhci,usb,usb_keyboard,usbms,verify,video,xen,xen_loader,xfs,xnu,zfs
#!/usr/bin/env python3
import argparse
import re
import subprocess
import tempfile
from pathlib import Path
from queue import Queue
not_all_video_mods = [
"efi_gop",
"efi_uga",
"ieee1275_fb",
"vbe",
"vga",
"video_bochs",
"video_cirrus",
]
def get_deps(mod: str) -> dict[str, list[str]]:
deps = {}
q = Queue()
q.put(mod)
while not q.empty():
mod = q.get()
deps[mod] = []
with tempfile.TemporaryDirectory() as tmpdir:
sections = subprocess.check_output(
["objdump", "-h", f"/boot/grub/x86_64-efi/{mod}.mod"]
).splitlines()[5:]
sections = b"\n".join(sections)
if b".moddeps" not in sections:
continue
subprocess.run(
[
"objcopy",
"--dump-section",
f".moddeps={tmpdir}/out",
f"/boot/grub/x86_64-efi/{mod}.mod",
"/dev/null",
]
)
with Path(tmpdir, "out").open() as f:
lines = f.read().split("\0")
lines = [line for line in lines if line]
deps[mod] = lines
for dep in deps[mod]:
if dep not in deps:
q.put(dep)
return deps
insmod_pattern = r"insmod\s+([\w]+)"
def read_grub_cfg(path: str):
mod_counter = {}
with Path(path).open() as f:
for line in f:
line = line.strip()
if "insmod" in line:
match = re.search(insmod_pattern, line)
mod = match.group(1)
mod_counter[mod] = mod_counter.get(mod, 0) + 1
for neg_mod in not_all_video_mods:
if neg_mod in mod_counter:
mod_counter[neg_mod] -= 1
if mod_counter[neg_mod] == 0:
del mod_counter[neg_mod]
return list(mod_counter.keys())
def main():
parser = argparse.ArgumentParser()
parser.add_argument("-i", "--input", required=True, help="grub.cfg file")
args = parser.parse_args()
mods = read_grub_cfg(args.input)
flatten = []
for mod in mods:
deps = get_deps(mod)
for key, values in deps.items():
if key not in flatten:
flatten.append(key)
for value in values:
if value not in flatten:
flatten.append(value)
flatten.sort()
print(" ".join(flatten))
if __name__ == "__main__":
main()
@doraeric
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment