import os import sys import shutil import subprocess import uuid from engine.InventoryLib import * from engine.SystemLib import * from engine.UEFILib import * def ogBoot(): FUNCNAME = ogBoot.__name__ # Variables locales. PART = None TYPE = None MNTDIR = None PARAMS = None KERNEL = None INITRD = None APPEND = None FILE = None LOADER = None f = None NVRAMPERM = None EFIDISK = None EFIPART = None EFIDIR = None BOOTLABEL = None BOOTLOADER = None BOOTNO = None DIRGRUB = None b = None # Si se solicita, mostrar ayuda. if len(sys.argv) > 1 and sys.argv[1] == "help": ogHelp(FUNCNAME, FUNCNAME + " int_ndisk int_nfilesys [ NVRAMPERM ] [str_kernel str_initrd str_kernelparams]", FUNCNAME + " 1 1", FUNCNAME + " 1 2 \"/boot/vmlinuz /boot/initrd.img root=/dev/sda2 ro\"", FUNCNAME + " 1 1", FUNCNAME + " 1 2 NVRAMPERM") return # Error si no se reciben 2 o 3 parámetros. if len(sys.argv) != 3 and len(sys.argv) != 4 and len(sys.argv) != 5: ogRaiseError(OG_ERR_FORMAT) return # Detectar tipo de sistema de archivos y montarlo. PART = ogDiskToDev(int(sys.argv[1]), int(sys.argv[2])) if PART is None: return TYPE = ogGetOsType(int(sys.argv[1]), int(sys.argv[2])) if TYPE is None: return # Error si no puede montar sistema de archivos. MNTDIR = ogMount(int(sys.argv[1]), int(sys.argv[2])) if MNTDIR is None: return if len(sys.argv) == 5 and sys.argv[4].upper() == "NVRAMPERM": NVRAMPERM = True else: NVRAMPERM = False PARAMS = sys.argv[4] if len(sys.argv) == 5 else sys.argv[3] if TYPE in ["Linux", "Android"]: # Si no se indican, obtiene los parámetros de arranque para Linux. PARAMS = PARAMS or ogLinuxBootParameters(int(sys.argv[1]), int(sys.argv[2])) # Si no existe y el UEFI buscar en particion ESP if not PARAMS and ogIsEfiActive(): PARAMS = ogLinuxBootParameters(ogGetEsp()) # Si no existe, buscar sistema de archivo /boot en /etc/fstab. if not PARAMS and os.path.exists(os.path.join(MNTDIR, "etc/fstab")): # Localizar S.F. /boot en /etc/fstab del S.F. actual. PART = ogDevToDisk(subprocess.check_output(["awk", '$1!="#" && $2=="/boot" {print $1}', os.path.join(MNTDIR, "etc/fstab")]).decode().strip()) # Montar S.F. de /boot. MNTDIR = ogMount(PART) if MNTDIR is None: return # Buscar los datos de arranque. PARAMS = ogLinuxBootParameters(PART) if PARAMS is None: return KERNEL, INITRD, APPEND = PARAMS.split() if PARAMS else (None, None, None) # Si no hay kernel, no hay sistema operativo. if not KERNEL or not os.path.exists(os.path.join(MNTDIR, KERNEL)): ogRaiseError(OG_ERR_NOTOS, sys.argv[1], sys.argv[2], TYPE) return # Arrancar de partición distinta a la original. if os.path.exists(os.path.join(MNTDIR, "etc")): APPEND = APPEND.replace("root=[-+=_/a-zA-Z0-9]* ", "root={} ".format(PART)) # Comprobar tipo de sistema. if ogIsEfiActive(): # Comprobar si el Kernel está firmado. if not subprocess.check_output(["file", "-k", os.path.join(MNTDIR, KERNEL)]).decode().strip().startswith("EFI app"): ogRaiseError(OG_ERR_NOTOS, sys.argv[1], sys.argv[2], TYPE, "EFI") return BOOTLABEL = "Part-{:02d}-{:02d}".format(int(sys.argv[1]), int(sys.argv[2])) BOOTLOADER = "shimx64.efi" # Obtener parcición EFI. EFIDISK, EFIPART = ogGetEsp() # TODO: Comprobamos que existe la BOOTLABEL, si no buscamos por sistema operativo if not ogGetPath(EFIDISK, EFIPART, "EFI/{}".format(BOOTLABEL)): OSVERSION = ogGetOsVersion(int(sys.argv[1]), int(sys.argv[2])) if OSVERSION: if "SUSE" in OSVERSION: BOOTLABEL = "opensuse" elif "Fedora" in OSVERSION: BOOTLABEL = "fedora" elif "Ubuntu" in OSVERSION: BOOTLABEL = "ubuntu" else: ogRaiseError(OG_ERR_NOTFOUND, EFIDISK, EFIPART, "Boot loader") return # Crear orden de arranque (con unos valores por defecto). ogNvramAddEntry(BOOTLABEL, "/EFI/{}/Boot/{}".format(BOOTLABEL, BOOTLOADER), NVRAMPERM) # Marcar próximo arranque y reiniciar. ogNvramSetNext(BOOTLABEL) reboot() else: # Arranque BIOS: configurar kernel Linux con los parámetros leídos de su GRUB. subprocess.call(["kexec", "-l", os.path.join(MNTDIR, KERNEL), "--append={}".format(APPEND), "--initrd={}".format(os.path.join(MNTDIR, INITRD))]) subprocess.call(["kexec", "-e"]) elif TYPE == "Windows": # Comprobar tipo de sistema. if ogIsEfiActive(): BOOTLABEL = "Part-{:02d}-{:02d}".format(int(sys.argv[1]), int(sys.argv[2])) # Obtener parcición EFI. EFIDISK, EFIPART = ogGetEsp() if not EFIPART: ogRaiseError(OG_ERR_PARTITION, "ESP") return EFIDIR = ogMount(EFIDISK, EFIPART) if EFIDIR is None: return # Comprobar cargador (si no existe buscar por defecto en ESP). LOADER = ogGetPath(os.path.join(EFIDIR, "EFI", BOOTLABEL, "Boot/bootmgfw.efi")) if not LOADER: BOOTLABEL = "Microsoft" LOADER = ogGetPath(os.path.join(EFIDIR, "EFI", "Microsoft/Boot/bootmgfw.efi")) if not LOADER: ogRaiseError(OG_ERR_NOTOS, sys.argv[1], sys.argv[2], TYPE, "EFI") return # Crear orden de arranque (con unos valores por defecto). ogNvramAddEntry(BOOTLABEL, "/EFI{}".format(LOADER[LOADER.find("EFI"):]), NVRAMPERM) # Marcar próximo arranque y reiniciar. ogNvramSetNext(BOOTLABEL) reboot() else: # Arranque BIOS: comprueba si hay un cargador de Windows. for f in ["io.sys", "ntldr", "bootmgr"]: FILE = ogGetPath(int(sys.argv[1]), int(sys.argv[2]), f) if FILE: LOADER = f if not LOADER: ogRaiseError(OG_ERR_NOTOS, sys.argv[1], sys.argv[2], TYPE) return if winboot == "kexec": # Modo de arranque en caliente (con kexec). shutil.copy(os.path.join(OGLIB, "grub4dos/*"), MNTDIR) # */ (Comentario Doxygen) subprocess.call(["kexec", "-l", os.path.join(MNTDIR, "grub.exe"), "--append=--config-file=\"root (hd{}),{}); chainloader (hd{}),{}/{}; tpm --init\"".format(int(sys.argv[1])-1, int(sys.argv[2])-1, int(sys.argv[1])-1, int(sys.argv[2])-1, LOADER)]) subprocess.call(["kexec", "-e"]) else: # Modo de arranque por reinicio (con reboot). with open(os.path.join(MNTDIR, "ogboot.me"), "wb") as f: f.write(b"\x00" * 1024 * 3) with open(os.path.join(MNTDIR, "ogboot.firstboot"), "wb") as f: f.write(b"\x00" * 1024 * 3) with open(os.path.join(MNTDIR, "ogboot.secondboot"), "wb") as f: f.write(b"\x00" * 1024 * 3) if not ogGetRegistryValue(MNTDIR, "SOFTWARE", "\\Microsoft\\Windows\\CurrentVersion\\Run\\ogcleannboot"): ogAddRegistryValue(MNTDIR, "SOFTWARE", "\\Microsoft\\Windows\\CurrentVersion\\Run\\ogcleanboot") ogSetRegistryValue(MNTDIR, "SOFTWARE", "\\Microsoft\\Windows\\CurrentVersion\\Run\\ogcleanboot", "cmd /c del c:\\ogboot.*") # Activar la partición. ogSetPartitionActive(int(sys.argv[1]), int(sys.argv[2])) reboot() elif TYPE == "MacOS": # Modo de arranque por reinicio. # Nota: el cliente tiene que tener configurado correctamente Grub. open(os.path.join(MNTDIR, "boot.mac"), "w").close() reboot() elif TYPE == "GrubLoader": # Reiniciar. #reboot() pass else: ogRaiseError(OG_ERR_NOTOS, sys.argv[1], sys.argv[2], TYPE) return def ogGetWindowsName(): FUNCNAME = ogGetWindowsName.__name__ # Variables locales. MNTDIR = None # Si se solicita, mostrar ayuda. if len(sys.argv) > 1 and sys.argv[1] == "help": ogHelp(FUNCNAME, FUNCNAME + " int_ndisk int_npartition", FUNCNAME + " 1 1 ==> PRACTICA-PC") return # Error si no se reciben 2 parámetros. if len(sys.argv) != 3: ogRaiseError(OG_ERR_FORMAT) return # Montar el sistema de archivos. MNTDIR = ogMount(int(sys.argv[1]), int(sys.argv[2])) if MNTDIR is None: return # Obtener dato del valor de registro. ogGetRegistryValue(MNTDIR, "system", "\\ControlSet001\\Control\\ComputerName\\ComputerName\\ComputerName") def ogLinuxBootParameters(ndisk, nfilesys): FUNCNAME = ogLinuxBootParameters.__name__ # Variables locales. MNTDIR = None CONFDIR = None CONFFILE = None f = None # Si se solicita, mostrar ayuda. if len(sys.argv) > 1 and sys.argv[1] == "help": ogHelp(FUNCNAME, FUNCNAME + " int_ndisk int_nfilesys", FUNCNAME + " 1 2 ==> /vmlinuz-3.5.0-21-generic /initrd.img-3.5.0-21-generic root=/dev/sda2 ro splash") return # Error si no se reciben 2 parámetros. if len(sys.argv) != 3: ogRaiseError(OG_ERR_FORMAT) return # Detectar id. de tipo de partición y codificar al mnemonico. MNTDIR = ogMount(int(sys.argv[1]), int(sys.argv[2])) if MNTDIR is None: return # Fichero de configuración de GRUB. CONFDIR = MNTDIR # Sistema de archivos de arranque (/boot). if os.path.isdir(os.path.join(MNTDIR, "boot")): CONFDIR = os.path.join(MNTDIR, "boot") # Sist. archivos raíz con directorio boot. for f in [os.path.join(CONFDIR, "grubMBR/boot/menu.lst"), os.path.join(CONFDIR, "grubPARTITION/boot/menu.lst"), os.path.join(CONFDIR, "grub/boot/menu.lst"), os.path.join(CONFDIR, "grub2/boot/grub.cfg"), os.path.join(CONFDIR, "efi/EFI/*/grub.cfg")]: if os.path.isfile(f): CONFFILE = f break if CONFFILE is None: ogRaiseError(OG_ERR_NOTFOUND, "grub.cfg") return # Toma del fichero de configuracion los valores del kernel, initrd # y parámetros de arranque usando las cláusulas por defecto # ("default" en GRUB1, "set default" en GRUB2) # y los formatea para que sean compatibles con \c kexec . awk_script = r''' BEGIN {cont=-1;} $1~/^default$/ {sub(/=/," "); def=$2;} $1~/^set$/ && $2~/^default/ { gsub(/[="]/," "); def=$3; if (def ~ /saved_entry/) def=0; } $1~/^(title|menuentry)$/ {cont++} $1~/^set$/ && $2~/^root=.\(hd'$[1-1]',(msdos|gpt)'$2'\).$/ { if (def==0) def=cont; } $1~/^(kernel|linux(16|efi)?)$/ { if (def==cont) { kern=$2; sub($1,""); sub($1,""); sub(/^[ \t]*/,""); app=$0 } } $1~/^initrd(16|efi)?$/ {if (def==cont) init=$2} END {if (kern!="") printf("%s %s %s", kern,init,app)} ''' awk_command = ["awk", awk_script, CONFFILE] output = subprocess.check_output(awk_command).decode().strip() return output def ogGetLinuxBootParameters(ndisk, nfilesys): FUNCNAME = ogGetLinuxBootParameters.__name__ # Variables locales. MNTDIR = None CONFDIR = None CONFFILE = None f = None # Si se solicita, mostrar ayuda. if len(sys.argv) > 1 and sys.argv[1] == "help": ogHelp(FUNCNAME, FUNCNAME + " int_ndisk int_nfilesys", FUNCNAME + " 1 2 ==> /vmlinuz-3.5.0-21-generic /initrd.img-3.5.0-21-generic root=/dev/sda2 ro splash") return # Error si no se reciben 2 parámetros. if len(sys.argv) != 3: ogRaiseError(OG_ERR_FORMAT) return # Detectar id. de tipo de partición y codificar al mnemonico. MNTDIR = ogMount(int(sys.argv[1]), int(sys.argv[2])) if MNTDIR is None: return # Fichero de configuración de GRUB. CONFDIR = MNTDIR # Sistema de archivos de arranque (/boot). if os.path.isdir(os.path.join(MNTDIR, "boot")): CONFDIR = os.path.join(MNTDIR, "boot") # Sist. archivos raíz con directorio boot. for f in [os.path.join(CONFDIR, "grubMBR/boot/menu.lst"), os.path.join(CONFDIR, "grubPARTITION/boot/menu.lst"), os.path.join(CONFDIR, "grub/boot/menu.lst"), os.path.join(CONFDIR, "grub2/boot/grub.cfg"), os.path.join(CONFDIR, "efi/EFI/*/grub.cfg")]: if os.path.isfile(f): CONFFILE = f break if CONFFILE is None: ogRaiseError(OG_ERR_NOTFOUND, "grub.cfg") return # Toma del fichero de configuracion los valores del kernel, initrd # y parámetros de arranque usando las cláusulas por defecto # ("default" en GRUB1, "set default" en GRUB2) # y los formatea para que sean compatibles con \c kexec . awk_script = r''' BEGIN {cont=-1;} $1~/^default$/ {sub(/=/," "); def=$2;} $1~/^set$/ && $2~/^default/ { gsub(/[="]/," "); def=$3; if (def ~ /saved_entry/) def=0; } $1~/^(title|menuentry)$/ {cont++} $1~/^set$/ && $2~/^root=.\(hd'$[1-1]',(msdos|gpt)'$2'\).$/ { if (def==0) def=cont; } $1~/^(kernel|linux(16|efi)?)$/ { if (def==cont) { kern=$2; sub($1,""); sub($1,""); sub(/^[ \t]*/,""); app=$0 } } $1~/^initrd(16|efi)?$/ {if (def==cont) init=$2} END {if (kern!="") printf("%s %s %s", kern,init,app)} ''' awk_command = ["awk", awk_script, CONFFILE] output = subprocess.check_output(awk_command).decode().strip() return output def ogSetWindowsName(): FUNCNAME = ogSetWindowsName.__name__ # Variables locales. PART = None MNTDIR = None NAME = None # Si se solicita, mostrar ayuda. if len(sys.argv) > 1 and sys.argv[1] == "help": ogHelp(FUNCNAME, FUNCNAME + " int_ndisk int_filesys str_name", FUNCNAME + " 1 1 PRACTICA-PC") return # Error si no se reciben 3 parámetros. if len(sys.argv) != 4: ogRaiseError(OG_ERR_FORMAT) return # Error si el nombre supera los 15 caracteres. if len(sys.argv[3]) > 15: ogRaiseError(OG_ERR_OUTOFLIMIT, sys.argv[3][:15] + "...") return # Montar el sistema de archivos. MNTDIR = ogMount(int(sys.argv[1]), int(sys.argv[2])) if MNTDIR is None: return # Asignar nombre. NAME = sys.argv[3] # Modificar datos de los valores de registro. ogSetRegistryValue(MNTDIR, "system", "\\ControlSet001\\Control\\ComputerName\\ComputerName\\ComputerName", NAME) ogSetRegistryValue(MNTDIR, "system", "\\ControlSet001\\Services\\Tcpip\\Parameters\\Hostname", NAME) ogSetRegistryValue(MNTDIR, "system", "\\ControlSet001\\Services\\Tcpip\\Parameters\\HostName", NAME) ogSetRegistryValue(MNTDIR, "system", "\\ControlSet001\\services\\Tcpip\\Parameters\\Hostname", NAME) ogSetRegistryValue(MNTDIR, "system", "\\ControlSet001\\Services\\Tcpip\\Parameters\\NV Hostname", NAME) ogSetRegistryValue(MNTDIR, "system", "\\ControlSet001\\Services\\Tcpip\\Parameters\\NV HostName", NAME) ogSetRegistryValue(MNTDIR, "system", "\\ControlSet001\\services\\Tcpip\\Parameters\\NV Hostname", NAME) def ogSetWinlogonUser(): FUNCNAME = ogSetWinlogonUser.__name__ # Variables locales. PART = None MNTDIR = None NAME = None # Si se solicita, mostrar ayuda. if len(sys.argv) > 1 and sys.argv[1] == "help": ogHelp(FUNCNAME, FUNCNAME + " int_ndisk int_npartition str_username", FUNCNAME + " 1 1 USUARIO") return # Error si no se reciben 3 parámetros. if len(sys.argv) != 4: ogRaiseError(OG_ERR_FORMAT) return # Montar el sistema de archivos. MNTDIR = ogMount(int(sys.argv[1]), int(sys.argv[2])) if MNTDIR is None: return # Asignar nombre. NAME = sys.argv[3] # Modificar datos en el registro. ogSetRegistryValue(MNTDIR, "SOFTWARE", "\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\DefaultUserName", NAME) def ogBootMbrXP(): FUNCNAME = ogBootMbrXP.__name__ # Variables locales. DISK = None # Si se solicita, mostrar ayuda. if len(sys.argv) > 1 and sys.argv[1] == "help": ogHelp(FUNCNAME, FUNCNAME + " int_ndisk ", FUNCNAME + " 1") return # Error si no se recibe 1 parámetro. if len(sys.argv) != 2: ogRaiseError(OG_ERR_FORMAT) return DISK = ogDiskToDev(int(sys.argv[1])) if DISK is None: return subprocess.call(["ms-sys", "-z", "-f", DISK]) subprocess.call(["ms-sys", "-m", "-f", DISK]) def ogBootMbrGeneric(): FUNCNAME = ogBootMbrGeneric.__name__ # Variables locales. DISK = None # Si se solicita, mostrar ayuda. if len(sys.argv) > 1 and sys.argv[1] == "help": ogHelp(FUNCNAME, FUNCNAME + " int_ndisk ", FUNCNAME + " 1") return # Error si no se recibe 1 parámetro. if len(sys.argv) != 2: ogRaiseError(OG_ERR_FORMAT) return DISK = ogDiskToDev(int(sys.argv[1])) if DISK is None: return subprocess.call(["ms-sys", "-z", "-f", DISK]) subprocess.call(["ms-sys", "-s", "-f", DISK]) # Firma necesaria para Windows equipos UEFI SIGNATURE = "0x" + str(uuid.uuid4()).split('-')[0] subprocess.call(["ms-sys", "-S", SIGNATURE, DISK]) def ogFixBootSector(): FUNCNAME = ogFixBootSector.__name__ # Variables locales. PARTYPE = None DISK = None PART = None FILE = None # Si se solicita, mostrar ayuda. if len(sys.argv) > 1 and sys.argv[1] == "help": ogHelp(FUNCNAME, FUNCNAME + " int_ndisk int_partition ", FUNCNAME + " 1 1 ") return # Error si no se reciben 2 parámetros. if len(sys.argv) != 3: ogRaiseError(OG_ERR_FORMAT) return # TODO, solo si la particion existe # TODO, solo si es ntfs o fat PARTYPE = ogGetPartitionId(int(sys.argv[1]), int(sys.argv[2])) if PARTYPE not in [1, 4, 6, 7, 11, 12, 14, 15, 23, 1792, 61440, 61440]: ogRaiseError(OG_ERR_PARTITION) return ogUnmount(int(sys.argv[1]), int(sys.argv[2])) or ogRaiseError(OG_ERR_PARTITION) # Preparando instruccion DISK = int(sys.argv[1]) - 1 PART = int(sys.argv[2]) FILE = "/tmp/temp$$" with open(FILE, "w") as f: f.write(f"disk={DISK}\nmain_part={PART}\nfix_first_sector=yes\n") subprocess.run(["timeout", "--foreground", "--signal=SIGKILL", "5s", "spartlnx.run", "-cui", "-nm", "-a", "-f", FILE]) os.remove(FILE) def ogGetBootMbr(): FUNCNAME = ogGetBootMbr.__name__ # Variables locales. DISK = None # Si se solicita, mostrar ayuda. if len(sys.argv) > 1 and sys.argv[1] == "help": ogHelp(FUNCNAME, FUNCNAME + " int_ndisk ", FUNCNAME + " 1") return # Error si no se recibe 1 parámetro. if len(sys.argv) != 2: ogRaiseError(OG_ERR_FORMAT) return DISK = ogDiskToDev(int(sys.argv[1])) if DISK is None: return subprocess.call(["ms-sys", "-f", DISK]) def ogWindowsBootParameters(): FUNCNAME = ogWindowsBootParameters.__name__ # Variables locales. PART = None DISK = None BOOTLABEL = None BCDFILE = None BOOTDISK = None BOOTPART = None FILE = None WINVER = None MOUNT = None # Si se solicita, mostrar ayuda. if len(sys.argv) > 1 and sys.argv[1] == "help": ogHelp(FUNCNAME, FUNCNAME + " int_ndisk int_partition ", FUNCNAME + " 1 1 ") return # Error si no se reciben 2 parámetros. if len(sys.argv) != 3: ogRaiseError(OG_ERR_FORMAT) return ogDiskToDev(int(sys.argv[1]), int(sys.argv[2])) or ogRaiseError(OG_ERR_PARTITION) DISK = int(sys.argv[1]) - 1 PART = int(sys.argv[2]) # Preparando variables adaptadas a sintaxis windows. if ogIsEfiActive(): BOOTDISK, BOOTPART = ogGetEsp() ogUnmount(BOOTDISK, BOOTPART) or ogRaiseError(OG_ERR_PARTITION, "ESP: {} {}".format(BOOTDISK, BOOTPART)) BOOTDISK -= 1 BOOTLABEL = "Part-{:02d}-{:02d}".format(int(sys.argv[1]), int(sys.argv[2])) BCDFILE = "boot_BCD_file=/EFI/{}/Boot/BCD".format(BOOTLABEL) else: BOOTDISK = DISK BOOTPART = PART BCDFILE = "" # Obtener versión de Windows. WINVER = ogGetOsVersion(int(sys.argv[1]), int(sys.argv[2])) if WINVER is None or not WINVER.startswith("Windows"): ogRaiseError(OG_ERR_NOTOS, "Windows") return # Acciones para Windows XP. if "XP" in WINVER: MOUNT = ogMount(int(sys.argv[1]), int(sys.argv[2])) if not os.path.isfile(os.path.join(MOUNT, "boot.ini")): ogRaiseError(OG_ERR_NOTFOUND, "boot.ini") return with open(os.path.join(MOUNT, "boot.ini"), "r") as f: content = f.read() content = content.replace("partition[0-9]", "partition[{}]".format(PART)).replace("rdisk[0-9]", "rdisk[{}]".format(DISK)) with open(os.path.join(MOUNT, "tmp.boot.ini"), "w") as f: f.write(content) os.rename(os.path.join(MOUNT, "tmp.boot.ini"), os.path.join(MOUNT, "boot.ini")) return ogUnmount(int(sys.argv[1]), int(sys.argv[2])) or ogRaiseError(OG_ERR_PARTITION) # Preparando instrucciones para Windows Resume Application, tipo windows, Ramdisk Options, Recovery Environment, Recovery, Windows Boot Manager, Herramienta de diagnóstico de memoria de Windows instructions = [ ("Windows Resume Application", ""), (WINVER, ""), ("Ramdisk Options", ""), ("Windows Recovery Environment", ""), ("Windows Recovery", ""), ("Windows Boot Manager", ""), ("Herramienta de diagnóstico de memoria de Windows", ""), ("Herramienta de diagnóstico de memoria de Windows", "") ] for entry, options in instructions: with open(FILE, "w") as f: f.write("boot_disk={}\n".format(BOOTDISK)) f.write("boot_main_part={}\n".format(BOOTPART)) f.write("{}\n".format(BCDFILE)) f.write("disk={}\n".format(DISK)) f.write("main_part={}\n".format(PART)) f.write("boot_entry={}\n".format(entry)) subprocess.run(["timeout", "--foreground", "--signal=SIGKILL", "5s", "spartlnx.run", "-cui", "-nm", "-w", "-f", FILE]) os.remove(FILE) def ogWindowsRegisterPartition(): FUNCNAME = ogWindowsRegisterPartition.__name__ # Variables locales. PART = None DISK = None FILE = None REGISTREDDISK = None REGISTREDPART = None REGISTREDVOL = None VERSION = None SYSTEMROOT = None # Si se solicita, mostrar ayuda. if len(sys.argv) > 1 and sys.argv[1] == "help": ogHelp(FUNCNAME, FUNCNAME + " int_ndisk_TO_registre int_partition_TO_registre str_NewVolume int_disk int_parition ", FUNCNAME + " 1 1 c: 1 1") return # Error si no se reciben 5 parámetros. if len(sys.argv) != 6: return ogRaiseError(OG_ERR_FORMAT) REGISTREDDISK = int(sys.argv[1]) REGISTREDPART = int(sys.argv[2]) REGISTREDVOL = sys.argv[3][0].upper() DISK = int(sys.argv[4]) PART = int(sys.argv[5]) FILE = "/tmp/temp$$" ogDiskToDev(REGISTREDDISK, REGISTREDPART) or ogRaiseError(OG_ERR_PARTITION, "particion a registrar") ogDiskToDev(DISK, PART) or ogRaiseError(OG_ERR_PARTITION, "particion de windows") TYPE = ogGetOsType(DISK, PART) if "Windows" not in TYPE: return ogRaiseError(OG_ERR_NOTOS, "no es windows") VERSION = ogGetOsVersion(DISK, PART) # Systemroot if ogGetPath(DISK, PART, "WINDOWS"): SYSTEMROOT = "Windows" elif ogGetPath(DISK, PART, "WINNT"): SYSTEMROOT = "winnt" else: return ogRaiseError(OG_ERR_NOTOS) ogUnmount(DISK, PART) DISK -= 1 REGISTREDDISK -= 1 # Preparando instruccion Windows Boot Manager with open(FILE, "w") as f: f.write(f"windows_disk={DISK}\n") f.write(f"windows_main_part={PART}\n") f.write(f"windows_dir={SYSTEMROOT}\n") f.write(f"disk={REGISTREDDISK}\n") f.write(f"main_part={REGISTREDPART}\n") f.write(f";ext_part\n") f.write(f"part_letter={REGISTREDVOL}\n") subprocess.run(["timeout", "--foreground", "--signal=SIGKILL", "5s", "spartlnx.run", "-cui", "-nm", "-u", "-f", FILE]) def ogGrubInstallMbr(): FUNCNAME = ogGrubInstallMbr.__name__ # Variables locales. PART = None DISK = None VERSION = None FIRSTSTAGE = None SECONDSTAGE = None CHECKOS = None KERNELPARAM = None BACKUPNAME = ".backup.og" EFIDISK = None EFIPART = None EFISECONDSTAGE = None EFISUBDIR = None EFIOPTGRUB = "" GRUBENTRY = None NEWORDER = None # Si se solicita, mostrar ayuda. if len(sys.argv) > 1 and sys.argv[1] == "help": ogHelp(FUNCNAME, FUNCNAME + " int_ndiskSecondStage int_partitionSecondStage bolean_Configure_2ndStage \"param param \" ", FUNCNAME + " 1 1 FALSE ", FUNCNAME + " 1 1 TRUE \"nomodeset irqpoll pci=noacpi quiet splash \" ") return # Error si no se reciben 2 parámetros. if len(sys.argv) < 3: return ogRaiseError(OG_ERR_FORMAT) DISK = int(sys.argv[1]) PART = int(sys.argv[2]) CHECKOS = sys.argv[3].upper() if len(sys.argv) > 3 else "FALSE" KERNELPARAM = sys.argv[4] if len(sys.argv) > 4 else "" # Error si no es linux. VERSION = ogGetOsVersion(DISK, PART) if not VERSION.startswith("Linux"): return ogRaiseError(OG_ERR_NOTOS, "no es linux") # La primera etapa del grub se fija en el primer disco duro FIRSTSTAGE = ogDiskToDev(1) # Localizar disco segunda etapa del grub SECONDSTAGE = ogMount(DISK, PART) if SECONDSTAGE is None: return # Prepara el directorio principal de la segunda etapa os.makedirs(os.path.join(SECONDSTAGE, "boot/grub"), exist_ok=True) # Localizar directorio segunda etapa del grub PREFIXSECONDSTAGE = "/boot/grubMBR" # Instalamos grub para EFI en ESP if ogIsEfiActive(): EFIDISK, EFIPART = ogGetEsp() # Comprobamos que exista ESP y el directorio para ubuntu EFISECONDSTAGE = ogMount(EFIDISK, EFIPART) if EFISECONDSTAGE is None: ogFormat(EFIDISK, EFIPART, "FAT32") EFISECONDSTAGE = ogMount(EFIDISK, EFIPART) if EFISECONDSTAGE is None: return ogRaiseError(OG_ERR_PARTITION, "ESP") EFISUBDIR = "grub" # Borramos la configuración anterior if os.path.isdir(os.path.join(EFISECONDSTAGE, "EFI", EFISUBDIR)): shutil.rmtree(os.path.join(EFISECONDSTAGE, "EFI", EFISUBDIR)) os.makedirs(os.path.join(EFISECONDSTAGE, "EFI", EFISUBDIR, "Boot"), exist_ok=True) EFIOPTGRUB = f"--removable --no-nvram --uefi-secure-boot --target {ogGetArch()}-efi --efi-directory=os.path.join(EFISECONDSTAGE, 'EFI', EFISUBDIR')" # Si Reconfigurar segunda etapa (grub.cfg) == FALSE if CHECKOS == "FALSE" and (os.path.isfile(os.path.join(SECONDSTAGE, "boot/grub/grub.cfg")) or os.path.isfile(os.path.join(SECONDSTAGE, "boot/grub/grub.cfg" + BACKUPNAME))): # Si no se reconfigura se utiliza el grub.cfg orginal if os.path.isfile(os.path.join(SECONDSTAGE, "boot/grub/grub.cfg" + BACKUPNAME)): os.rename(os.path.join(SECONDSTAGE, "boot/grub/grub.cfg" + BACKUPNAME), os.path.join(SECONDSTAGE, "boot/grub/grub.cfg")) # Si no se reconfigure se borra los ficheros previos de configuración específicos de opengnsys. if os.path.isdir(os.path.join(SECONDSTAGE, PREFIXSECONDSTAGE)): shutil.rmtree(os.path.join(SECONDSTAGE, PREFIXSECONDSTAGE)) PREFIXSECONDSTAGE = "" else: # SI Reconfigurar segunda etapa (grub.cfg) == TRUE # llamada a updateBootCache para que aloje la primera fase del ogLive updateBootCache() if ogIsEfiActive(): # UEFI: grubSintax necesita grub.cfg para detectar los kernels: si no existe recupero backup. if not os.path.isfile(os.path.join(SECONDSTAGE, "boot/grub/grub.cfg")): if os.path.isfile(os.path.join(SECONDSTAGE, "boot/grub/grub.cfg" + BACKUPNAME)): os.rename(os.path.join(SECONDSTAGE, "boot/grub/grub.cfg" + BACKUPNAME), os.path.join(SECONDSTAGE, "boot/grub/grub.cfg")) else: # Evitar detectar modo recovery - mover grub.cfg original a grub.cfg.backup os.rename(os.path.join(SECONDSTAGE, "boot/grub/grub.cfg"), os.path.join(SECONDSTAGE, "boot/grub/grub.cfg" + BACKUPNAME)) # Configurar la sintaxis grub para evitar menus de "recovery" en el OGLive with open("/etc/default/grub", "a") as f: f.write("GRUB_DISABLE_RECOVERY=\"true\"\n") f.write("GRUB_DISABLE_LINUX_UUID=\"true\"\n") # Preparar configuración segunda etapa: crear ubicacion os.makedirs(os.path.join(SECONDSTAGE, PREFIXSECONDSTAGE, "boot/grub"), exist_ok=True) # Preparar configuración segunda etapa: crear cabecera del fichero (ignorar errores) subprocess.run(["sed", "-i", "s/^set -e/#set -e/", "/etc/grub.d/00_header"]) # (ogLive 5.0) Si 'pkgdatadir' está vacía ponemos valor de otros ogLive subprocess.run(["sed", "-i", "/grub-mkconfig_lib/i\pkgdatadir=${pkgdatadir:-\"${datarootdir}/grub\"}'", "/etc/grub.d/00_header"]) subprocess.run(["/etc/grub.d/00_header"], stdout=open(os.path.join(SECONDSTAGE, PREFIXSECONDSTAGE, "boot/grub/grub.cfg"), "w"), stderr=subprocess.DEVNULL) # Preparar configuración segunda etapa: crear entrada del sistema operativo grubSyntax(KERNELPARAM, stdout=open(os.path.join(SECONDSTAGE, PREFIXSECONDSTAGE, "boot/grub/grub.cfg"), "a")) # Renombramos la configuración de grub antigua if os.path.isfile(os.path.join(SECONDSTAGE, "boot/grub/grub.cfg")): os.rename(os.path.join(SECONDSTAGE, "boot/grub/grub.cfg"), os.path.join(SECONDSTAGE, "boot/grub/grub.cfg" + BACKUPNAME)) # Instalar el grub subprocess.run(["grub-install", "--force", EFIOPTGRUB, f"--root-directory={os.path.join(SECONDSTAGE, PREFIXSECONDSTAGE)}", FIRSTSTAGE]) EVAL = subprocess.run(["echo", "$?"], capture_output=True, text=True).stdout.strip() # Movemos el grubx64.efi if ogIsEfiActive(): shutil.move(os.path.join(EFISECONDSTAGE, "EFI", EFISUBDIR, "EFI", "BOOT", "*"), os.path.join(EFISECONDSTAGE, "EFI", EFISUBDIR, "Boot")) shutil.rmtree(os.path.join(EFISECONDSTAGE, "EFI", EFISUBDIR, "EFI")) shutil.copy("/usr/lib/shim/shimx64.efi.signed", os.path.join(EFISECONDSTAGE, "EFI", EFISUBDIR, "Boot", "shimx64.efi")) # Nombre OpenGnsys para cargador shutil.copy(os.path.join(EFISECONDSTAGE, "EFI", EFISUBDIR, "Boot", "grubx64.efi"), os.path.join(EFISECONDSTAGE, "EFI", EFISUBDIR, "Boot", "ogloader.efi")) # Creamos entrada NVRAM y la ponemos en segundo lugar ogNvramAddEntry("grub", "/EFI/grub/Boot/shimx64.efi") GRUBENTRY = ogNvramList().get("grub") NEWORDER = ogNvramGetOrder() NEWORDER[GRUBENTRY] = NEWORDER.pop(0) ogNvramSetOrder(NEWORDER) return EVAL def ogGrubInstallPartition(): FUNCNAME = ogGrubInstallPartition.__name__ # Variables locales. PART = None DISK = None VERSION = None FIRSTAGE = None SECONSTAGE = None CHECKOS = None KERNELPARAM = None BACKUPNAME = ".backup.og" EFIDISK = None EFIPART = None EFISECONDSTAGE = None EFISUBDIR = None EFIOPTGRUB = "" EFIBOOTDIR = "" # Si se solicita, mostrar ayuda. if len(sys.argv) > 1 and sys.argv[1] == "help": ogHelp(FUNCNAME, FUNCNAME + " int_ndiskSecondStage int_partitionSecondStage bolean_Configure_2ndStage \"param param \" ", FUNCNAME + " 1 1 FALSE ", FUNCNAME + " 1 1 TRUE \"nomodeset irqpoll pci=noacpi quiet splash \" ") return # Error si no se reciben 2 parámetros. if len(sys.argv) < 3: return ogRaiseError(OG_ERR_FORMAT) DISK = int(sys.argv[1]) PART = int(sys.argv[2]) CHECKOS = sys.argv[3].upper() if len(sys.argv) > 3 else "FALSE" KERNELPARAM = sys.argv[4] if len(sys.argv) > 4 else "" BACKUPNAME = ".backup.og" # Error si no es linux. VERSION = ogGetOsVersion(DISK, PART) if not VERSION.startswith("Linux"): return ogRaiseError(OG_ERR_NOTOS, "no es linux") # Localizar primera etapa del grub FIRSTAGE = ogDiskToDev(DISK, PART) # Localizar disco segunda etapa del grub SECONSTAGE = ogMount(DISK, PART) # Localizar directorio segunda etapa del grub PREFIXSECONDSTAGE = "/boot/grubPARTITION" # Si es EFI instalamos el grub en la ESP EFIOPTGRUB = "" EFIBOOTDIR = "" if ogIsEfiActive(): EFIDISK, EFIPART = ogGetEsp() # Comprobamos que exista ESP y el directorio para ubuntu EFISECONDSTAGE = ogMount(EFIDISK, EFIPART) if EFISECONDSTAGE is None: ogFormat(EFIDISK, EFIPART, "FAT32") EFISECONDSTAGE = ogMount(EFIDISK, EFIPART) if EFISECONDSTAGE is None: return ogRaiseError(OG_ERR_PARTITION, "ESP") EFISUBDIR = "Part-{:02d}-{:02d}".format(DISK, PART) # Borramos la configuración anterior if os.path.isdir(os.path.join(EFISECONDSTAGE, "EFI", EFISUBDIR)): shutil.rmtree(os.path.join(EFISECONDSTAGE, "EFI", EFISUBDIR)) os.makedirs(os.path.join(EFISECONDSTAGE, "EFI", EFISUBDIR, "Boot"), exist_ok=True) EFIOPTGRUB = "--removable --no-nvram --uefi-secure-boot --target {}-efi --efi-directory={}".format(ogGetArch(), os.path.join(EFISECONDSTAGE, "EFI", EFISUBDIR)) EFIBOOTDIR = "/boot" # Si Reconfigurar segunda etapa (grub.cfg) == FALSE if CHECKOS == "FALSE" and (os.path.isfile(os.path.join(SECONSTAGE, "boot/grub/grub.cfg")) or os.path.isfile(os.path.join(SECONSTAGE, "boot/grub/grub.cfg" + BACKUPNAME))): # Si no se reconfigura se utiliza el grub.cfg orginal if os.path.isfile(os.path.join(SECONSTAGE, "boot/grub/grub.cfg" + BACKUPNAME)): os.rename(os.path.join(SECONSTAGE, "boot/grub/grub.cfg" + BACKUPNAME), os.path.join(SECONSTAGE, "boot/grub/grub.cfg")) # Si no se reconfigure se borra los ficheros previos de configuración específicos de opengnsys. if os.path.isdir(os.path.join(SECONSTAGE, PREFIXSECONDSTAGE)): shutil.rmtree(os.path.join(SECONSTAGE, PREFIXSECONDSTAGE)) PREFIXSECONDSTAGE = "" else: # SI Reconfigurar segunda etapa (grub.cfg) == TRUE if ogIsEfiActive(): # UEFI: grubSintax necesita grub.cfg para detectar los kernels: si no existe recupero backup. if not os.path.isfile(os.path.join(SECONSTAGE, "boot/grub/grub.cfg")): if os.path.isfile(os.path.join(SECONSTAGE, "boot/grub/grub.cfg" + BACKUPNAME)): os.rename(os.path.join(SECONSTAGE, "boot/grub/grub.cfg" + BACKUPNAME), os.path.join(SECONSTAGE, "boot/grub/grub.cfg")) else: # Evitar detectar modo recovery - mover grub.cfg original a grub.cfg.backup os.rename(os.path.join(SECONSTAGE, "boot/grub/grub.cfg"), os.path.join(SECONSTAGE, "boot/grub/grub.cfg" + BACKUPNAME)) # Configurar la sintaxis grub para evitar menus de "recovery" en el OGLive with open("/etc/default/grub", "a") as f: f.write("GRUB_DISABLE_RECOVERY=\"true\"\n") f.write("GRUB_DISABLE_LINUX_UUID=\"true\"\n") # Preparar configuración segunda etapa: crear ubicacion os.makedirs(os.path.join(SECONSTAGE, PREFIXSECONDSTAGE, "boot/grub"), exist_ok=True) # Preparar configuración segunda etapa: crear cabecera del fichero (ignorar errores) subprocess.run(["sed", "-i", "s/^set -e/#set -e/", "/etc/grub.d/00_header"]) # (ogLive 5.0) Si 'pkgdatadir' está vacía ponemos valor de otros ogLive subprocess.run(["sed", "-i", "/grub-mkconfig_lib/i\pkgdatadir=${pkgdatadir:-\"${datarootdir}/grub\"}'", "/etc/grub.d/00_header"]) subprocess.run(["/etc/grub.d/00_header"], stdout=open(os.path.join(SECONSTAGE, PREFIXSECONDSTAGE, "boot/grub/grub.cfg"), "w"), stderr=subprocess.DEVNULL) # Preparar configuración segunda etapa: crear entrada del sistema operativo grubSyntax(KERNELPARAM, stdout=open(os.path.join(SECONSTAGE, PREFIXSECONDSTAGE, "boot/grub/grub.cfg"), "a")) # Renombramos la configuración de grub antigua if os.path.isfile(os.path.join(SECONSTAGE, "boot/grub/grub.cfg")): os.rename(os.path.join(SECONSTAGE, "boot/grub/grub.cfg"), os.path.join(SECONSTAGE, "boot/grub/grub.cfg" + BACKUPNAME)) # Instalar el grub subprocess.run(["grub-install", "--force", EFIOPTGRUB, "--root-directory={}".format(os.path.join(SECONSTAGE, PREFIXSECONDSTAGE)), FIRSTAGE]) EVAL = subprocess.run(["echo", "$?"], capture_output=True, text=True).stdout.strip() # Movemos el grubx64.efi if ogIsEfiActive(): shutil.move(os.path.join(EFISECONDSTAGE, "EFI", EFISUBDIR, "EFI", "BOOT", "*"), os.path.join(EFISECONDSTAGE, "EFI", EFISUBDIR, "Boot")) shutil.rmtree(os.path.join(EFISECONDSTAGE, "EFI", EFISUBDIR, "EFI")) shutil.copy("/usr/lib/shim/shimx64.efi.signed", os.path.join(EFISECONDSTAGE, "EFI", EFISUBDIR, "Boot", "shimx64.efi")) # Nombre OpenGnsys para cargador shutil.copy(os.path.join(EFISECONDSTAGE, "EFI", EFISUBDIR, "Boot", "grubx64.efi"), os.path.join(EFISECONDSTAGE, "EFI", EFISUBDIR, "Boot", "ogloader.efi")) return EVAL def ogConfigureFstab(): # Variables locales. FSTAB = None DEFROOT = None PARTROOT = None DEFSWAP = None PARTSWAP = None EFIDISK = None EFIPART = None EFIDEV = None EFIOPT = None # Si se solicita, mostrar ayuda. if len(sys.argv) > 1 and sys.argv[1] == "help": return # Error si no se reciben 2 parámetros. if len(sys.argv) != 3: return ogRaiseError(OG_ERR_FORMAT) # Error si no se encuentra un fichero etc/fstab en el sistema de archivos. FSTAB = ogGetPath(int(sys.argv[1]), int(sys.argv[2]), "/etc/fstab") if not FSTAB: return ogRaiseError(OG_ERR_NOTFOUND, f"{sys.argv[1]},{sys.argv[2]},/etc/fstab") # Hacer copia de seguridad del fichero fstab original. shutil.copy2(FSTAB, f"{FSTAB}.backup") # Dispositivo del raíz en fichero fstab: 1er campo (si no tiene "#") con 2º campo = "/". with open(FSTAB, "r") as f: for line in f: if not line.startswith("#"): fields = line.split() if len(fields) >= 2 and fields[1] == "/": DEFROOT = fields[0] break PARTROOT = ogDiskToDev(int(sys.argv[1]), int(sys.argv[2])) # Configuración de swap (solo 1ª partición detectada). PARTSWAP = subprocess.run(["blkid", "-t", "TYPE=swap"], capture_output=True, text=True).stdout.split(":")[0] if PARTSWAP: # Dispositivo de swap en fichero fstab: 1er campo (si no tiene "#") con 3er campo = "swap". with open(FSTAB, "r") as f: for line in f: if not line.startswith("#"): fields = line.split() if len(fields) >= 3 and fields[2] == "swap": DEFSWAP = fields[0] break if DEFSWAP: print(f"Hay definicion de SWAP en el FSTAB {DEFSWAP} -> modificamos fichero con nuevo valor {DEFSWAP}->{PARTSWAP}") # Mensaje temporal. subprocess.run(["sed", f"s|{DEFSWAP}|{PARTSWAP}|g ; s|{DEFROOT}|{PARTROOT}|g", f"{FSTAB}.backup"], check=True, text=True, capture_output=True) else: print("No hay definicion de SWAP y si hay partición SWAP -> moficamos fichero") # Mensaje temporal. subprocess.run(["sed", f"s|{DEFROOT}|{PARTROOT}|g", f"{FSTAB}.backup"], check=True, text=True, capture_output=True) with open(FSTAB, "a") as f: f.write(f"{PARTSWAP}\tnone\tswap\tsw\t0\t0\n") else: print("No hay partición SWAP -> configuramos FSTAB") # Mensaje temporal. subprocess.run(["sed", "/swap/d", f"{FSTAB}.backup"], check=True, text=True, capture_output=True) # Si es un sistema EFI incluimos partición ESP (Si existe la modificamos) if ogIsEfiActive(): EFIDISK, EFIPART = ogGetEsp() EFIDEV = ogDiskToDev(EFIDISK, EFIPART) # Opciones de la partición ESP: si no existe ponemos un valor por defecto with open(FSTAB, "r") as f: for line in f: if not line.startswith("#"): fields = line.split() if len(fields) >= 2 and fields[1] == "/boot/efi": EFIOPT = "\t".join(fields[2:6]) break if not EFIOPT: EFIOPT = "vfat\tumask=0077\t0\t1" subprocess.run(["sed", "-i", "/boot\/efi/d", FSTAB], check=True, text=True, capture_output=True) with open(FSTAB, "a") as f: f.write(f"{EFIDEV}\t/boot/efi\t{EFIOPT}\n") def ogSetLinuxName(): # Variables locales. MNTDIR = None ETC = None NAME = None # Si se solicita, mostrar ayuda. if len(sys.argv) > 1 and sys.argv[1] == "help": return # Error si no se reciben 2 o 3 parámetros. if len(sys.argv) == 3: # Asignar nombre automático (por defecto, "pc"). NAME = ogGetHostname() or "pc" elif len(sys.argv) == 4: # Asignar nombre del 3er parámetro. NAME = sys.argv[3] else: # Formato de ejecución incorrecto. return ogRaiseError(OG_ERR_FORMAT) # Montar el sistema de archivos. MNTDIR = ogMount(int(sys.argv[1]), int(sys.argv[2])) if not MNTDIR: return ETC = ogGetPath(int(sys.argv[1]), int(sys.argv[2]), "/etc") if os.path.isdir(ETC): # cambio de nombre en hostname with open(os.path.join(ETC, "hostname"), "w") as f: f.write(NAME) # cambio de nombre en hosts with open(os.path.join(ETC, "hosts"), "w") as f: f.write("127.0.0.1 localhost\n") f.write("127.0.1.1 {}\n".format(NAME)) f.write("\n") f.write("# The following lines are desirable for IPv6 capable hosts\n") f.write("::1 ip6-localhost ip6-loopback\n") f.write("fe00::0 ip6-localnet\n") f.write("ff00::0 ip6-mcastprefix\n") f.write("ff02::1 ip6-allnodes\n") f.write("ff02::2 ip6-allrouters\n") def ogCleanLinuxDevices(): # Variables locales. MNTDIR = None # Si se solicita, mostrar ayuda. if len(sys.argv) > 1 and sys.argv[1] == "help": return # Error si no se reciben 2 parámetros. if len(sys.argv) != 3: return ogRaiseError(OG_ERR_FORMAT) # Montar el sistema de archivos. MNTDIR = ogMount(int(sys.argv[1]), int(sys.argv[2])) if not MNTDIR: return # Eliminar fichero de configuración de udev para dispositivos fijos de red. if os.path.isfile(os.path.join(MNTDIR, "etc/udev/rules.d/70-persistent-net.rules")): os.remove(os.path.join(MNTDIR, "etc/udev/rules.d/70-persistent-net.rules")) # Eliminar fichero resume (estado previo de hibernación) utilizado por el initrd scripts-premount if os.path.isfile(os.path.join(MNTDIR, "etc/initramfs-tools/conf.d/resume")): os.remove(os.path.join(MNTDIR, "etc/initramfs-tools/conf.d/resume")) def ogGrubAddOgLive(): FUNCNAME = ogGrubAddOgLive.__name__ TIMEOUT = None DIRMOUNT = None GRUBGFC = None PARTTABLETYPE = None NUMDISK = None NUMPART = None KERNEL = None STATUS = None NUMLINE = None MENUENTRY = None # Si se solicita, mostrar ayuda. if len(sys.argv) > 1 and sys.argv[1] == "help": ogHelp(FUNCNAME, f"{FUNCNAME} int_ndisk int_npartition [ time_out ] [ offline|online ]", f"{FUNCNAME} 1 1", f"{FUNCNAME} 1 6 15 offline") return # Error si no se reciben 2 parámetros. if len(sys.argv) < 3: return ogRaiseError(OG_ERR_FORMAT) if sys.argv[3].isdigit(): TIMEOUT = int(sys.argv[3]) # Error si no existe el kernel y el initrd en la cache. # Falta crear nuevo codigo de error. if not os.path.isfile(f"{OGCAC}/boot/{oglivedir}/ogvmlinuz") or not os.path.isfile(f"{OGCAC}/boot/{oglivedir}/oginitrd.img"): return ogRaiseError(OG_ERR_NOTFOUND, "CACHE: ogvmlinuz, oginitrd.img") # Archivo de configuracion del grub DIRMOUNT = ogMount(int(sys.argv[1]), int(sys.argv[2])) GRUBGFC = f"{DIRMOUNT}/boot/grubMBR/boot/grub/grub.cfg" # Error si no existe archivo del grub if not os.path.isfile(GRUBGFC): return ogRaiseError(OG_ERR_NOTFOUND, GRUBGFC) # Si existe la entrada de opengnsys, se borra with open(GRUBGFC, "r") as f: lines = f.readlines() with open(GRUBGFC, "w") as f: for line in lines: if "menuentry Opengnsys" not in line: f.write(line) # Tipo de tabla de particiones PARTTABLETYPE = ogGetPartitionTableType(int(sys.argv[1])).lower() # Localizacion de la cache NUMDISK, NUMPART = ogFindCache() NUMDISK -= 1 # kernel y sus opciones. Pasamos a modo usuario KERNEL = f"/boot/{oglivedir}/ogvmlinuz {' '.join([arg for arg in sys.argv[4:] if not arg.startswith('ogactiveadmin=')])}" # Configuracion offline si existe parametro if "offline" in sys.argv: STATUS = "offline" elif "online" in sys.argv: STATUS = "online" if STATUS: KERNEL = KERNEL.replace("ogprotocol=", "ogprotocol=local ") KERNEL += f" ogstatus={STATUS}" # Numero de línea de la primera entrada del grub. with open(GRUBGFC, "r") as f: lines = f.readlines() for i, line in enumerate(lines): if line.startswith("menuentry"): NUMLINE = i + 1 break # Texto de la entrada de opengnsys MENUENTRY = f"""menuentry "OpenGnsys" --class opengnsys --class gnu --class os {{ insmod part_{PARTTABLETYPE} insmod ext2 set root='(hd{NUMDISK},{PARTTABLETYPE}{NUMPART})' linux {KERNEL} initrd /boot/{oglivedir}/oginitrd.img }} """ # Insertamos la entrada de opengnsys antes de la primera entrada existente. lines.insert(NUMLINE, MENUENTRY + "\n") with open(GRUBGFC, "w") as f: f.writelines(lines) # Ponemos que la entrada por defecto sea la primera. with open(GRUBGFC, "r") as f: lines = f.readlines() with open(GRUBGFC, "w") as f: for line in lines: if line.startswith("set default="): f.write("set default=\"0\"\n") else: f.write(line) # Si me dan valor para timeout lo cambio en el grub. if TIMEOUT: with open(GRUBGFC, "r") as f: lines = f.readlines() with open(GRUBGFC, "w") as f: for line in lines: if line.startswith("timeout="): f.write(f"timeout={TIMEOUT}\n") else: f.write(line) def ogGrubHidePartitions(): FUNCNAME = ogGrubHidePartitions.__name__ # Si se solicita, mostrar ayuda. if len(sys.argv) > 1 and sys.argv[1] == "help": ogHelp(FUNCNAME, f"{FUNCNAME} int_ndisk int_npartition [ num_disk_partdata num_partdata ]", f"{FUNCNAME} 1 2", f"{FUNCNAME} 1 2 1 3") return ogBootLoaderHidePartitions(*sys.argv[1:]) return def ogBurgHidePartitions(): FUNCNAME = ogBurgHidePartitions.__name__ # Si se solicita, mostrar ayuda. if len(sys.argv) > 1 and sys.argv[1] == "help": ogHelp(FUNCNAME, f"{FUNCNAME} int_ndisk int_npartition [ num_disk_partdata num_partdata ]", f"{FUNCNAME} 1 2", f"{FUNCNAME} 1 2 1 3") return ogBootLoaderHidePartitions(*sys.argv[1:]) return def ogBootLoaderHidePartitions(): FUNCNAME = ogBootLoaderHidePartitions.__name__ FUNC = None DIRMOUNT = None GFCFILE = None PARTTABLETYPE = None WINENTRY = None WINPART = None ENTRY = None LINE = None PART = None PARTDATA = None TEXT = None PARTHIDDEN = None HIDDEN = None # Si se solicita, mostrar ayuda. if len(sys.argv) > 1 and sys.argv[1] == "help": ogHelp(FUNCNAME, f"{FUNCNAME} num_disk num_part [ num_disk_partdata num_partdata ]", f"{FUNCNAME} 1 2", f"{FUNCNAME} 1 2 1 3") return # Nombre de la función que llama a esta. FUNC = sys._getframe().f_back.f_code.co_name # Error si no se reciben 2 parámetros. if len(sys.argv) < 3: return ogRaiseError(OG_ERR_FORMAT) if len(sys.argv) == 4: PARTDATA = ogDiskToDev(int(sys.argv[3]), int(sys.argv[4])) else: PARTDATA = 0 # Archivo de configuracion del grub DIRMOUNT = ogMount(int(sys.argv[1]), int(sys.argv[2])) # La función debe ser llamada desde ogGrubHidePartitions or ogBurgHidePartitions. if FUNC == "ogGrubHidePartitions": GFCFILE = f"{DIRMOUNT}/boot/grubMBR/boot/grub/grub.cfg" elif FUNC == "ogBurgHidePartitions": GFCFILE = f"{DIRMOUNT}/boot/burg/burg.cfg" else: return ogRaiseError(OG_ERR_FORMAT, "Use ogGrubHidePartitions or ogBurgHidePartitions.") # Error si no existe archivo del grub if not os.path.isfile(GFCFILE): return ogRaiseError(OG_ERR_NOTFOUND, GFCFILE) # Si solo hay una particion de Windows me salgo if subprocess.run(["fdisk", "-l", ogDiskToDev(), "|", "grep", "NTFS", "|", "wc", "-l"], capture_output=True, text=True).stdout.strip() == "1": return 0 # Elimino llamadas a parttool, se han incluido en otras ejecuciones de esta funcion. subprocess.run(["sed", "-i", "/parttool/d", GFCFILE], check=True) PARTTABLETYPE = ogGetPartitionTableType(int(sys.argv[1])).lower() # Entradas de Windows: numero de linea y particion. De mayor a menor. WINENTRY = subprocess.run(["awk", "/menuentry.*Windows/ {gsub(/\\)\"/, \"\"); gsub(/^.*dev/,\"\", \"\"); print NR\":/dev\"$1}", CFGFILE], capture_output=True, text=True).stdout.strip().split("\n") # Particiones de Windows, pueden no estar en el grub. WINPART = subprocess.run(["fdisk", "-l", ogDiskToDev(), "|", "awk", "/NTFS/ {print $1}", "|", "sed", "1!G;h;$!d"], capture_output=True, text=True).stdout.strip().split("\n") # Modifico todas las entradas de Windows. for ENTRY in WINENTRY: LINE, PART = ENTRY.split(":") TEXT = "" for PARTHIDDEN in WINPART: # Muestro la particion de la entrada actual y la de datos. if PARTHIDDEN == PART or PARTHIDDEN == PARTDATA: HIDDEN = "-" else: HIDDEN = "+" NUMDISK, NUMPART = ogDevToDisk(PARTHIDDEN) TEXT = f"\tparttool (hd{NUMDISK-1},{PARTTABLETYPE}{NUMPART}) hidden{HIDDEN} \n{TEXT}" subprocess.run(["sed", "-i", f"{LINE}a\ {TEXT}", GFCFILE], check=True) # Activamos la particion que se inicia en todas las entradas de windows. subprocess.run(["sed", "-i", "/chainloader/i\\\tparttool ${root} boot+", GFCFILE], check=True) CFGFILE = "path/to/config/file" def ogGrubDeleteEntry(): # Si se solicita, mostrar ayuda. if len(sys.argv) > 1 and sys.argv[1] == "help": ogHelp(sys.argv[0], f"{sys.argv[0]} int_ndisk int_npartition int_disk_delete int_npartition_delete", f"{sys.argv[0]} 1 6 2 1") return ogBootLoaderDeleteEntry(*sys.argv[1:]) return def ogBurgDeleteEntry(): # Si se solicita, mostrar ayuda. if len(sys.argv) > 1 and sys.argv[1] == "help": ogHelp(sys.argv[0], f"{sys.argv[0]} int_ndisk int_npartition int_disk_delete int_npartition_delete", f"{sys.argv[0]} 1 6 2 1") return ogBootLoaderDeleteEntry(*sys.argv[1:]) return def ogRefindDeleteEntry(): # Si se solicita, mostrar ayuda. if len(sys.argv) > 1 and sys.argv[1] == "help": ogHelp("ogRefindDeleteEntry", "ogRefindDeleteEntry int_disk_delete int_npartition_delete", "ogRefindDeleteEntry 2 1") return EFIDISK, EFIPART = ogGetEsp().split() ogBootLoaderDeleteEntry(EFIDISK, EFIPART, *sys.argv[1:]) return def ogBootLoaderDeleteEntry(): FUNC = None DIRMOUNT = None CFGFILE = None LABEL = None MENUENTRY = None DELETEENTRY = None ENDENTRY = None ENTRY = None # Si se solicita, mostrar ayuda. if len(sys.argv) > 1 and sys.argv[1] == "help": ogHelp(sys.argv[0], f"{sys.argv[0]} int_ndisk int_npartition int_disk_delete int_npartition_delete", f"{sys.argv[0]} 1 6 2 1") return # Si el número de parámetros es menor que 4, salimos. if len(sys.argv) < 5: return ogRaiseError(OG_ERR_FORMAT) # Nombre de la función que llama a esta. FUNC = sys._getframe().f_back.f_code.co_name # Archivo de configuracion del grub DIRMOUNT = ogMount(int(sys.argv[1]), int(sys.argv[2])) # La función debe ser llamada desde ogGrubDeleteEntry, ogBurgDeleteEntry or ogRefindDeleteEntry. if FUNC == "ogGrubDeleteEntry": CFGFILE = f"{DIRMOUNT}/boot/grubMBR/boot/grub/grub.cfg" elif FUNC == "ogBurgDeleteEntry": CFGFILE = f"{DIRMOUNT}/boot/burg/burg.cfg" elif FUNC == "ogRefindDeleteEntry": CFGFILE = f"{DIRMOUNT}/EFI/refind/refind.conf" else: return ogRaiseError(OG_ERR_FORMAT, "Use ogGrubDeleteEntry, ogBurgDeleteEntry or ogRefindDeleteEntry.") # Dispositivo if os.path.basename(CFGFILE) == "refind.conf": LABEL = f"Part-{int(sys.argv[3]):02d}-{int(sys.argv[4]):02d}" else: LABEL = ogDiskToDev(int(sys.argv[3]), int(sys.argv[4])) # Error si no existe archivo de configuración if not os.path.isfile(CFGFILE): return ogRaiseError(OG_ERR_NOTFOUND, CFGFILE) # Numero de linea de cada entrada. with open(CFGFILE, "r") as f: lines = f.readlines() MENUENTRY = [str(i+1) for i, line in enumerate(lines) if "menuentry" in line] # Entradas que hay que borrar. DELETEENTRY = [str(i+1) for i, line in enumerate(lines) if f"menuentry {LABEL}" in line] # Si no hay entradas para borrar, salimos con aviso if not DELETEENTRY: return ogRaiseError(OG_ERR_NOTFOUND, f"Menuentry {LABEL}") # Recorremos el fichero del final hacia el principio. ENDENTRY = len(lines) for ENTRY in MENUENTRY: # Comprobamos si hay que borrar la entrada. if ENTRY in DELETEENTRY: ENDENTRY -= 1 lines = lines[:int(ENTRY)-1] + lines[int(ENDENTRY):] # Guardamos el número de línea de la entrada, que sera el final de la siguiente. ENDENTRY = ENTRY with open(CFGFILE, "w") as f: f.writelines(lines) def ogBurgInstallMbr(): FUNCNAME = ogBurgInstallMbr.__name__ # Variables locales. BINARYAVAILABLE = None PART = None DISK = None DEVICE = None MOUNTDISK = None FIRSTAGE = None SECONSTAGE = None PREFIXSECONDSTAGE = None CHECKOS = None KERNELPARAM = None BACKUPNAME = ".backup.og" FILECFG = None # Si se solicita, mostrar ayuda. if len(sys.argv) > 1 and sys.argv[1] == "help": ogHelp(FUNCNAME, f"{FUNCNAME} int_ndiskSecondStage int_partitionSecondStage bolean_Configure_2ndStage \"param param \" ", f"{FUNCNAME} 1 1 FALSE ", f"{FUNCNAME} 1 1 TRUE \"nomodeset irqpoll pci=noacpi quiet splash \" ") return # Error si no se reciben 2 parametros. if len(sys.argv) < 3: return ogRaiseError(OG_ERR_FORMAT) # Error si no tenemos el binario burg BINARYAVAILABLE = subprocess.run(["burg-install", "-v"], capture_output=True, text=True).stdout.strip() if BINARYAVAILABLE == "NO": if os.path.exists(f"{OGLIB}/burg/burg.tgz"): subprocess.run(["tar", "xzvf", f"{OGLIB}/burg/burg.tgz", "--strip", "1"], cwd="/", capture_output=True, text=True) else: return ogRaiseError(OG_ERR_NOTEXEC, "Binary burg not found") DISK = int(sys.argv[1]) PART = int(sys.argv[2]) CHECKOS = sys.argv[3].upper() if len(sys.argv) > 3 else "FALSE" KERNELPARAM = sys.argv[4] if len(sys.argv) > 4 else "" # Controlar disco no uefi if ogIsEfiActive(): return ogRaiseError(OG_ERR_NOTBIOS, "grub4dos solo soporta PC con bios legacy") # Controlar particionado tipo msdos if not ogCheckStringInGroup(ogGetPartitionTableType(DISK), "MSDOS"): return ogRaiseError(OG_ERR_NOMSDOS, "grub2dos requiere particionado tipo MSDOS") # Controlar existencia de disco y particion DEVICE = ogDiskToDev(DISK) if not DEVICE: return ogRaiseError(OG_ERR_NOTFOUND) MOUNTDISK = ogMount(DISK, PART) if not MOUNTDISK: return ogRaiseError(OG_ERR_PARTITION) # Controlar particion segunda etapa del burg if not ogCheckStringInGroup(ogGetFsType(DISK, PART), "CACHE EXT4 EXT3 EXT2"): return ogRaiseError(OG_ERR_PARTITION, "burg.cfg soporta solo particiones linux") # Controlar acceso de escritura a la particion segunda etapa del burg if ogIsReadonly(DISK, PART): return ogRaiseError(OG_ERR_NOTWRITE, f"{DISK} {PART}") # Asigar la primera etapa del grub en el primer disco duro FIRSTAGE = ogDiskToDev(1) # Localizar disco segunda etapa del grub SECONSTAGE = ogMount(DISK, PART) # Preparar el directorio principal de la segunda etapa (y copia los binarios) if not os.path.isdir(f"{SECONSTAGE}/boot/burg/"): os.makedirs(f"{SECONSTAGE}/boot/burg/") shutil.copytree("/boot/burg/", f"{SECONSTAGE}/boot/burg/") shutil.copytree(f"{OGLIB}/burg/themes", f"{SECONSTAGE}/boot/burg/themes") # No configurar la segunda etapa (grub.cfg). Parámetro FALSE if os.path.isfile(f"{SECONSTAGE}/boot/burg/burg.cfg") or os.path.isfile(f"{SECONSTAGE}/boot/burg/burg.cfg{BACKUPNAME}"): if CHECKOS == "FALSE": subprocess.run(["burg-install", "--force", f"--root-directory={SECONSTAGE}", FIRSTAGE], capture_output=True, text=True) return # Configurar la segunda etapa (burg.cfg) == tercer parámetro TRUE # Llamar a updateBootCache para que aloje la primera fase del ogLive updateBootCache() # Configurar la sintaxis grub para evitar menus de "recovery" en el OGLive with open("/etc/default/grub", "a") as f: f.write("GRUB_DISABLE_RECOVERY=\"true\"\n") f.write("GRUB_DISABLE_LINUX_UUID=\"true\"\n") # Preparar configuración segunda etapa: crear ubicacion os.makedirs(f"{SECONSTAGE}{PREFIXSECONDSTAGE}/boot/burg/") # Preparar configuración segunda etapa: crear cabecera del fichero FILECFG = f"{SECONSTAGE}{PREFIXSECONDSTAGE}/boot/burg/burg.cfg" # Preparar configuración segunda etapa: crear entrada del sistema operativo with open(FILECFG, "w") as f: f.write("set theme_name=OpenGnsys\n") f.write("set gfxmode=1024x768\n") f.write("set locale_dir=($root)/boot/burg/locale\n") f.write("set default=0\n") f.write("set timeout=25\n") f.write("set lang=es\n") f.write("insmod ext2\n") f.write("insmod gettext\n") f.write("if [ -s $prefix/burgenv ]; then\n") f.write(" load_env\n") f.write("fi\n") f.write("if [ ${prev_saved_entry} ]; then\n") f.write(" set saved_entry=${prev_saved_entry}\n") f.write(" save_env saved_entry\n") f.write(" set prev_saved_entry=\n") f.write(" save_env prev_saved_entry\n") f.write(" set boot_once=true\n") f.write("fi\n") f.write("function savedefault {\n") f.write(" if [ -z ${boot_once} ]; then\n") f.write(" saved_entry=${chosen}\n") f.write(" save_env saved_entry\n") f.write(" fi\n") f.write("}\n") f.write("function select_menu {\n") f.write(" if menu_popup -t template_popup theme_menu ; then\n") f.write(" free_config template_popup template_subitem menu class screen\n") f.write(" load_config ${prefix}/themes/${theme_name}/theme ${prefix}/themes/custom/theme_${theme_name}\n") f.write(" save_env theme_name\n") f.write(" menu_refresh\n") f.write(" fi\n") f.write("}\n") f.write("function toggle_fold {\n") f.write(" if test -z $theme_fold ; then\n") f.write(" set theme_fold=1\n") f.write(" else\n") f.write(" set theme_fold=\n") f.write(" fi\n") f.write(" save_env theme_fold\n") f.write(" menu_refresh\n") f.write("}\n") f.write("function select_resolution {\n") f.write(" if menu_popup -t template_popup resolution_menu ; then\n") f.write(" menu_reload_mode\n") f.write(" save_env gfxmode\n") f.write(" fi\n") f.write("}\n") f.write("if test -f ${prefix}/themes/${theme_name}/theme ; then\n") f.write(" insmod coreui\n") f.write(" menu_region.text\n") f.write(" load_string '+theme_menu { -OpenGnsys { command=\"set theme_name=OpenGnsys\" }}'\n") f.write(" load_config ${prefix}/themes/conf.d/10_hotkey\n") f.write(" load_config ${prefix}/themes/${theme_name}/theme ${prefix}/themes/custom/theme_${theme_name}\n") f.write(" insmod vbe\n") f.write(" insmod png\n") f.write(" insmod jpeg\n") f.write(" set gfxfont=\"Unifont Regular 16\"\n") f.write(" menu_region.gfx\n") f.write(" vmenu resolution_menu\n") f.write(" controller.ext\n") f.write("fi\n") # Preparar configuración segunda etapa: crear entrada del sistema operativo grubSyntax(KERNELPARAM, FILECFG) # Instalar el burg subprocess.run(["burg-install", "--force", f"--root-directory={SECONSTAGE}", FIRSTAGE], capture_output=True, text=True) def ogGrubDefaultEntry(): # Si se solicita, mostrar ayuda. if len(sys.argv) > 1 and sys.argv[1] == "help": ogHelp(sys.argv[0], f"{sys.argv[0]} int_ndisk int_npartition int_disk_default_entry int_npartition_default_entry", f"{sys.argv[0]} 1 6 1 1") return ogBootLoaderDefaultEntry(*sys.argv[1:]) return def ogBurgDefaultEntry(): # Si se solicita, mostrar ayuda. if len(sys.argv) > 1 and sys.argv[1] == "help": ogHelp(sys.argv[0], f"{sys.argv[0]} int_ndisk int_npartition int_disk_default_entry int_npartition_default_entry", f"{sys.argv[0]} 1 6 1 1") return ogBootLoaderDefaultEntry(*sys.argv[1:]) return def ogRefindDefaultEntry(): EFIDISK, EFIPART = ogGetEsp().split() # Si se solicita, mostrar ayuda. if len(sys.argv) > 1 and sys.argv[1] == "help": ogHelp("ogRefindDefaultEntry", "ogRefindDefaultEntry int_disk_default_entry int_npartition_default_entry", "ogRefindDefaultEntry 1 1") return ogBootLoaderDefaultEntry(EFIDISK, EFIPART, *sys.argv[1:]) return def ogBootLoaderDefaultEntry(): # Variables locales. PART = None FUNC = None DIRMOUNT = None LABEL = None CFGFILE = None DEFAULTENTRY = None MENUENTRY = None # Si se solicita, mostrar ayuda. if len(sys.argv) > 1 and sys.argv[1] == "help": ogHelp(sys.argv[0], f"{sys.argv[0]} int_ndiskSecondStage int_partitionSecondStage int_disk_default_entry int_partitions_default_entry", f"{sys.argv[0]} 1 6 1 1") return # Nombre de la función que llama a esta. FUNC = sys._getframe().f_back.f_code.co_name # Error si no se reciben 4 parámetros. if len(sys.argv) < 5: return ogRaiseError(OG_ERR_FORMAT) # Error si no puede montar sistema de archivos. DIRMOUNT = ogMount(int(sys.argv[1]), int(sys.argv[2])) if not DIRMOUNT: return # Comprobamos que exista fichero de configuración # La función debe ser llamada desde ogGrubDefaultEntry, ogBurgDefaultEntry or ogRefindDefaultEntry. if FUNC == "ogGrubDefaultEntry": CFGFILE = f"{DIRMOUNT}/boot/grubMBR/boot/grub/grub.cfg" elif FUNC == "ogBurgDefaultEntry": CFGFILE = f"{DIRMOUNT}/boot/burg/burg.cfg" elif FUNC == "ogRefindDefaultEntry": CFGFILE = f"{DIRMOUNT}/EFI/refind/refind.conf" else: return ogRaiseError(OG_ERR_FORMAT, "Use ogGrubDefaultEntry, ogBurgDefaultEntry or ogRefindDefaultEntry.") # Error si no existe archivo de configuración if not os.path.isfile(CFGFILE): return ogRaiseError(OG_ERR_NOTFOUND, CFGFILE) # Dispositivo if os.path.basename(CFGFILE) == "refind.conf": LABEL = f"Part-{int(sys.argv[3]):02d}-{int(sys.argv[4]):02d}" else: LABEL = ogDiskToDev(int(sys.argv[3]), int(sys.argv[4])) # Número de línea de la entrada por defecto en CFGFILE (primera de la partición). with open(CFGFILE, "r") as f: lines = f.readlines() for i, line in enumerate(lines): if f"menuentry {LABEL}" in line: DEFAULTENTRY = i + 1 break # Si no hay entradas para borrar me salgo con aviso if not DEFAULTENTRY: return ogRaiseError(OG_ERR_NOTFOUND, f"No menuentry {LABEL}") # Número de la de linea por defecto en el menú de usuario with open(CFGFILE, "r") as f: menu_entries = [i for i, line in enumerate(f) if "menuentry" in line] MENUENTRY = menu_entries.index(DEFAULTENTRY) + 1 if os.path.basename(CFGFILE) == "refind.conf": subprocess.run(["sed", "-i", "/default_selection.*$/d", CFGFILE], check=True) subprocess.run(["sed", "-i", f"1 i\\default_selection {MENUENTRY}", CFGFILE], check=True) else: # En grub y burg las líneas empiezan a contar desde cero MENUENTRY -= 1 subprocess.run(["sed", "-i", f"s/set default=\"?[0-9]*\"?$/set default=\"{MENUENTRY}\"/g", CFGFILE], check=True) def ogGrubOgliveDefaultEntry(): # Si se solicita, mostrar ayuda. if len(sys.argv) > 1 and sys.argv[1] == "help": ogHelp(sys.argv[0], f"{sys.argv[0]} int_ndiskSecondStage int_partitionSecondStage", f"{sys.argv[0]} 1 6") return ogBootLoaderOgliveDefaultEntry(*sys.argv[1:]) return def ogBurgOgliveDefaultEntry(): # Si se solicita, mostrar ayuda. if len(sys.argv) > 1 and sys.argv[1] == "help": ogHelp(sys.argv[0], f"{sys.argv[0]} int_ndiskSecondStage int_partitionSecondStage", f"{sys.argv[0]} 1 6") return ogBootLoaderOgliveDefaultEntry(*sys.argv[1:]) return def ogRefindOgliveDefaultEntry(): EFIDISK, EFIPART = ogGetEsp().split() # Si se solicita, mostrar ayuda. if len(sys.argv) > 1 and sys.argv[1] == "help": ogHelp("ogRefindOgliveDefaultEntry", "ogRefindOgliveDefaultEntry", "ogRefindOgliveDefaultEntry") return ogBootLoaderOgliveDefaultEntry(EFIDISK, EFIPART) return def ogBootLoaderOgliveDefaultEntry(): # Variables locales. PART = None FUNC = None CFGFILE = None NUMENTRY = None # Si se solicita, mostrar ayuda. if len(sys.argv) > 1 and sys.argv[1] == "help": ogHelp(sys.argv[0], f"{sys.argv[0]} int_ndiskSecondStage int_partitionSecondStage", f"{sys.argv[0]} 1 6") return # Nombre de la función que llama a esta. FUNC = sys._getframe().f_back.f_code.co_name # Error si no se reciben 2 parametros. if len(sys.argv) < 3: return ogRaiseError(OG_ERR_FORMAT) # Error si no puede montar sistema de archivos. PART = ogMount(int(sys.argv[1]), int(sys.argv[2])) if not PART: return # La función debe ser llamada desde ogGrubOgliveDefaultEntry, ogBurgOgliveDefaultEntry or ogRefindOgliveDefaultEntry. if FUNC == "ogGrubOgliveDefaultEntry": CFGFILE = f"{PART}/boot/grubMBR/boot/grub/grub.cfg" elif FUNC == "ogBurgOgliveDefaultEntry": CFGFILE = f"{PART}/boot/burg/burg.cfg" elif FUNC == "ogRefindOgliveDefaultEntry": CFGFILE = f"{PART}/EFI/refind/refind.conf" else: return ogRaiseError(OG_ERR_FORMAT, "Use ogGrubOgliveDefaultEntry, ogBurgOgliveDefaultEntry or ogRefindOgliveDefaultEntry.") # Comprobamos que exista fichero de configuración if not os.path.isfile(CFGFILE): return ogRaiseError(OG_ERR_NOTFOUND, CFGFILE) # Detectamos cual es la entrada de ogLive with open(CFGFILE, "r") as f: lines = f.readlines() for i, line in enumerate(lines): if "menuentry" in line and "OpenGnsys Live" in line: NUMENTRY = i + 1 break # Si no existe entrada de ogLive nos salimos if not NUMENTRY: return ogRaiseError(OG_ERR_NOTFOUND, f"menuentry OpenGnsys Live in {CFGFILE}") if os.path.basename(CFGFILE) == "refind.conf": subprocess.run(["sed", "-i", "/default_selection.*$/d", CFGFILE], check=True) subprocess.run(["sed", "-i", f"1 i\\default_selection {NUMENTRY}", CFGFILE], check=True) else: NUMENTRY -= 1 subprocess.run(["sed", "-i", f"s/set default=\"?[0-9]+\"?/set default=\"{NUMENTRY}\"/g", CFGFILE], check=True) # Generate the help message based on the function name MSG = f"MSG_HELP_{FUNC}" help_message = f"{globals()[MSG].split('.')[0]}: {' '.join(sys.argv[1:])}" print(help_message) def ogGrubSecurity(): # Variables locales. SECONDSTAGE = None GRUBGFC = None FILE = None USER = None PASSWD = None ENCRYPTPASSWD = None # Si se solicita, mostrar ayuda. if len(sys.argv) > 1 and sys.argv[1] == "help": ogHelp(sys.argv[0], f"{sys.argv[0]} int_ndiskSecondStage int_partitionSecondStage [USER] [PASSWORD]", f"{sys.argv[0]} 1 1", f"{sys.argv[0]} 1 2 user clave") return # Error si no se reciben 2 parámetros. if len(sys.argv) < 3: return ogRaiseError(OG_ERR_FORMAT, f"{sys.argv[0]} int_ndiskSecondStage int_partitionSecondStage [USER] [PASSWORD]") # localizar disco segunda etapa del grub SECONDSTAGE = ogMount(int(sys.argv[1]), int(sys.argv[2])) if not SECONDSTAGE: return GRUBGFC = subprocess.run(["ls", f"{SECONDSTAGE}/{{,boot/}}" "{{grubMBR,grubPARTITION}/boot/,}}" "{{grub{,2},{,efi/}EFI/*}}/" "{{menu.lst,grub.cfg,grub.cfg.backup.og}}"], capture_output=True, text=True, shell=True).stdout.strip().split("\n") # comprobamos que exista el archivo de configuración. if not GRUBGFC: return ogRaiseError(OG_ERR_NOTFOUND, "grub.cfg") USER = sys.argv[3] if len(sys.argv) > 3 else "root" PASSWD = sys.argv[4] if len(sys.argv) > 4 else "" ENCRYPTPASSWD = subprocess.run(["echo", "-e", f"{PASSWD}\n{PASSWD}"], capture_output=True, text=True).stdout.strip().split("\n") ENCRYPTPASSWD = subprocess.run(["grub-mkpasswd-pbkdf2"], input="\n".join(ENCRYPTPASSWD), capture_output=True, text=True).stdout.strip().split("\n") ENCRYPTPASSWD = subprocess.run(["sed", "-e", "1,2d", "-e", "s/^.*grub/grub/"], input="\n".join(ENCRYPTPASSWD), capture_output=True, text=True).stdout.strip() for FILE in GRUBGFC: # Eliminamos configuración anterior subprocess.run(["sed", "-i", "-e", "/superusers/d", "-e", "/password_pbkdf2/d", FILE], check=True) # Configuramos grub.cfg para que sólo permita editar o entrar en línea de comandos al usuario especificado if PASSWD != "": subprocess.run(["sed", "-i", f"1i\\password_pbkdf2 {USER} {ENCRYPTPASSWD}", FILE], check=True) subprocess.run(["sed", "-i", f"1i\\set superusers=\"{USER}\"", FILE], check=True) # Permitimos que se seleccionen las entradas subprocess.run(["sed", "-i", "/\"menuentry \"/s/\"{\"/--unrestricted {\"/", FILE], check=True) def ogGrubSetTheme(): # Si se solicita, mostrar ayuda. if len(sys.argv) > 1 and sys.argv[1] == "help": ogHelp(sys.argv[0], f"{sys.argv[0]} int_ndiskSecondStage int_partitionSecondStage str_themeName", f"{sys.argv[0]} 1 4 ThemeBasic", f"{sys.argv[0]} $(ogFindCache) ThemeBasic") return ogBootLoaderSetTheme(*sys.argv[1:]) return def ogBurgSetTheme(): # Si se solicita, mostrar ayuda. if len(sys.argv) > 1 and sys.argv[1] == "help": ogHelp(sys.argv[0], f"{sys.argv[0]} int_ndiskSecondStage int_partitionSecondStage str_themeName", f"{sys.argv[0]} 1 4 ThemeBasic", f"{sys.argv[0]} $(ogFindCache) ThemeBasic") print("Temas disponibles:", os.listdir(f"{OGLIB}/boot/burg/themes/")) return ogBootLoaderSetTheme(*sys.argv[1:]) return def ogRefindSetTheme(): PART = None DIRTHEME = None CFGFILE = None # Si se solicita, mostrar ayuda. if len(sys.argv) > 1 and sys.argv[1] == "help": ogHelp(sys.argv[0], f"{sys.argv[0]} str_themeName", f"{sys.argv[0]} ThemeBasic") print(f"\nThemes in {OGLIB}/refind:\n{os.listdir(f'{OGLIB}/refind/themes/')}") return # Detectamos partición ESP EFIDISK, EFIPART = ogGetEsp().split() PART = ogMount(int(EFIDISK), int(EFIPART)) if not PART: return DIRTHEME = f"{PART}/EFI/refind/themes" CFGFILE = f"{PART}/EFI/refind/refind.conf" # Para utilizar ogBootLoaderSetTheme es necesario la entrada set theme_name if os.path.isfile(CFGFILE): subprocess.run(["sed", "-i", "1 i\\set theme_name=none", CFGFILE], check=True) else: return ogRaiseError(OG_ERR_NOTFOUND, CFGFILE) # Creamos el directorio para los temas if not os.path.isdir(DIRTHEME): os.makedirs(DIRTHEME) ogBootLoaderSetTheme(EFIDISK, EFIPART, *sys.argv[1:]) return def ogBootLoaderSetTheme(): # Variables locales. PART = None CFGFILE = None THEME = None NEWTHEME = None BOOTLOADER = None MSG = None NEWTHEMECFG = None # Si se solicita, mostrar ayuda. if len(sys.argv) > 1 and sys.argv[1] == "help": ogHelp(sys.argv[0], f"{sys.argv[0]} int_ndiskSecondStage int_partitionSecondStage str_themeName", f"{sys.argv[0]} 1 4 ThemeBasic", f"{sys.argv[0]} $(ogFindCache) ThemeBasic") return NEWTHEME = sys.argv[3] # Nombre de la función que llama a esta. FUNC = sys._getframe().f_back.f_code.co_name FUNC = FUNC.split()[1] # Error si no se reciben 3 parametros. if len(sys.argv) < 4: return ogRaiseError(OG_ERR_FORMAT, f"{sys.argv[0]} int_ndiskSecondStage int_partitionSecondStage str_themeName") # Error si no puede montar sistema de archivos. PART = ogMount(int(sys.argv[1]), int(sys.argv[2])) if not PART: return # La función debe ser llamada desde ogGrubSetTheme, ogBurgSetTheme or ogRefindSetTheme. if FUNC == "ogGrubSetTheme": BOOTLOADER = "grub" BOOTLOADERDIR = "boot/grubMBR" CFGFILE = f"{PART}/boot/grubMBR/boot/grub/grub.cfg" return ogRaiseError(OG_ERR_FORMAT, "ogGrubSetTheme not supported") elif FUNC == "ogBurgSetTheme": BOOTLOADER = "burg" BOOTLOADERDIR = "boot/burg" CFGFILE = f"{PART}/boot/burg/burg.cfg" elif FUNC == "ogRefindSetTheme": BOOTLOADER = "refind" BOOTLOADERDIR = "EFI/refind" CFGFILE = f"{PART}/EFI/refind/refind.conf" else: return ogRaiseError(OG_ERR_FORMAT, "Use ogGrubSetTheme, ogBurgSetTheme or ogRefindSetTheme.") # Comprobamos que exista fichero de configuración if not os.path.isfile(CFGFILE): return ogRaiseError(OG_ERR_NOTFOUND, CFGFILE) # Detectamos cual es el tema asignado with open(CFGFILE, "r") as f: lines = f.readlines() for line in lines: if line.startswith("set theme_name="): THEME = line.split("=")[1].strip() break # Si no existe entrada de theme_name nos salimos if not THEME: return ogRaiseError(OG_ERR_NOTFOUND, f"theme_name in {CFGFILE}") # Actualizamos el tema del servidor a la particion if os.path.isdir(f"{OGLIB}/{BOOTLOADER}/themes/{NEWTHEME}"): # Para refind es necesario que exista theme.conf en el directorio del tema. if BOOTLOADER == "refind": NEWTHEMECFG = f"{OGLIB}/{BOOTLOADER}/themes/{NEWTHEME}/theme.conf" if not os.path.isfile(NEWTHEMECFG): return ogRaiseError(OG_ERR_NOTFOUND, "theme.conf") with open(NEWTHEMECFG, "r") as f: theme_lines = f.readlines() with open(CFGFILE, "a") as f: for line in theme_lines: if not line.startswith("#"): f.write(line) # eliminamos "set theme" es de grub y no de refind subprocess.run(["sed", "-i", "/theme_name/d", CFGFILE], check=True) shutil.copytree(f"{OGLIB}/{BOOTLOADER}/themes/{NEWTHEME}", f"{PART}/{BOOTLOADERDIR}/themes/") # Verificamos que el tema esta en la particion if not os.path.isdir(f"{PART}/{BOOTLOADERDIR}/themes/{NEWTHEME}"): return ogRaiseError(OG_ERR_NOTFOUND, f"theme_name={NEWTHEME} in {PART}/{BOOTLOADERDIR}/themes/") # Cambiamos la entrada el fichero de configuración. subprocess.run(["sed", "-i", f"s/set theme_name={THEME}/set theme_name={NEWTHEME}/g", CFGFILE], check=True) def ogGrubSetAdminKeys(): # Si se solicita, mostrar ayuda. if len(sys.argv) > 1 and sys.argv[1] == "help": ogHelp(sys.argv[0], f"{sys.argv[0]} int_ndiskSecondStage int_partitionSecondStage str_bolean", f"{sys.argv[0]} 1 4 FALSE", f"{sys.argv[0]} $(ogFindCache) ThemeBasic") return ogBootLoaderSetAdminKeys(*sys.argv[1:]) return def ogBurgSetAdminKeys(): # Si se solicita, mostrar ayuda. if len(sys.argv) > 1 and sys.argv[1] == "help": ogHelp(sys.argv[0], f"{sys.argv[0]} int_ndiskSecondStage int_partitionSecondStage str_bolean", f"{sys.argv[0]} 1 4 TRUE", f"{sys.argv[0]} $(ogFindCache) FALSE") return ogBootLoaderSetAdminKeys(*sys.argv[1:]) return def ogBootLoaderSetAdminKeys(): # Variables locales. PART = None CFGFILE = None BOOTLOADER = None BOOTLOADERDIR = None # Si se solicita, mostrar ayuda. if len(sys.argv) > 1 and sys.argv[1] == "help": ogHelp(sys.argv[0], f"{sys.argv[0]} int_ndiskSecondStage int_partitionSecondStage str_bolean", f"{sys.argv[0]} 1 4 TRUE", f"{sys.argv[0]} $(ogFindCache) FALSE") return # Nombre de la función que llama a esta. FUNC = sys._getframe().f_back.f_code.co_name FUNC = FUNC.split()[1] # Error si no se reciben 3 parametros. if len(sys.argv) < 4: return ogRaiseError(OG_ERR_FORMAT, f"{sys.argv[0]} int_ndiskSecondStage int_partitionSecondStage str_bolean") # Error si no puede montar sistema de archivos. PART = ogMount(int(sys.argv[1]), int(sys.argv[2])) if not PART: return # La función debe ser llamada desde ogGrubSetAdminKeys or ogBurgSetAdminKeys. if FUNC == "ogGrubSetAdminKeys": BOOTLOADER = "grub" BOOTLOADERDIR = "grubMBR" CFGFILE = f"{PART}/boot/grubMBR/boot/grub/grub.cfg" return ogRaiseError(OG_ERR_FORMAT, "ogGrubSetAdminKeys not supported") elif FUNC == "ogBurgSetAdminKeys": BOOTLOADER = "burg" BOOTLOADERDIR = "burg" CFGFILE = f"{PART}/boot/burg/burg.cfg" else: return ogRaiseError(OG_ERR_FORMAT, "Use ogGrubSetAdminKeys") # Comprobamos que exista fichero de configuración if not os.path.isfile(CFGFILE): return ogRaiseError(OG_ERR_NOTFOUND, CFGFILE) if sys.argv[3].lower() == "true": shutil.move(f"{OGCAC}/boot/{BOOTLOADERDIR}/themes/conf.d/10_hotkey.disabled", f"{OGCAC}/boot/{BOOTLOADERDIR}/themes/conf.d/10_hotkey") elif sys.argv[3].lower() == "false": shutil.move(f"{OGCAC}/boot/{BOOTLOADERDIR}/themes/conf.d/10_hotkey", f"{OGCAC}/boot/{BOOTLOADERDIR}/themes/conf.d/10_hotkey.disabled") else: return ogRaiseError(OG_ERR_FORMAT, "str bolean unknown") def ogGrubSetTimeOut(): # Si se solicita, mostrar ayuda. if len(sys.argv) > 1 and sys.argv[1] == "help": ogHelp(sys.argv[0], f"{sys.argv[0]} int_ndiskSecondStage int_partitionSecondStage int_timeout_seconds", f"{sys.argv[0]} 1 4 50", f"{sys.argv[0]} $(ogFindCache) 50") return ogBootLoaderSetTimeOut(*sys.argv[1:]) return def ogBurgSetTimeOut(): # Si se solicita, mostrar ayuda. if len(sys.argv) > 1 and sys.argv[1] == "help": ogHelp(sys.argv[0], f"{sys.argv[0]} int_ndiskSecondStage int_partitionSecondStage str_timeout_seconds", f"{sys.argv[0]} 1 4 50", f"{sys.argv[0]} $(ogFindCache) 50") return ogBootLoaderSetTimeOut(*sys.argv[1:]) return def ogRefindSetTimeOut(): EFIDISK, EFIPART = ogGetEsp().split() # Si se solicita, mostrar ayuda. if len(sys.argv) > 1 and sys.argv[1] == "help": ogHelp(sys.argv[0], f"{sys.argv[0]} int_timeout_seconds", f"{sys.argv[0]} 50") return ogBootLoaderSetTimeOut(EFIDISK, EFIPART, *sys.argv[1:]) return def ogBootLoaderSetTimeOut(): # Variables locales. PART = None CFGFILE = None TIMEOUT = None BOOTLOADER = None BOOTLOADERDIR = None MSG = None # Si se solicita, mostrar ayuda. if len(sys.argv) > 1 and sys.argv[1] == "help": ogHelp(sys.argv[0], f"{sys.argv[0]} int_ndiskSecondStage int_partitionSecondStage int_timeout_seconds", f"{sys.argv[0]} 1 4 50", f"{sys.argv[0]} $(ogFindCache) 50") return # Nombre de la función que llama a esta. FUNC = sys._getframe().f_back.f_code.co_name FUNC = FUNC.split()[1] # Error si no se reciben 3 parametros. if len(sys.argv) < 4: return ogRaiseError(OG_ERR_FORMAT, f"{sys.argv[0]} int_ndiskSecondStage int_partitionSecondStage int_timeout_seconds") # Error si no puede montar sistema de archivos. PART = ogMount(int(sys.argv[1]), int(sys.argv[2])) if not PART: return # La función debe ser llamada desde ogGrubSetTimeOut, ogBurgSetTimeOut or ogRefindSetTimeOut. if FUNC == "ogGrubSetTimeOut": BOOTLOADER = "grub" BOOTLOADERDIR = "boot/grubMBR" CFGFILE = f"{PART}/boot/grubMBR/boot/grub/grub.cfg" elif FUNC == "ogBurgSetTimeOut": BOOTLOADER = "burg" BOOTLOADERDIR = "boot/burg" CFGFILE = f"{PART}/boot/burg/burg.cfg" elif FUNC == "ogRefindSetTimeOut": BOOTLOADER = "refind" BOOTLOADERDIR = "EFI/refind" CFGFILE = f"{PART}/EFI/refind/refind.conf" else: return ogRaiseError(OG_ERR_FORMAT, "Use ogGrubSetTimeOut, ogBurgSetTimeOut or ogRefindSetTimeOut.") # Comprobamos que exista fichero de configuración if not os.path.isfile(CFGFILE): return ogRaiseError(OG_ERR_NOTFOUND, CFGFILE) # Asignamos el timeOut. if BOOTLOADER == "refind": subprocess.run(["sed", "-i", f"s/timeout.*$/timeout {sys.argv[3]}/g", CFGFILE], check=True) else: subprocess.run(["sed", "-i", f"s/timeout=.*$/timeout={sys.argv[3]}/g", CFGFILE], check=True) def ogGrubSetResolution(): # Si se solicita, mostrar ayuda. if len(sys.argv) > 1 and sys.argv[1] == "help": ogHelp(sys.argv[0], f"{sys.argv[0]} int_ndiskSecondStage int_partitionSecondStage [str_resolution]", f"{sys.argv[0]} 1 4 1024x768", f"{sys.argv[0]} $(ogFindCache) 1024x768", f"{sys.argv[0]} 1 4") return ogBootLoaderSetResolution(*sys.argv[1:]) return def ogBurgSetResolution(): # Si se solicita, mostrar ayuda. if len(sys.argv) > 1 and sys.argv[1] == "help": ogHelp(sys.argv[0], f"{sys.argv[0]} int_ndiskSecondStage int_partitionSecondStage [str_resolution]", f"{sys.argv[0]} 1 4 1024x768", f"{sys.argv[0]} $(ogFindCache) 1024x768", f"{sys.argv[0]} 1 4") return ogBootLoaderSetResolution(*sys.argv[1:]) return def ogBootLoaderSetResolution(): # Variables locales. PART = None CFGFILE = None RESOLUTION = None NEWRESOLUTION = None DEFAULTRESOLUTION = "1024x768" BOOTLOADER = None BOOTLOADERDIR = None MSG = None # Si se solicita, mostrar ayuda. if len(sys.argv) > 1 and sys.argv[1] == "help": ogHelp(sys.argv[0], f"{sys.argv[0]} int_ndiskSecondStage int_partitionSecondStage [str_resolution]", f"{sys.argv[0]} 1 4 1024x768", f"{sys.argv[0]} $(ogFindCache) 1024x768", f"{sys.argv[0]} 1 4") return # Nombre de la función que llama a esta. FUNC = sys._getframe().f_back.f_code.co_name FUNC = FUNC.split()[1] # Error si no se reciben 2 parametros. if len(sys.argv) < 3: return ogRaiseError(OG_ERR_FORMAT, f"{sys.argv[0]} int_ndiskSecondStage int_partitionSecondStage [str_resolution]") # Error si no puede montar sistema de archivos. PART = ogMount(int(sys.argv[1]), int(sys.argv[2])) if not PART: return # La función debe ser llamada desde ogGrubSetResolution, ogBurgSetResolution or ogRefindSetResolution. if FUNC == "ogGrubSetResolution": BOOTLOADER = "grub" BOOTLOADERDIR = "boot/grubMBR" CFGFILE = f"{PART}/boot/grubMBR/boot/grub/grub.cfg" return ogRaiseError(OG_ERR_FORMAT, "ogGrubSetResolution not supported") elif FUNC == "ogBurgSetResolution": BOOTLOADER = "burg" BOOTLOADERDIR = "boot/burg" CFGFILE = f"{PART}/boot/burg/burg.cfg" else: return ogRaiseError(OG_ERR_FORMAT, "Use ogGrubSetResolution, ogBurgSetResolution or ogRefindSetResolution.") DEFAULTRESOLUTION = "1024x768" # Comprobamos que exista fichero de configuración if not os.path.isfile(CFGFILE): return ogRaiseError(OG_ERR_NOTFOUND, CFGFILE) # Controlar variable a considerar vga (default template) o video (menu) # Si solo dos parametros autoconfiguracion basado en el parametro vga de las propiedad menu. si no hay menu asignado es 788 por defecto if len(sys.argv) == 3: if "video" in globals() and video: NEWRESOLUTION = video.split(":")[1].split("-")[0] if "vga" in globals() and vga: if vga in ["788", "789", "814"]: NEWRESOLUTION = "800x600" elif vga in ["791", "792", "824"]: NEWRESOLUTION = "1024x768" elif vga == "355": NEWRESOLUTION = "1152x864" elif vga in ["794", "795", "829"]: NEWRESOLUTION = "1280x1024" elif len(sys.argv) == 4: # Comprobamos que el parametro 3 cumple formato NNNNxNNNN if re.match(r"[0-9]{3,4}[x][0-9]{3,4}$", sys.argv[3]): NEWRESOLUTION = sys.argv[3] else: return ogRaiseError(OG_ERR_FORMAT, "param 3 is not a valid resolution: 800x600, 1024x768, 1152x864, 1280x1024, 1600x1200") # Si no existe NEWRESOLUTION asignamos la DEFAULTRESOLUTION if not NEWRESOLUTION: NEWRESOLUTION = DEFAULTRESOLUTION # Cambiamos la entrada el fichero de configuración. subprocess.run(["sed", "-i", f"s/gfxmode=.*$/gfxmode={NEWRESOLUTION}/g", CFGFILE], check=True) def ogRefindSetResolution(): # Variables locales. PART = None CFGFILE = None # Si se solicita, mostrar ayuda. if len(sys.argv) > 1 and sys.argv[1] == "help": ogHelp(sys.argv[0], f"{sys.argv[0]} int_resolution1 [int_resolution2]", f"{sys.argv[0]} 1366 768", f"{sys.argv[0]} 1") return # Error si no se reciben 2 parametros. if len(sys.argv) < 2: return ogRaiseError(OG_ERR_FORMAT, f"{sys.argv[0]} int_resolution1 [int_resolution2]") # Error si no puede montar sistema de archivos. PART = ogMount(ogGetEsp()) if not PART: return # Comprobamos que exista fichero de configuración CFGFILE = f"{PART}/EFI/refind/refind.conf" if not os.path.isfile(CFGFILE): return ogRaiseError(OG_ERR_NOTFOUND, CFGFILE) # Borramos resolucion anterior y configuramos la nueva subprocess.run(["sed", "-i", "/^resolution/d", CFGFILE], check=True) subprocess.run(["sed", "-i", f"1 i\\resolution {sys.argv[1]} {sys.argv[2]}", CFGFILE], check=True) def ogRefindInstall(bool_autoconfig): # Variables locales. CONFIG = bool_autoconfig EFIDISK, EFIPART = ogGetEsp().split() EFIDEVICE = ogDiskToDev(EFIDISK, EFIPART) EFIMNT = ogMount(EFIDISK, EFIPART) EFIDIR = f"{EFIMNT}/EFI" SHIM = ogGetPath("/usr/lib/shim/shimx64.efi.signed") # Si se solicita, mostrar ayuda. if CONFIG == "help": ogHelp("ogRefindInstall", "ogRefindInstall boolean_autoconfig", "ogRefindInstall TRUE") return # Error si no se reciben 2 parametros. if not bool_autoconfig: ogRaiseError(OG_ERR_FORMAT, "ogRefindInstall boolean_autoconfig") return # Error si no puede montar sistema de archivos. if not EFIMNT: ogRaiseError(OG_ERR_PARTITION, "mount ESP") return # Comprobamos que exista shimx64 if not SHIM: ogRaiseError(OG_ERR_NOTFOUND, "shimx64.efi.signed") return # Si existe configuración anterior de refind la borro if os.path.isdir(f"{EFIDIR}/refind"): shutil.rmtree(f"{EFIDIR}/refind") # Instalamos rEFInd. subprocess.run(["refind-install", "--yes", "--alldrivers", "--root", EFIMNT, "--shim", SHIM]) # Firmo refind con certificado de OpenGnsys shutil.move(f"{EFIDIR}/refind/grubx64.efi", f"{EFIDIR}/refind/grubx64.efi-unsigned") subprocess.run(["sbsign", "--key", f"{OGETC}/ssl/private/opengnsys.key", "--cert", f"{OGETC}/ssl/certs/opengnsys.crt", "--output", f"{EFIDIR}/refind/grubx64.efi", f"{EFIDIR}/refind/grubx64.efi-unsigned"]) # Copio los certificados shutil.copytree("/etc/refind.d/keys", f"{EFIDIR}/refind/keys") # Copio certificado opengnsys shutil.copy(f"{OGETC}/ssl/certs/opengnsys.*", f"{EFIDIR}/refind/keys") # Ponemos la entrada en NVRAM en el segundo lugar del orden de arranque NEWORDER = ogNvramGetOrder().split(",") NEWORDER[0], NEWORDER[1] = NEWORDER[1], NEWORDER[0] ogNvramSetOrder(",".join(NEWORDER)) # Borramos configuración linux if os.path.isfile(f"{EFIMNT}/boot/refind_linux.conf"): shutil.move(f"{EFIMNT}/boot/refind_linux.conf", f"{EFIMNT}/boot/refind_linux.conf.ogbackup") # Eliminamos punto de montaje (por si ejecutamos más de una vez) subprocess.run(["umount", f"{EFIMNT}/boot/efi"]) # Para la configuración del ogLive ogMountCache() if ogMountCache() == 0: # Detectamos si hay ogLive CACHEDEVICE = ogDiskToDev(ogFindCache()) OGLIVE = glob.glob(f"{OGCAC}/boot/ogvmlinuz*")[0] # Obtenemos parametros del kernel y sustituimos root # La línea de opciones no puede contener la cadena initrd. CMDLINE = " ".join(sys.argv[3:]) CMDLINE = f"root={CACHEDEVICE} {CMDLINE.replace('ogvmlinuz', '')}" # Icono para la entrada de menú OGICON = glob.glob(f"{OGLIB}/refind/icons/so_opengnsys.png") OGICON = OGICON[0] if OGICON else f"{EFIDIR}/refind/icons/os_unknown.png" shutil.copy(OGICON, f"{OGCAC}/.VolumeIcon.png") # Configuramos rEFInd si es necesario CFGFILE = f"{EFIDIR}/refind/refind.conf" if CONFIG == "TRUE": with open(CFGFILE, "a") as f: f.write("\n\n# Configuración OpenGnsys\n") # Excluimos dispositivos distintos de ESP y CACHE DEVICES = subprocess.run(["blkid", "-s", "PARTUUID"], capture_output=True, text=True).stdout DEVICES = DEVICES.split("\n") DEVICES = [device.split("=")[1].replace('"', '') for device in DEVICES if device] DEVICES = [device for device in DEVICES if device != EFIDEVICE and device != CACHEDEVICE] DEVICES = " ".join(DEVICES) f.write(f"dont_scan_volumes {DEVICES}\n") # Excluimos en la ESP los directorios de los sistemas operativos f.write("dont_scan_dirs EFI/microsoft,EFI/ubuntu,EFI/grub\n") f.write("use_graphics_for osx,linux,windows\n") f.write("showtools reboot, shutdown\n") # Configuramos ogLive if OGLIVE: # Cambiamos nombre de kernel e initrd para que lo detecte refind OGLIVEDIR = os.path.dirname(OGLIVE) shutil.copy(OGLIVE, f"{OGLIVE}.efi") shutil.copy(f"{OGLIVEDIR}/oginitrd.img", f"{OGLIVEDIR}/initrd.img") # Incluimos el directorio de ogLive. with open(CFGFILE, "a") as f: f.write(f"also_scan_dirs +,boot/{os.path.basename(OGLIVEDIR)}\n") # Fichero de configuración de refind para kernel de linux. LNXCFGFILE = f"{OGLIVEDIR}/refind_linux.conf" with open(LNXCFGFILE, "w") as f: f.write(f"\"OpenGnsys Live\" \"{CMDLINE}\"\n") # Ponemos ogLive como la entrada por defecto NUMENTRY = len(glob.glob(f"{EFIDIR}/Part-??-??")) with open(CFGFILE, "a") as f: f.write(f"default_selection {NUMENTRY+1}\n") else: # Renombramos la configuración por defecto shutil.move(CFGFILE, f"{CFGFILE}.auto") # Creamos nueva configuración with open(CFGFILE, "w") as f: f.write("# Configuración OpenGnsys\n") f.write("timeout 20\n") f.write("showtools reboot, shutdown\n") f.write("\nscanfor manual\n") # Configuración para sistemas restaurados con OpenGnsys for DIR in glob.glob("/mnt/sda1/EFI/Part-*-*"): DIRNAME = os.path.basename(DIR) f.write(f"menuentry \"{DIRNAME}\" {{\n") f.write(f" loader /EFI/{DIRNAME}/Boot/ogloader.efi\n") if os.path.isfile(f"{DIR}/Boot/bootmgfw.efi"): f.write(" icon /EFI/refind/icons/os_win8.png\n") if os.path.isfile(f"{DIR}/Boot/grubx64.efi"): f.write(" icon /EFI/refind/icons/os_linux.png\n") f.write("}\n") # Configuración ogLive si secureboot no está activado if "secureboot" not in subprocess.run(["dmesg"], capture_output=True, text=True).stdout: if OGLIVE: f.write("menuentry \"OpenGnsys Live\" {\n") f.write(" volume CACHE\n") f.write(" ostype Linux\n") f.write(f" loader /boot/{os.path.basename(os.path.dirname(OGLIVE))}/ogvmlinuz\n") f.write(f" initrd /boot/{os.path.basename(os.path.dirname(OGLIVE))}/oginitrd.img\n") f.write(f" options \"{CMDLINE}\"\n") f.write("}\n") # Ponemos ogLive como la entrada por defecto subprocess.run(["sed", "-i", "1 i\default_selection \"OpenGnsys Live\"", CFGFILE], check=True) def ogGrub4dosInstallMbr(): # Variables locales. DISK = None PART = None DEVICE = None MOUNTDISK = None GRUBDISK = None BINBDIR = None # Si se solicita, mostrar ayuda. if len(sys.argv) > 1 and sys.argv[1] == "help": ogHelp(sys.argv[0], f"{sys.argv[0]} int_ndisk int_part", f"{sys.argv[0]} 1 1") return # Error si no se recibe 2 parámetros. if len(sys.argv) < 3: return ogRaiseError(OG_ERR_FORMAT, f"{sys.argv[0]} int_ndisk int_part") DISK = sys.argv[1] PART = sys.argv[2] # Controlar existencia de disco y particion DEVICE = ogDiskToDev(DISK) if not DEVICE: return ogRaiseError(OG_ERR_NOTFOUND) MOUNTDISK = ogMount(DISK, PART) if not MOUNTDISK: return ogRaiseError(OG_ERR_PARTITION) # Controlar acceso de escritura a la particion if ogIsReadonly(DISK, PART): return ogRaiseError(OG_ERR_NOTWRITE, f": {DISK} {PART}") # Controlar disco no uefi if ogIsEfiActive(): return ogRaiseError(OG_ERR_NOTBIOS, ": grub4dos solo soporta PC con bios legacy") # Controlar particionado tipo msdos if not ogCheckStringInGroup(ogGetPartitionTableType(DISK), "MSDOS"): return ogRaiseError(OG_ERR_NOMSDOS, ": grub2dos requiere particionado tipo MSDOS") # Controlar la existencia del grub4dos con acceso a ntfs BINDIR = f"{OGLIB}/grub4dos/grub4dos-0.4.6a" if not os.path.isfile(f"{BINDIR}/bootlace.com"): return ogRaiseError(OG_ERR_NOTFOUND, f": {BINDIR}/bootlace.com") # instalar el bootloader de grlrd en el MBR subprocess.run([f"{BINDIR}/bootlace64.com", DEVICE], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) # copiar grld a la particion shutil.copy(f"{BINDIR}/grldr", MOUNTDISK) # Instalar y configurar grub4dos if os.path.isfile(f"{MOUNTDISK}/boot/grub/menu.lst"): os.remove(f"{MOUNTDISK}/boot/grub/menu.lst") os.rmdir(f"{MOUNTDISK}/boot/grub") if not os.path.isfile(f"{MOUNTDISK}/boot/grub/menu.lst"): os.makedirs(f"{MOUNTDISK}/boot/grub") with open(f"{MOUNTDISK}/boot/grub/menu.lst", "w") as f: GRUBDISK = int(DISK) - 1 f.write(f"##NO-TOCAR-ESTA-LINEA MBR\n") f.write(f"timeout 0\n") f.write(f"title MBR\n") f.write(f"root (hd{GRUBDISK},0)\n") f.write(f"chainloader (hd{GRUBDISK},0)+1\n") f.write(f"boot\n")