source: client/engine/BootLib.py @ 5b1449d

ogClonningEnginetest-python-scriptsticket-693ticket-700
Last change on this file since 5b1449d was af9a1d9, checked in by Antonio Emmanuel Guerrero Silva <aguerrero@…>, 8 months ago

refs #585 Libraries convert to Python3

  • Property mode set to 100644
File size: 96.7 KB
Line 
1import os
2import sys
3import shutil
4import subprocess
5import uuid
6
7from engine.InventoryLib import *
8from engine.SystemLib import *
9from engine.UEFILib import *
10
11
12def ogBoot():
13    FUNCNAME = ogBoot.__name__
14    # Variables locales.
15    PART = None
16    TYPE = None
17    MNTDIR = None
18    PARAMS = None
19    KERNEL = None
20    INITRD = None
21    APPEND = None
22    FILE = None
23    LOADER = None
24    f = None
25    NVRAMPERM = None
26    EFIDISK = None
27    EFIPART = None
28    EFIDIR = None
29    BOOTLABEL = None
30    BOOTLOADER = None
31    BOOTNO = None
32    DIRGRUB = None
33    b = None
34
35    # Si se solicita, mostrar ayuda.
36    if len(sys.argv) > 1 and sys.argv[1] == "help":
37        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")
38        return
39
40    # Error si no se reciben 2 o 3 parámetros.
41    if len(sys.argv) != 3 and len(sys.argv) != 4 and len(sys.argv) != 5:
42        ogRaiseError(OG_ERR_FORMAT)
43        return
44
45    # Detectar tipo de sistema de archivos y montarlo.
46    PART = ogDiskToDev(int(sys.argv[1]), int(sys.argv[2]))
47    if PART is None:
48        return
49    TYPE = ogGetOsType(int(sys.argv[1]), int(sys.argv[2]))
50    if TYPE is None:
51        return
52    # Error si no puede montar sistema de archivos.
53    MNTDIR = ogMount(int(sys.argv[1]), int(sys.argv[2]))
54    if MNTDIR is None:
55        return
56    if len(sys.argv) == 5 and sys.argv[4].upper() == "NVRAMPERM":
57        NVRAMPERM = True
58    else:
59        NVRAMPERM = False
60        PARAMS = sys.argv[4] if len(sys.argv) == 5 else sys.argv[3]
61
62    if TYPE in ["Linux", "Android"]:
63        # Si no se indican, obtiene los parámetros de arranque para Linux.
64        PARAMS = PARAMS or ogLinuxBootParameters(int(sys.argv[1]), int(sys.argv[2]))
65        # Si no existe y el UEFI buscar en particion ESP
66        if not PARAMS and ogIsEfiActive():
67            PARAMS = ogLinuxBootParameters(ogGetEsp())
68        # Si no existe, buscar sistema de archivo /boot en /etc/fstab.
69        if not PARAMS and os.path.exists(os.path.join(MNTDIR, "etc/fstab")):
70            # Localizar S.F. /boot en /etc/fstab del S.F. actual.
71            PART = ogDevToDisk(subprocess.check_output(["awk", '$1!="#" && $2=="/boot" {print $1}', os.path.join(MNTDIR, "etc/fstab")]).decode().strip())
72            # Montar S.F. de /boot.
73            MNTDIR = ogMount(PART)
74            if MNTDIR is None:
75                return
76            # Buscar los datos de arranque.
77            PARAMS = ogLinuxBootParameters(PART)
78            if PARAMS is None:
79                return
80        KERNEL, INITRD, APPEND = PARAMS.split() if PARAMS else (None, None, None)
81        # Si no hay kernel, no hay sistema operativo.
82        if not KERNEL or not os.path.exists(os.path.join(MNTDIR, KERNEL)):
83            ogRaiseError(OG_ERR_NOTOS, sys.argv[1], sys.argv[2], TYPE)
84            return
85        # Arrancar de partición distinta a la original.
86        if os.path.exists(os.path.join(MNTDIR, "etc")):
87            APPEND = APPEND.replace("root=[-+=_/a-zA-Z0-9]* ", "root={} ".format(PART))
88        # Comprobar tipo de sistema.
89        if ogIsEfiActive():
90            # Comprobar si el Kernel está firmado.
91            if not subprocess.check_output(["file", "-k", os.path.join(MNTDIR, KERNEL)]).decode().strip().startswith("EFI app"):
92                ogRaiseError(OG_ERR_NOTOS, sys.argv[1], sys.argv[2], TYPE, "EFI")
93                return
94
95            BOOTLABEL = "Part-{:02d}-{:02d}".format(int(sys.argv[1]), int(sys.argv[2]))
96            BOOTLOADER = "shimx64.efi"
97            # Obtener parcición EFI.
98            EFIDISK, EFIPART = ogGetEsp()
99            # TODO: Comprobamos que existe la BOOTLABEL, si no buscamos por sistema operativo
100            if not ogGetPath(EFIDISK, EFIPART, "EFI/{}".format(BOOTLABEL)):
101                OSVERSION = ogGetOsVersion(int(sys.argv[1]), int(sys.argv[2]))
102                if OSVERSION:
103                    if "SUSE" in OSVERSION:
104                        BOOTLABEL = "opensuse"
105                    elif "Fedora" in OSVERSION:
106                        BOOTLABEL = "fedora"
107                    elif "Ubuntu" in OSVERSION:
108                        BOOTLABEL = "ubuntu"
109                    else:
110                        ogRaiseError(OG_ERR_NOTFOUND, EFIDISK, EFIPART, "Boot loader")
111                        return
112
113            # Crear orden de arranque (con unos valores por defecto).
114            ogNvramAddEntry(BOOTLABEL, "/EFI/{}/Boot/{}".format(BOOTLABEL, BOOTLOADER), NVRAMPERM)
115            # Marcar próximo arranque y reiniciar.
116            ogNvramSetNext(BOOTLABEL)
117            reboot()
118        else:
119            # Arranque BIOS: configurar kernel Linux con los parámetros leídos de su GRUB.
120            subprocess.call(["kexec", "-l", os.path.join(MNTDIR, KERNEL), "--append={}".format(APPEND), "--initrd={}".format(os.path.join(MNTDIR, INITRD))])
121            subprocess.call(["kexec", "-e"])
122    elif TYPE == "Windows":
123        # Comprobar tipo de sistema.
124        if ogIsEfiActive():
125            BOOTLABEL = "Part-{:02d}-{:02d}".format(int(sys.argv[1]), int(sys.argv[2]))
126            # Obtener parcición EFI.
127            EFIDISK, EFIPART = ogGetEsp()
128            if not EFIPART:
129                ogRaiseError(OG_ERR_PARTITION, "ESP")
130                return
131            EFIDIR = ogMount(EFIDISK, EFIPART)
132            if EFIDIR is None:
133                return
134            # Comprobar cargador (si no existe buscar por defecto en ESP).
135            LOADER = ogGetPath(os.path.join(EFIDIR, "EFI", BOOTLABEL, "Boot/bootmgfw.efi"))
136            if not LOADER:
137                BOOTLABEL = "Microsoft"
138                LOADER = ogGetPath(os.path.join(EFIDIR, "EFI", "Microsoft/Boot/bootmgfw.efi"))
139            if not LOADER:
140                ogRaiseError(OG_ERR_NOTOS, sys.argv[1], sys.argv[2], TYPE, "EFI")
141                return
142
143            # Crear orden de arranque (con unos valores por defecto).
144            ogNvramAddEntry(BOOTLABEL, "/EFI{}".format(LOADER[LOADER.find("EFI"):]), NVRAMPERM)
145            # Marcar próximo arranque y reiniciar.
146            ogNvramSetNext(BOOTLABEL)
147            reboot()
148        else:
149            # Arranque BIOS: comprueba si hay un cargador de Windows.
150            for f in ["io.sys", "ntldr", "bootmgr"]:
151                FILE = ogGetPath(int(sys.argv[1]), int(sys.argv[2]), f)
152                if FILE:
153                    LOADER = f
154            if not LOADER:
155                ogRaiseError(OG_ERR_NOTOS, sys.argv[1], sys.argv[2], TYPE)
156                return
157            if winboot == "kexec":
158                # Modo de arranque en caliente (con kexec).
159                shutil.copy(os.path.join(OGLIB, "grub4dos/*"), MNTDIR)  # */ (Comentario Doxygen)
160                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)])
161                subprocess.call(["kexec", "-e"])
162            else:
163                # Modo de arranque por reinicio (con reboot).
164                with open(os.path.join(MNTDIR, "ogboot.me"), "wb") as f:
165                    f.write(b"\x00" * 1024 * 3)
166                with open(os.path.join(MNTDIR, "ogboot.firstboot"), "wb") as f:
167                    f.write(b"\x00" * 1024 * 3)
168                with open(os.path.join(MNTDIR, "ogboot.secondboot"), "wb") as f:
169                    f.write(b"\x00" * 1024 * 3)
170                if not ogGetRegistryValue(MNTDIR, "SOFTWARE", "\\Microsoft\\Windows\\CurrentVersion\\Run\\ogcleannboot"):
171                    ogAddRegistryValue(MNTDIR, "SOFTWARE", "\\Microsoft\\Windows\\CurrentVersion\\Run\\ogcleanboot")
172                    ogSetRegistryValue(MNTDIR, "SOFTWARE", "\\Microsoft\\Windows\\CurrentVersion\\Run\\ogcleanboot", "cmd /c del c:\\ogboot.*")
173                # Activar la partición.
174                ogSetPartitionActive(int(sys.argv[1]), int(sys.argv[2]))
175                reboot()
176    elif TYPE == "MacOS":
177        # Modo de arranque por reinicio.
178        # Nota: el cliente tiene que tener configurado correctamente Grub.
179        open(os.path.join(MNTDIR, "boot.mac"), "w").close()
180        reboot()
181    elif TYPE == "GrubLoader":
182        # Reiniciar.
183        #reboot()
184        pass
185    else:
186        ogRaiseError(OG_ERR_NOTOS, sys.argv[1], sys.argv[2], TYPE)
187        return
188   
189def ogGetWindowsName():
190    FUNCNAME = ogGetWindowsName.__name__
191    # Variables locales.
192    MNTDIR = None
193
194    # Si se solicita, mostrar ayuda.
195    if len(sys.argv) > 1 and sys.argv[1] == "help":
196        ogHelp(FUNCNAME, FUNCNAME + " int_ndisk int_npartition", FUNCNAME + " 1 1  ==>  PRACTICA-PC")
197        return
198
199    # Error si no se reciben 2 parámetros.
200    if len(sys.argv) != 3:
201        ogRaiseError(OG_ERR_FORMAT)
202        return
203
204    # Montar el sistema de archivos.
205    MNTDIR = ogMount(int(sys.argv[1]), int(sys.argv[2]))
206    if MNTDIR is None:
207        return
208
209    # Obtener dato del valor de registro.
210    ogGetRegistryValue(MNTDIR, "system", "\\ControlSet001\\Control\\ComputerName\\ComputerName\\ComputerName")
211
212def ogLinuxBootParameters(ndisk, nfilesys):
213    FUNCNAME = ogLinuxBootParameters.__name__
214    # Variables locales.
215    MNTDIR = None
216    CONFDIR = None
217    CONFFILE = None
218    f = None
219
220    # Si se solicita, mostrar ayuda.
221    if len(sys.argv) > 1 and sys.argv[1] == "help":
222        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")
223        return
224
225    # Error si no se reciben 2 parámetros.
226    if len(sys.argv) != 3:
227        ogRaiseError(OG_ERR_FORMAT)
228        return
229
230    # Detectar id. de tipo de partición y codificar al mnemonico.
231    MNTDIR = ogMount(int(sys.argv[1]), int(sys.argv[2]))
232    if MNTDIR is None:
233        return
234
235    # Fichero de configuración de GRUB.
236    CONFDIR = MNTDIR  # Sistema de archivos de arranque (/boot).
237    if os.path.isdir(os.path.join(MNTDIR, "boot")):
238        CONFDIR = os.path.join(MNTDIR, "boot")  # Sist. archivos raíz con directorio boot.
239    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")]:
240        if os.path.isfile(f):
241            CONFFILE = f
242            break
243    if CONFFILE is None:
244        ogRaiseError(OG_ERR_NOTFOUND, "grub.cfg")
245        return
246
247    # Toma del fichero de configuracion los valores del kernel, initrd
248    # y parámetros de arranque usando las cláusulas por defecto
249    # ("default" en GRUB1, "set default" en GRUB2)
250    # y los formatea para que sean compatibles con \c kexec .
251    awk_script = r'''
252    BEGIN {cont=-1;}
253    $1~/^default$/     {sub(/=/," "); def=$2;}
254    $1~/^set$/ && $2~/^default/ { gsub(/[="]/," "); def=$3;
255                                    if (def ~ /saved_entry/) def=0;
256                                }
257    $1~/^(title|menuentry)$/ {cont++}
258    $1~/^set$/ && $2~/^root=.\(hd'$[1-1]',(msdos|gpt)'$2'\).$/ { if (def==0) def=cont; }
259    $1~/^(kernel|linux(16|efi)?)$/ { if (def==cont) {
260                                        kern=$2;
261                                        sub($1,""); sub($1,""); sub(/^[ \t]*/,""); app=$0
262                                        }
263                                    }
264    $1~/^initrd(16|efi)?$/ {if (def==cont) init=$2}
265    END {if (kern!="") printf("%s %s %s", kern,init,app)}
266    '''
267    awk_command = ["awk", awk_script, CONFFILE]
268    output = subprocess.check_output(awk_command).decode().strip()
269    return output
270
271def ogGetLinuxBootParameters(ndisk, nfilesys):
272    FUNCNAME = ogGetLinuxBootParameters.__name__
273    # Variables locales.
274    MNTDIR = None
275    CONFDIR = None
276    CONFFILE = None
277    f = None
278
279    # Si se solicita, mostrar ayuda.
280    if len(sys.argv) > 1 and sys.argv[1] == "help":
281        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")
282        return
283
284    # Error si no se reciben 2 parámetros.
285    if len(sys.argv) != 3:
286        ogRaiseError(OG_ERR_FORMAT)
287        return
288
289    # Detectar id. de tipo de partición y codificar al mnemonico.
290    MNTDIR = ogMount(int(sys.argv[1]), int(sys.argv[2]))
291    if MNTDIR is None:
292        return
293
294    # Fichero de configuración de GRUB.
295    CONFDIR = MNTDIR  # Sistema de archivos de arranque (/boot).
296    if os.path.isdir(os.path.join(MNTDIR, "boot")):
297        CONFDIR = os.path.join(MNTDIR, "boot")  # Sist. archivos raíz con directorio boot.
298    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")]:
299        if os.path.isfile(f):
300            CONFFILE = f
301            break
302    if CONFFILE is None:
303        ogRaiseError(OG_ERR_NOTFOUND, "grub.cfg")
304        return
305
306    # Toma del fichero de configuracion los valores del kernel, initrd
307    # y parámetros de arranque usando las cláusulas por defecto
308    # ("default" en GRUB1, "set default" en GRUB2)
309    # y los formatea para que sean compatibles con \c kexec .
310    awk_script = r'''
311    BEGIN {cont=-1;}
312    $1~/^default$/     {sub(/=/," "); def=$2;}
313    $1~/^set$/ && $2~/^default/ { gsub(/[="]/," "); def=$3;
314                                    if (def ~ /saved_entry/) def=0;
315                                }
316    $1~/^(title|menuentry)$/ {cont++}
317    $1~/^set$/ && $2~/^root=.\(hd'$[1-1]',(msdos|gpt)'$2'\).$/ { if (def==0) def=cont; }
318    $1~/^(kernel|linux(16|efi)?)$/ { if (def==cont) {
319                                        kern=$2;
320                                        sub($1,""); sub($1,""); sub(/^[ \t]*/,""); app=$0
321                                        }
322                                    }
323    $1~/^initrd(16|efi)?$/ {if (def==cont) init=$2}
324    END {if (kern!="") printf("%s %s %s", kern,init,app)}
325    '''
326    awk_command = ["awk", awk_script, CONFFILE]
327    output = subprocess.check_output(awk_command).decode().strip()
328    return output
329
330def ogSetWindowsName():
331    FUNCNAME = ogSetWindowsName.__name__
332    # Variables locales.
333    PART = None
334    MNTDIR = None
335    NAME = None
336
337    # Si se solicita, mostrar ayuda.
338    if len(sys.argv) > 1 and sys.argv[1] == "help":
339        ogHelp(FUNCNAME, FUNCNAME + " int_ndisk int_filesys str_name", FUNCNAME + " 1 1 PRACTICA-PC")
340        return
341
342    # Error si no se reciben 3 parámetros.
343    if len(sys.argv) != 4:
344        ogRaiseError(OG_ERR_FORMAT)
345        return
346
347    # Error si el nombre supera los 15 caracteres.
348    if len(sys.argv[3]) > 15:
349        ogRaiseError(OG_ERR_OUTOFLIMIT, sys.argv[3][:15] + "...")
350        return
351
352    # Montar el sistema de archivos.
353    MNTDIR = ogMount(int(sys.argv[1]), int(sys.argv[2]))
354    if MNTDIR is None:
355        return
356
357    # Asignar nombre.
358    NAME = sys.argv[3]
359
360    # Modificar datos de los valores de registro.
361    ogSetRegistryValue(MNTDIR, "system", "\\ControlSet001\\Control\\ComputerName\\ComputerName\\ComputerName", NAME)
362    ogSetRegistryValue(MNTDIR, "system", "\\ControlSet001\\Services\\Tcpip\\Parameters\\Hostname", NAME)
363    ogSetRegistryValue(MNTDIR, "system", "\\ControlSet001\\Services\\Tcpip\\Parameters\\HostName", NAME)
364    ogSetRegistryValue(MNTDIR, "system", "\\ControlSet001\\services\\Tcpip\\Parameters\\Hostname", NAME)
365    ogSetRegistryValue(MNTDIR, "system", "\\ControlSet001\\Services\\Tcpip\\Parameters\\NV Hostname", NAME)
366    ogSetRegistryValue(MNTDIR, "system", "\\ControlSet001\\Services\\Tcpip\\Parameters\\NV HostName", NAME)
367    ogSetRegistryValue(MNTDIR, "system", "\\ControlSet001\\services\\Tcpip\\Parameters\\NV Hostname", NAME)
368
369def ogSetWinlogonUser():
370    FUNCNAME = ogSetWinlogonUser.__name__
371    # Variables locales.
372    PART = None
373    MNTDIR = None
374    NAME = None
375
376    # Si se solicita, mostrar ayuda.
377    if len(sys.argv) > 1 and sys.argv[1] == "help":
378        ogHelp(FUNCNAME, FUNCNAME + " int_ndisk int_npartition str_username", FUNCNAME + " 1 1 USUARIO")
379        return
380
381    # Error si no se reciben 3 parámetros.
382    if len(sys.argv) != 4:
383        ogRaiseError(OG_ERR_FORMAT)
384        return
385
386    # Montar el sistema de archivos.
387    MNTDIR = ogMount(int(sys.argv[1]), int(sys.argv[2]))
388    if MNTDIR is None:
389        return
390
391    # Asignar nombre.
392    NAME = sys.argv[3]
393
394    # Modificar datos en el registro.
395    ogSetRegistryValue(MNTDIR, "SOFTWARE", "\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\DefaultUserName", NAME)
396
397def ogBootMbrXP():
398    FUNCNAME = ogBootMbrXP.__name__
399    # Variables locales.
400    DISK = None
401
402    # Si se solicita, mostrar ayuda.
403    if len(sys.argv) > 1 and sys.argv[1] == "help":
404        ogHelp(FUNCNAME, FUNCNAME + " int_ndisk ", FUNCNAME + " 1")
405        return
406
407    # Error si no se recibe 1 parámetro.
408    if len(sys.argv) != 2:
409        ogRaiseError(OG_ERR_FORMAT)
410        return
411
412    DISK = ogDiskToDev(int(sys.argv[1]))
413    if DISK is None:
414        return
415    subprocess.call(["ms-sys", "-z", "-f", DISK])
416    subprocess.call(["ms-sys", "-m", "-f", DISK])
417
418def ogBootMbrGeneric():
419    FUNCNAME = ogBootMbrGeneric.__name__
420    # Variables locales.
421    DISK = None
422
423    # Si se solicita, mostrar ayuda.
424    if len(sys.argv) > 1 and sys.argv[1] == "help":
425        ogHelp(FUNCNAME, FUNCNAME + " int_ndisk ", FUNCNAME + " 1")
426        return
427
428    # Error si no se recibe 1 parámetro.
429    if len(sys.argv) != 2:
430        ogRaiseError(OG_ERR_FORMAT)
431        return
432
433    DISK = ogDiskToDev(int(sys.argv[1]))
434    if DISK is None:
435        return
436    subprocess.call(["ms-sys", "-z", "-f", DISK])
437    subprocess.call(["ms-sys", "-s", "-f", DISK])
438
439    # Firma necesaria para Windows equipos UEFI
440    SIGNATURE = "0x" + str(uuid.uuid4()).split('-')[0]
441    subprocess.call(["ms-sys", "-S", SIGNATURE, DISK])
442
443def ogFixBootSector():
444    FUNCNAME = ogFixBootSector.__name__
445    # Variables locales.
446    PARTYPE = None
447    DISK = None
448    PART = None
449    FILE = None
450
451    # Si se solicita, mostrar ayuda.
452    if len(sys.argv) > 1 and sys.argv[1] == "help":
453        ogHelp(FUNCNAME, FUNCNAME + " int_ndisk int_partition ", FUNCNAME + " 1 1 ")
454        return
455
456    # Error si no se reciben 2 parámetros.
457    if len(sys.argv) != 3:
458        ogRaiseError(OG_ERR_FORMAT)
459        return
460
461    # TODO, solo si la particion existe
462    # TODO, solo si es ntfs o fat
463    PARTYPE = ogGetPartitionId(int(sys.argv[1]), int(sys.argv[2]))
464    if PARTYPE not in [1, 4, 6, 7, 11, 12, 14, 15, 23, 1792, 61440, 61440]:
465        ogRaiseError(OG_ERR_PARTITION)
466        return
467
468    ogUnmount(int(sys.argv[1]), int(sys.argv[2])) or ogRaiseError(OG_ERR_PARTITION)
469
470    # Preparando instruccion
471    DISK = int(sys.argv[1]) - 1
472    PART = int(sys.argv[2])
473    FILE = "/tmp/temp$$"
474    with open(FILE, "w") as f:
475        f.write(f"disk={DISK}\nmain_part={PART}\nfix_first_sector=yes\n")
476
477    subprocess.run(["timeout", "--foreground", "--signal=SIGKILL", "5s", "spartlnx.run", "-cui", "-nm", "-a", "-f", FILE])
478    os.remove(FILE)
479
480def ogGetBootMbr():
481    FUNCNAME = ogGetBootMbr.__name__
482    # Variables locales.
483    DISK = None
484
485    # Si se solicita, mostrar ayuda.
486    if len(sys.argv) > 1 and sys.argv[1] == "help":
487        ogHelp(FUNCNAME, FUNCNAME + " int_ndisk ", FUNCNAME + " 1")
488        return
489
490    # Error si no se recibe 1 parámetro.
491    if len(sys.argv) != 2:
492        ogRaiseError(OG_ERR_FORMAT)
493        return
494
495    DISK = ogDiskToDev(int(sys.argv[1]))
496    if DISK is None:
497        return
498    subprocess.call(["ms-sys", "-f", DISK])
499
500def ogWindowsBootParameters():
501    FUNCNAME = ogWindowsBootParameters.__name__
502    # Variables locales.
503    PART = None
504    DISK = None
505    BOOTLABEL = None
506    BCDFILE = None
507    BOOTDISK = None
508    BOOTPART = None
509    FILE = None
510    WINVER = None
511    MOUNT = None
512
513    # Si se solicita, mostrar ayuda.
514    if len(sys.argv) > 1 and sys.argv[1] == "help":
515        ogHelp(FUNCNAME, FUNCNAME + " int_ndisk int_partition ", FUNCNAME + " 1 1 ")
516        return
517
518    # Error si no se reciben 2 parámetros.
519    if len(sys.argv) != 3:
520        ogRaiseError(OG_ERR_FORMAT)
521        return
522
523    ogDiskToDev(int(sys.argv[1]), int(sys.argv[2])) or ogRaiseError(OG_ERR_PARTITION)
524    DISK = int(sys.argv[1]) - 1
525    PART = int(sys.argv[2])
526
527    # Preparando variables adaptadas a sintaxis windows.
528    if ogIsEfiActive():
529        BOOTDISK, BOOTPART = ogGetEsp()
530        ogUnmount(BOOTDISK, BOOTPART) or ogRaiseError(OG_ERR_PARTITION, "ESP: {} {}".format(BOOTDISK, BOOTPART))
531        BOOTDISK -= 1
532        BOOTLABEL = "Part-{:02d}-{:02d}".format(int(sys.argv[1]), int(sys.argv[2]))
533        BCDFILE = "boot_BCD_file=/EFI/{}/Boot/BCD".format(BOOTLABEL)
534    else:
535        BOOTDISK = DISK
536        BOOTPART = PART
537        BCDFILE = ""
538
539    # Obtener versión de Windows.
540    WINVER = ogGetOsVersion(int(sys.argv[1]), int(sys.argv[2]))
541    if WINVER is None or not WINVER.startswith("Windows"):
542        ogRaiseError(OG_ERR_NOTOS, "Windows")
543        return
544
545    # Acciones para Windows XP.
546    if "XP" in WINVER:
547        MOUNT = ogMount(int(sys.argv[1]), int(sys.argv[2]))
548        if not os.path.isfile(os.path.join(MOUNT, "boot.ini")):
549            ogRaiseError(OG_ERR_NOTFOUND, "boot.ini")
550            return
551        with open(os.path.join(MOUNT, "boot.ini"), "r") as f:
552            content = f.read()
553        content = content.replace("partition[0-9]", "partition[{}]".format(PART)).replace("rdisk[0-9]", "rdisk[{}]".format(DISK))
554        with open(os.path.join(MOUNT, "tmp.boot.ini"), "w") as f:
555            f.write(content)
556        os.rename(os.path.join(MOUNT, "tmp.boot.ini"), os.path.join(MOUNT, "boot.ini"))
557        return
558
559    ogUnmount(int(sys.argv[1]), int(sys.argv[2])) or ogRaiseError(OG_ERR_PARTITION)
560
561    # Preparando instrucciones para Windows Resume Application, tipo windows, Ramdisk Options, Recovery Environment, Recovery, Windows Boot Manager, Herramienta de diagnóstico de memoria de Windows
562    instructions = [
563        ("Windows Resume Application", ""),
564        (WINVER, ""),
565        ("Ramdisk Options", ""),
566        ("Windows Recovery Environment", ""),
567        ("Windows Recovery", ""),
568        ("Windows Boot Manager", ""),
569        ("Herramienta de diagnóstico de memoria de Windows", ""),
570        ("Herramienta de diagnóstico de memoria de Windows", "")
571    ]
572
573    for entry, options in instructions:
574        with open(FILE, "w") as f:
575            f.write("boot_disk={}\n".format(BOOTDISK))
576            f.write("boot_main_part={}\n".format(BOOTPART))
577            f.write("{}\n".format(BCDFILE))
578            f.write("disk={}\n".format(DISK))
579            f.write("main_part={}\n".format(PART))
580            f.write("boot_entry={}\n".format(entry))
581        subprocess.run(["timeout", "--foreground", "--signal=SIGKILL", "5s", "spartlnx.run", "-cui", "-nm", "-w", "-f", FILE])
582
583    os.remove(FILE)
584
585def ogWindowsRegisterPartition():
586    FUNCNAME = ogWindowsRegisterPartition.__name__
587    # Variables locales.
588    PART = None
589    DISK = None
590    FILE = None
591    REGISTREDDISK = None
592    REGISTREDPART = None
593    REGISTREDVOL = None
594    VERSION = None
595    SYSTEMROOT = None
596
597    # Si se solicita, mostrar ayuda.
598    if len(sys.argv) > 1 and sys.argv[1] == "help":
599        ogHelp(FUNCNAME, FUNCNAME + " int_ndisk_TO_registre int_partition_TO_registre str_NewVolume int_disk int_parition ",
600                FUNCNAME + " 1 1 c: 1 1")
601        return
602
603    # Error si no se reciben 5 parámetros.
604    if len(sys.argv) != 6:
605        return ogRaiseError(OG_ERR_FORMAT)
606
607    REGISTREDDISK = int(sys.argv[1])
608    REGISTREDPART = int(sys.argv[2])
609    REGISTREDVOL = sys.argv[3][0].upper()
610    DISK = int(sys.argv[4])
611    PART = int(sys.argv[5])
612    FILE = "/tmp/temp$$"
613
614    ogDiskToDev(REGISTREDDISK, REGISTREDPART) or ogRaiseError(OG_ERR_PARTITION, "particion a registrar")
615    ogDiskToDev(DISK, PART) or ogRaiseError(OG_ERR_PARTITION, "particion de windows")
616
617    TYPE = ogGetOsType(DISK, PART)
618    if "Windows" not in TYPE:
619        return ogRaiseError(OG_ERR_NOTOS, "no es windows")
620
621    VERSION = ogGetOsVersion(DISK, PART)
622
623    # Systemroot
624    if ogGetPath(DISK, PART, "WINDOWS"):
625        SYSTEMROOT = "Windows"
626    elif ogGetPath(DISK, PART, "WINNT"):
627        SYSTEMROOT = "winnt"
628    else:
629        return ogRaiseError(OG_ERR_NOTOS)
630
631    ogUnmount(DISK, PART)
632    DISK -= 1
633    REGISTREDDISK -= 1
634
635    # Preparando instruccion Windows Boot Manager
636    with open(FILE, "w") as f:
637        f.write(f"windows_disk={DISK}\n")
638        f.write(f"windows_main_part={PART}\n")
639        f.write(f"windows_dir={SYSTEMROOT}\n")
640        f.write(f"disk={REGISTREDDISK}\n")
641        f.write(f"main_part={REGISTREDPART}\n")
642        f.write(f";ext_part\n")
643        f.write(f"part_letter={REGISTREDVOL}\n")
644
645    subprocess.run(["timeout", "--foreground", "--signal=SIGKILL", "5s", "spartlnx.run", "-cui", "-nm", "-u", "-f", FILE])
646
647def ogGrubInstallMbr():
648    FUNCNAME = ogGrubInstallMbr.__name__
649    # Variables locales.
650    PART = None
651    DISK = None
652    VERSION = None
653    FIRSTSTAGE = None
654    SECONDSTAGE = None
655    CHECKOS = None
656    KERNELPARAM = None
657    BACKUPNAME = ".backup.og"
658    EFIDISK = None
659    EFIPART = None
660    EFISECONDSTAGE = None
661    EFISUBDIR = None
662    EFIOPTGRUB = ""
663    GRUBENTRY = None
664    NEWORDER = None
665
666    # Si se solicita, mostrar ayuda.
667    if len(sys.argv) > 1 and sys.argv[1] == "help":
668        ogHelp(FUNCNAME, FUNCNAME + " int_ndiskSecondStage int_partitionSecondStage bolean_Configure_2ndStage   \"param param \"  ",
669                FUNCNAME + " 1 1 FALSE ",
670                FUNCNAME + " 1 1 TRUE \"nomodeset irqpoll pci=noacpi quiet splash \" ")
671        return
672
673    # Error si no se reciben 2 parámetros.
674    if len(sys.argv) < 3:
675        return ogRaiseError(OG_ERR_FORMAT)
676
677    DISK = int(sys.argv[1])
678    PART = int(sys.argv[2])
679    CHECKOS = sys.argv[3].upper() if len(sys.argv) > 3 else "FALSE"
680    KERNELPARAM = sys.argv[4] if len(sys.argv) > 4 else ""
681
682    # Error si no es linux.
683    VERSION = ogGetOsVersion(DISK, PART)
684    if not VERSION.startswith("Linux"):
685        return ogRaiseError(OG_ERR_NOTOS, "no es linux")
686
687    # La primera etapa del grub se fija en el primer disco duro
688    FIRSTSTAGE = ogDiskToDev(1)
689
690    # Localizar disco segunda etapa del grub
691    SECONDSTAGE = ogMount(DISK, PART)
692    if SECONDSTAGE is None:
693        return
694
695    # Prepara el directorio principal de la segunda etapa
696    os.makedirs(os.path.join(SECONDSTAGE, "boot/grub"), exist_ok=True)
697
698    # Localizar directorio segunda etapa del grub
699    PREFIXSECONDSTAGE = "/boot/grubMBR"
700
701    # Instalamos grub para EFI en ESP
702    if ogIsEfiActive():
703        EFIDISK, EFIPART = ogGetEsp()
704        # Comprobamos que exista ESP y el directorio para ubuntu
705        EFISECONDSTAGE = ogMount(EFIDISK, EFIPART)
706        if EFISECONDSTAGE is None:
707            ogFormat(EFIDISK, EFIPART, "FAT32")
708            EFISECONDSTAGE = ogMount(EFIDISK, EFIPART)
709            if EFISECONDSTAGE is None:
710                return ogRaiseError(OG_ERR_PARTITION, "ESP")
711
712        EFISUBDIR = "grub"
713        # Borramos la configuración anterior
714        if os.path.isdir(os.path.join(EFISECONDSTAGE, "EFI", EFISUBDIR)):
715            shutil.rmtree(os.path.join(EFISECONDSTAGE, "EFI", EFISUBDIR))
716        os.makedirs(os.path.join(EFISECONDSTAGE, "EFI", EFISUBDIR, "Boot"), exist_ok=True)
717        EFIOPTGRUB = f"--removable --no-nvram --uefi-secure-boot --target {ogGetArch()}-efi --efi-directory=os.path.join(EFISECONDSTAGE, 'EFI', EFISUBDIR')"
718
719    # Si Reconfigurar segunda etapa (grub.cfg) == FALSE
720    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))):
721        # Si no se reconfigura se utiliza el grub.cfg orginal
722        if os.path.isfile(os.path.join(SECONDSTAGE, "boot/grub/grub.cfg" + BACKUPNAME)):
723            os.rename(os.path.join(SECONDSTAGE, "boot/grub/grub.cfg" + BACKUPNAME), os.path.join(SECONDSTAGE, "boot/grub/grub.cfg"))
724        # Si no se reconfigure se borra los ficheros previos de configuración específicos de opengnsys.
725        if os.path.isdir(os.path.join(SECONDSTAGE, PREFIXSECONDSTAGE)):
726            shutil.rmtree(os.path.join(SECONDSTAGE, PREFIXSECONDSTAGE))
727        PREFIXSECONDSTAGE = ""
728    else:
729        # SI Reconfigurar segunda etapa (grub.cfg) == TRUE
730
731        # llamada a updateBootCache para que aloje la primera fase del ogLive
732        updateBootCache()
733
734        if ogIsEfiActive():
735            # UEFI: grubSintax necesita grub.cfg para detectar los kernels: si no existe recupero backup.
736            if not os.path.isfile(os.path.join(SECONDSTAGE, "boot/grub/grub.cfg")):
737                if os.path.isfile(os.path.join(SECONDSTAGE, "boot/grub/grub.cfg" + BACKUPNAME)):
738                    os.rename(os.path.join(SECONDSTAGE, "boot/grub/grub.cfg" + BACKUPNAME), os.path.join(SECONDSTAGE, "boot/grub/grub.cfg"))
739        else:
740            # Evitar detectar modo recovery - mover grub.cfg original a grub.cfg.backup
741            os.rename(os.path.join(SECONDSTAGE, "boot/grub/grub.cfg"), os.path.join(SECONDSTAGE, "boot/grub/grub.cfg" + BACKUPNAME))
742
743        # Configurar la sintaxis grub para evitar menus de "recovery" en el OGLive
744        with open("/etc/default/grub", "a") as f:
745            f.write("GRUB_DISABLE_RECOVERY=\"true\"\n")
746            f.write("GRUB_DISABLE_LINUX_UUID=\"true\"\n")
747
748        # Preparar configuración segunda etapa: crear ubicacion
749        os.makedirs(os.path.join(SECONDSTAGE, PREFIXSECONDSTAGE, "boot/grub"), exist_ok=True)
750        # Preparar configuración segunda etapa: crear cabecera del fichero (ignorar errores)
751        subprocess.run(["sed", "-i", "s/^set -e/#set -e/", "/etc/grub.d/00_header"])
752        # (ogLive 5.0) Si 'pkgdatadir' está vacía ponemos valor de otros ogLive
753        subprocess.run(["sed", "-i", "/grub-mkconfig_lib/i\pkgdatadir=${pkgdatadir:-\"${datarootdir}/grub\"}'", "/etc/grub.d/00_header"])
754        subprocess.run(["/etc/grub.d/00_header"], stdout=open(os.path.join(SECONDSTAGE, PREFIXSECONDSTAGE, "boot/grub/grub.cfg"), "w"), stderr=subprocess.DEVNULL)
755
756        # Preparar configuración segunda etapa: crear entrada del sistema operativo
757        grubSyntax(KERNELPARAM, stdout=open(os.path.join(SECONDSTAGE, PREFIXSECONDSTAGE, "boot/grub/grub.cfg"), "a"))
758
759        # Renombramos la configuración de grub antigua
760        if os.path.isfile(os.path.join(SECONDSTAGE, "boot/grub/grub.cfg")):
761            os.rename(os.path.join(SECONDSTAGE, "boot/grub/grub.cfg"), os.path.join(SECONDSTAGE, "boot/grub/grub.cfg" + BACKUPNAME))
762
763    # Instalar el grub
764    subprocess.run(["grub-install", "--force", EFIOPTGRUB, f"--root-directory={os.path.join(SECONDSTAGE, PREFIXSECONDSTAGE)}", FIRSTSTAGE])
765    EVAL = subprocess.run(["echo", "$?"], capture_output=True, text=True).stdout.strip()
766
767    # Movemos el grubx64.efi
768    if ogIsEfiActive():
769        shutil.move(os.path.join(EFISECONDSTAGE, "EFI", EFISUBDIR, "EFI", "BOOT", "*"), os.path.join(EFISECONDSTAGE, "EFI", EFISUBDIR, "Boot"))
770        shutil.rmtree(os.path.join(EFISECONDSTAGE, "EFI", EFISUBDIR, "EFI"))
771        shutil.copy("/usr/lib/shim/shimx64.efi.signed", os.path.join(EFISECONDSTAGE, "EFI", EFISUBDIR, "Boot", "shimx64.efi"))
772        # Nombre OpenGnsys para cargador
773        shutil.copy(os.path.join(EFISECONDSTAGE, "EFI", EFISUBDIR, "Boot", "grubx64.efi"), os.path.join(EFISECONDSTAGE, "EFI", EFISUBDIR, "Boot", "ogloader.efi"))
774
775        # Creamos entrada NVRAM y la ponemos en segundo lugar
776        ogNvramAddEntry("grub", "/EFI/grub/Boot/shimx64.efi")
777        GRUBENTRY = ogNvramList().get("grub")
778        NEWORDER = ogNvramGetOrder()
779        NEWORDER[GRUBENTRY] = NEWORDER.pop(0)
780        ogNvramSetOrder(NEWORDER)
781
782    return EVAL
783
784def ogGrubInstallPartition():
785    FUNCNAME = ogGrubInstallPartition.__name__
786    # Variables locales.
787    PART = None
788    DISK = None
789    VERSION = None
790    FIRSTAGE = None
791    SECONSTAGE = None
792    CHECKOS = None
793    KERNELPARAM = None
794    BACKUPNAME = ".backup.og"
795    EFIDISK = None
796    EFIPART = None
797    EFISECONDSTAGE = None
798    EFISUBDIR = None
799    EFIOPTGRUB = ""
800    EFIBOOTDIR = ""
801
802    # Si se solicita, mostrar ayuda.
803    if len(sys.argv) > 1 and sys.argv[1] == "help":
804        ogHelp(FUNCNAME, FUNCNAME + " int_ndiskSecondStage int_partitionSecondStage bolean_Configure_2ndStage   \"param param \" ",
805                FUNCNAME + " 1 1 FALSE ",
806                FUNCNAME + " 1 1 TRUE \"nomodeset irqpoll pci=noacpi quiet splash \" ")
807        return
808
809    # Error si no se reciben 2 parámetros.
810    if len(sys.argv) < 3:
811        return ogRaiseError(OG_ERR_FORMAT)
812
813    DISK = int(sys.argv[1])
814    PART = int(sys.argv[2])
815    CHECKOS = sys.argv[3].upper() if len(sys.argv) > 3 else "FALSE"
816    KERNELPARAM = sys.argv[4] if len(sys.argv) > 4 else ""
817    BACKUPNAME = ".backup.og"
818
819    # Error si no es linux.
820    VERSION = ogGetOsVersion(DISK, PART)
821    if not VERSION.startswith("Linux"):
822        return ogRaiseError(OG_ERR_NOTOS, "no es linux")
823
824    # Localizar primera etapa del grub
825    FIRSTAGE = ogDiskToDev(DISK, PART)
826
827    # Localizar disco segunda etapa del grub
828    SECONSTAGE = ogMount(DISK, PART)
829
830    # Localizar directorio segunda etapa del grub
831    PREFIXSECONDSTAGE = "/boot/grubPARTITION"
832
833    # Si es EFI instalamos el grub en la ESP
834    EFIOPTGRUB = ""
835    EFIBOOTDIR = ""
836    if ogIsEfiActive():
837        EFIDISK, EFIPART = ogGetEsp()
838        # Comprobamos que exista ESP y el directorio para ubuntu
839        EFISECONDSTAGE = ogMount(EFIDISK, EFIPART)
840        if EFISECONDSTAGE is None:
841            ogFormat(EFIDISK, EFIPART, "FAT32")
842            EFISECONDSTAGE = ogMount(EFIDISK, EFIPART)
843            if EFISECONDSTAGE is None:
844                return ogRaiseError(OG_ERR_PARTITION, "ESP")
845
846        EFISUBDIR = "Part-{:02d}-{:02d}".format(DISK, PART)
847        # Borramos la configuración anterior
848        if os.path.isdir(os.path.join(EFISECONDSTAGE, "EFI", EFISUBDIR)):
849            shutil.rmtree(os.path.join(EFISECONDSTAGE, "EFI", EFISUBDIR))
850        os.makedirs(os.path.join(EFISECONDSTAGE, "EFI", EFISUBDIR, "Boot"), exist_ok=True)
851        EFIOPTGRUB = "--removable --no-nvram --uefi-secure-boot --target {}-efi --efi-directory={}".format(ogGetArch(), os.path.join(EFISECONDSTAGE, "EFI", EFISUBDIR))
852        EFIBOOTDIR = "/boot"
853
854    # Si Reconfigurar segunda etapa (grub.cfg) == FALSE
855    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))):
856        # Si no se reconfigura se utiliza el grub.cfg orginal
857        if os.path.isfile(os.path.join(SECONSTAGE, "boot/grub/grub.cfg" + BACKUPNAME)):
858            os.rename(os.path.join(SECONSTAGE, "boot/grub/grub.cfg" + BACKUPNAME), os.path.join(SECONSTAGE, "boot/grub/grub.cfg"))
859        # Si no se reconfigure se borra los ficheros previos de configuración específicos de opengnsys.
860        if os.path.isdir(os.path.join(SECONSTAGE, PREFIXSECONDSTAGE)):
861            shutil.rmtree(os.path.join(SECONSTAGE, PREFIXSECONDSTAGE))
862        PREFIXSECONDSTAGE = ""
863    else:
864        # SI Reconfigurar segunda etapa (grub.cfg) == TRUE
865
866        if ogIsEfiActive():
867            # UEFI: grubSintax necesita grub.cfg para detectar los kernels: si no existe recupero backup.
868            if not os.path.isfile(os.path.join(SECONSTAGE, "boot/grub/grub.cfg")):
869                if os.path.isfile(os.path.join(SECONSTAGE, "boot/grub/grub.cfg" + BACKUPNAME)):
870                    os.rename(os.path.join(SECONSTAGE, "boot/grub/grub.cfg" + BACKUPNAME), os.path.join(SECONSTAGE, "boot/grub/grub.cfg"))
871        else:
872            # Evitar detectar modo recovery - mover grub.cfg original a grub.cfg.backup
873            os.rename(os.path.join(SECONSTAGE, "boot/grub/grub.cfg"), os.path.join(SECONSTAGE, "boot/grub/grub.cfg" + BACKUPNAME))
874
875        # Configurar la sintaxis grub para evitar menus de "recovery" en el OGLive
876        with open("/etc/default/grub", "a") as f:
877            f.write("GRUB_DISABLE_RECOVERY=\"true\"\n")
878            f.write("GRUB_DISABLE_LINUX_UUID=\"true\"\n")
879
880        # Preparar configuración segunda etapa: crear ubicacion
881        os.makedirs(os.path.join(SECONSTAGE, PREFIXSECONDSTAGE, "boot/grub"), exist_ok=True)
882        # Preparar configuración segunda etapa: crear cabecera del fichero (ignorar errores)
883        subprocess.run(["sed", "-i", "s/^set -e/#set -e/", "/etc/grub.d/00_header"])
884        # (ogLive 5.0) Si 'pkgdatadir' está vacía ponemos valor de otros ogLive
885        subprocess.run(["sed", "-i", "/grub-mkconfig_lib/i\pkgdatadir=${pkgdatadir:-\"${datarootdir}/grub\"}'", "/etc/grub.d/00_header"])
886        subprocess.run(["/etc/grub.d/00_header"], stdout=open(os.path.join(SECONSTAGE, PREFIXSECONDSTAGE, "boot/grub/grub.cfg"), "w"), stderr=subprocess.DEVNULL)
887
888        # Preparar configuración segunda etapa: crear entrada del sistema operativo
889        grubSyntax(KERNELPARAM, stdout=open(os.path.join(SECONSTAGE, PREFIXSECONDSTAGE, "boot/grub/grub.cfg"), "a"))
890
891        # Renombramos la configuración de grub antigua
892        if os.path.isfile(os.path.join(SECONSTAGE, "boot/grub/grub.cfg")):
893            os.rename(os.path.join(SECONSTAGE, "boot/grub/grub.cfg"), os.path.join(SECONSTAGE, "boot/grub/grub.cfg" + BACKUPNAME))
894
895    # Instalar el grub
896    subprocess.run(["grub-install", "--force", EFIOPTGRUB, "--root-directory={}".format(os.path.join(SECONSTAGE, PREFIXSECONDSTAGE)), FIRSTAGE])
897    EVAL = subprocess.run(["echo", "$?"], capture_output=True, text=True).stdout.strip()
898
899    # Movemos el grubx64.efi
900    if ogIsEfiActive():
901        shutil.move(os.path.join(EFISECONDSTAGE, "EFI", EFISUBDIR, "EFI", "BOOT", "*"), os.path.join(EFISECONDSTAGE, "EFI", EFISUBDIR, "Boot"))
902        shutil.rmtree(os.path.join(EFISECONDSTAGE, "EFI", EFISUBDIR, "EFI"))
903        shutil.copy("/usr/lib/shim/shimx64.efi.signed", os.path.join(EFISECONDSTAGE, "EFI", EFISUBDIR, "Boot", "shimx64.efi"))
904        # Nombre OpenGnsys para cargador
905        shutil.copy(os.path.join(EFISECONDSTAGE, "EFI", EFISUBDIR, "Boot", "grubx64.efi"), os.path.join(EFISECONDSTAGE, "EFI", EFISUBDIR, "Boot", "ogloader.efi"))
906
907    return EVAL
908
909def ogConfigureFstab():
910    # Variables locales.
911    FSTAB = None
912    DEFROOT = None
913    PARTROOT = None
914    DEFSWAP = None
915    PARTSWAP = None
916    EFIDISK = None
917    EFIPART = None
918    EFIDEV = None
919    EFIOPT = None
920
921    # Si se solicita, mostrar ayuda.
922    if len(sys.argv) > 1 and sys.argv[1] == "help":
923        return
924
925    # Error si no se reciben 2 parámetros.
926    if len(sys.argv) != 3:
927        return ogRaiseError(OG_ERR_FORMAT)
928
929    # Error si no se encuentra un fichero etc/fstab en el sistema de archivos.
930    FSTAB = ogGetPath(int(sys.argv[1]), int(sys.argv[2]), "/etc/fstab")
931    if not FSTAB:
932        return ogRaiseError(OG_ERR_NOTFOUND, f"{sys.argv[1]},{sys.argv[2]},/etc/fstab")
933
934    # Hacer copia de seguridad del fichero fstab original.
935    shutil.copy2(FSTAB, f"{FSTAB}.backup")
936
937    # Dispositivo del raíz en fichero fstab: 1er campo (si no tiene "#") con 2º campo = "/".
938    with open(FSTAB, "r") as f:
939        for line in f:
940            if not line.startswith("#"):
941                fields = line.split()
942                if len(fields) >= 2 and fields[1] == "/":
943                    DEFROOT = fields[0]
944                    break
945
946    PARTROOT = ogDiskToDev(int(sys.argv[1]), int(sys.argv[2]))
947
948    # Configuración de swap (solo 1ª partición detectada).
949    PARTSWAP = subprocess.run(["blkid", "-t", "TYPE=swap"], capture_output=True, text=True).stdout.split(":")[0]
950
951    if PARTSWAP:
952        # Dispositivo de swap en fichero fstab: 1er campo (si no tiene "#") con 3er campo = "swap".
953        with open(FSTAB, "r") as f:
954            for line in f:
955                if not line.startswith("#"):
956                    fields = line.split()
957                    if len(fields) >= 3 and fields[2] == "swap":
958                        DEFSWAP = fields[0]
959                        break
960
961        if DEFSWAP:
962            print(f"Hay definicion de SWAP en el FSTAB {DEFSWAP} -> modificamos fichero con nuevo valor {DEFSWAP}->{PARTSWAP}")  # Mensaje temporal.
963            subprocess.run(["sed", f"s|{DEFSWAP}|{PARTSWAP}|g ; s|{DEFROOT}|{PARTROOT}|g", f"{FSTAB}.backup"], check=True, text=True, capture_output=True)
964        else:
965            print("No hay definicion de SWAP y si hay partición SWAP -> moficamos fichero")  # Mensaje temporal.
966            subprocess.run(["sed", f"s|{DEFROOT}|{PARTROOT}|g", f"{FSTAB}.backup"], check=True, text=True, capture_output=True)
967            with open(FSTAB, "a") as f:
968                f.write(f"{PARTSWAP}\tnone\tswap\tsw\t0\t0\n")
969    else:
970        print("No hay partición SWAP -> configuramos FSTAB")  # Mensaje temporal.
971        subprocess.run(["sed", "/swap/d", f"{FSTAB}.backup"], check=True, text=True, capture_output=True)
972
973    # Si es un sistema EFI incluimos partición ESP (Si existe la modificamos)
974    if ogIsEfiActive():
975        EFIDISK, EFIPART = ogGetEsp()
976        EFIDEV = ogDiskToDev(EFIDISK, EFIPART)
977
978        # Opciones de la partición ESP: si no existe ponemos un valor por defecto
979        with open(FSTAB, "r") as f:
980            for line in f:
981                if not line.startswith("#"):
982                    fields = line.split()
983                    if len(fields) >= 2 and fields[1] == "/boot/efi":
984                        EFIOPT = "\t".join(fields[2:6])
985                        break
986
987        if not EFIOPT:
988            EFIOPT = "vfat\tumask=0077\t0\t1"
989
990        subprocess.run(["sed", "-i", "/boot\/efi/d", FSTAB], check=True, text=True, capture_output=True)
991        with open(FSTAB, "a") as f:
992            f.write(f"{EFIDEV}\t/boot/efi\t{EFIOPT}\n")
993
994def ogSetLinuxName():
995    # Variables locales.
996    MNTDIR = None
997    ETC = None
998    NAME = None
999
1000    # Si se solicita, mostrar ayuda.
1001    if len(sys.argv) > 1 and sys.argv[1] == "help":
1002        return
1003
1004    # Error si no se reciben 2 o 3 parámetros.
1005    if len(sys.argv) == 3:
1006        # Asignar nombre automático (por defecto, "pc").
1007        NAME = ogGetHostname() or "pc"
1008    elif len(sys.argv) == 4:
1009        # Asignar nombre del 3er parámetro.
1010        NAME = sys.argv[3]
1011    else:
1012        # Formato de ejecución incorrecto.
1013        return ogRaiseError(OG_ERR_FORMAT)
1014
1015    # Montar el sistema de archivos.
1016    MNTDIR = ogMount(int(sys.argv[1]), int(sys.argv[2]))
1017    if not MNTDIR:
1018        return
1019
1020    ETC = ogGetPath(int(sys.argv[1]), int(sys.argv[2]), "/etc")
1021    if os.path.isdir(ETC):
1022        # cambio de nombre en hostname
1023        with open(os.path.join(ETC, "hostname"), "w") as f:
1024            f.write(NAME)
1025
1026        # cambio de nombre en hosts
1027        with open(os.path.join(ETC, "hosts"), "w") as f:
1028            f.write("127.0.0.1       localhost\n")
1029            f.write("127.0.1.1       {}\n".format(NAME))
1030            f.write("\n")
1031            f.write("# The following lines are desirable for IPv6 capable hosts\n")
1032            f.write("::1     ip6-localhost ip6-loopback\n")
1033            f.write("fe00::0 ip6-localnet\n")
1034            f.write("ff00::0 ip6-mcastprefix\n")
1035            f.write("ff02::1 ip6-allnodes\n")
1036            f.write("ff02::2 ip6-allrouters\n")
1037
1038def ogCleanLinuxDevices():
1039    # Variables locales.
1040    MNTDIR = None
1041
1042    # Si se solicita, mostrar ayuda.
1043    if len(sys.argv) > 1 and sys.argv[1] == "help":
1044        return
1045
1046    # Error si no se reciben 2 parámetros.
1047    if len(sys.argv) != 3:
1048        return ogRaiseError(OG_ERR_FORMAT)
1049
1050    # Montar el sistema de archivos.
1051    MNTDIR = ogMount(int(sys.argv[1]), int(sys.argv[2]))
1052    if not MNTDIR:
1053        return
1054
1055    # Eliminar fichero de configuración de udev para dispositivos fijos de red.
1056    if os.path.isfile(os.path.join(MNTDIR, "etc/udev/rules.d/70-persistent-net.rules")):
1057        os.remove(os.path.join(MNTDIR, "etc/udev/rules.d/70-persistent-net.rules"))
1058
1059    # Eliminar fichero resume (estado previo de hibernación) utilizado por el initrd scripts-premount
1060    if os.path.isfile(os.path.join(MNTDIR, "etc/initramfs-tools/conf.d/resume")):
1061        os.remove(os.path.join(MNTDIR, "etc/initramfs-tools/conf.d/resume"))
1062
1063def ogGrubAddOgLive():
1064    FUNCNAME = ogGrubAddOgLive.__name__
1065    TIMEOUT = None
1066    DIRMOUNT = None
1067    GRUBGFC = None
1068    PARTTABLETYPE = None
1069    NUMDISK = None
1070    NUMPART = None
1071    KERNEL = None
1072    STATUS = None
1073    NUMLINE = None
1074    MENUENTRY = None
1075
1076    # Si se solicita, mostrar ayuda.
1077    if len(sys.argv) > 1 and sys.argv[1] == "help":
1078        ogHelp(FUNCNAME, f"{FUNCNAME} int_ndisk int_npartition [ time_out ] [ offline|online ]",
1079                f"{FUNCNAME} 1 1",
1080                f"{FUNCNAME} 1 6 15 offline")
1081        return
1082
1083    # Error si no se reciben 2 parámetros.
1084    if len(sys.argv) < 3:
1085        return ogRaiseError(OG_ERR_FORMAT)
1086
1087    if sys.argv[3].isdigit():
1088        TIMEOUT = int(sys.argv[3])
1089
1090    # Error si no existe el kernel y el initrd en la cache.
1091    # Falta crear nuevo codigo de error.
1092    if not os.path.isfile(f"{OGCAC}/boot/{oglivedir}/ogvmlinuz") or not os.path.isfile(f"{OGCAC}/boot/{oglivedir}/oginitrd.img"):
1093        return ogRaiseError(OG_ERR_NOTFOUND, "CACHE: ogvmlinuz, oginitrd.img")
1094
1095    # Archivo de configuracion del grub
1096    DIRMOUNT = ogMount(int(sys.argv[1]), int(sys.argv[2]))
1097    GRUBGFC = f"{DIRMOUNT}/boot/grubMBR/boot/grub/grub.cfg"
1098
1099    # Error si no existe archivo del grub
1100    if not os.path.isfile(GRUBGFC):
1101        return ogRaiseError(OG_ERR_NOTFOUND, GRUBGFC)
1102
1103    # Si existe la entrada de opengnsys, se borra
1104    with open(GRUBGFC, "r") as f:
1105        lines = f.readlines()
1106    with open(GRUBGFC, "w") as f:
1107        for line in lines:
1108            if "menuentry Opengnsys" not in line:
1109                f.write(line)
1110
1111    # Tipo de tabla de particiones
1112    PARTTABLETYPE = ogGetPartitionTableType(int(sys.argv[1])).lower()
1113
1114    # Localizacion de la cache
1115    NUMDISK, NUMPART = ogFindCache()
1116    NUMDISK -= 1
1117
1118    # kernel y sus opciones. Pasamos a modo usuario
1119    KERNEL = f"/boot/{oglivedir}/ogvmlinuz {' '.join([arg for arg in sys.argv[4:] if not arg.startswith('ogactiveadmin=')])}"
1120
1121    # Configuracion offline si existe parametro
1122    if "offline" in sys.argv:
1123        STATUS = "offline"
1124    elif "online" in sys.argv:
1125        STATUS = "online"
1126    if STATUS:
1127        KERNEL = KERNEL.replace("ogprotocol=", "ogprotocol=local ")
1128        KERNEL += f" ogstatus={STATUS}"
1129
1130    # Numero de línea de la primera entrada del grub.
1131    with open(GRUBGFC, "r") as f:
1132        lines = f.readlines()
1133    for i, line in enumerate(lines):
1134        if line.startswith("menuentry"):
1135            NUMLINE = i + 1
1136            break
1137
1138    # Texto de la entrada de opengnsys
1139    MENUENTRY = f"""menuentry "OpenGnsys" --class opengnsys --class gnu --class os {{
1140    insmod part_{PARTTABLETYPE}
1141    insmod ext2
1142    set root='(hd{NUMDISK},{PARTTABLETYPE}{NUMPART})'
1143    linux {KERNEL}
1144    initrd /boot/{oglivedir}/oginitrd.img
1145    }}
1146    """
1147
1148    # Insertamos la entrada de opengnsys antes de la primera entrada existente.
1149    lines.insert(NUMLINE, MENUENTRY + "\n")
1150    with open(GRUBGFC, "w") as f:
1151        f.writelines(lines)
1152
1153    # Ponemos que la entrada por defecto sea la primera.
1154    with open(GRUBGFC, "r") as f:
1155        lines = f.readlines()
1156    with open(GRUBGFC, "w") as f:
1157        for line in lines:
1158            if line.startswith("set default="):
1159                f.write("set default=\"0\"\n")
1160            else:
1161                f.write(line)
1162
1163    # Si me dan valor para timeout lo cambio en el grub.
1164    if TIMEOUT:
1165        with open(GRUBGFC, "r") as f:
1166            lines = f.readlines()
1167        with open(GRUBGFC, "w") as f:
1168            for line in lines:
1169                if line.startswith("timeout="):
1170                    f.write(f"timeout={TIMEOUT}\n")
1171                else:
1172                    f.write(line)
1173
1174def ogGrubHidePartitions():
1175    FUNCNAME = ogGrubHidePartitions.__name__
1176    # Si se solicita, mostrar ayuda.
1177    if len(sys.argv) > 1 and sys.argv[1] == "help":
1178        ogHelp(FUNCNAME, f"{FUNCNAME} int_ndisk int_npartition [ num_disk_partdata num_partdata ]",
1179                f"{FUNCNAME} 1 2",
1180                f"{FUNCNAME} 1 2 1 3")
1181        return
1182    ogBootLoaderHidePartitions(*sys.argv[1:])
1183    return
1184
1185def ogBurgHidePartitions():
1186    FUNCNAME = ogBurgHidePartitions.__name__
1187    # Si se solicita, mostrar ayuda.
1188    if len(sys.argv) > 1 and sys.argv[1] == "help":
1189        ogHelp(FUNCNAME, f"{FUNCNAME} int_ndisk int_npartition [ num_disk_partdata num_partdata ]",
1190                f"{FUNCNAME} 1 2",
1191                f"{FUNCNAME} 1 2 1 3")
1192        return
1193    ogBootLoaderHidePartitions(*sys.argv[1:])
1194    return
1195
1196def ogBootLoaderHidePartitions():
1197    FUNCNAME = ogBootLoaderHidePartitions.__name__
1198    FUNC = None
1199    DIRMOUNT = None
1200    GFCFILE = None
1201    PARTTABLETYPE = None
1202    WINENTRY = None
1203    WINPART = None
1204    ENTRY = None
1205    LINE = None
1206    PART = None
1207    PARTDATA = None
1208    TEXT = None
1209    PARTHIDDEN = None
1210    HIDDEN = None
1211
1212    # Si se solicita, mostrar ayuda.
1213    if len(sys.argv) > 1 and sys.argv[1] == "help":
1214        ogHelp(FUNCNAME, f"{FUNCNAME} num_disk num_part [ num_disk_partdata num_partdata ]",
1215                f"{FUNCNAME} 1 2",
1216                f"{FUNCNAME} 1 2 1 3")
1217        return
1218
1219    # Nombre de la función que llama a esta.
1220    FUNC = sys._getframe().f_back.f_code.co_name
1221
1222    # Error si no se reciben 2 parámetros.
1223    if len(sys.argv) < 3:
1224        return ogRaiseError(OG_ERR_FORMAT)
1225
1226    if len(sys.argv) == 4:
1227        PARTDATA = ogDiskToDev(int(sys.argv[3]), int(sys.argv[4]))
1228    else:
1229        PARTDATA = 0
1230
1231    # Archivo de configuracion del grub
1232    DIRMOUNT = ogMount(int(sys.argv[1]), int(sys.argv[2]))
1233    # La función debe ser llamada desde ogGrubHidePartitions or ogBurgHidePartitions.
1234    if FUNC == "ogGrubHidePartitions":
1235        GFCFILE = f"{DIRMOUNT}/boot/grubMBR/boot/grub/grub.cfg"
1236    elif FUNC == "ogBurgHidePartitions":
1237        GFCFILE = f"{DIRMOUNT}/boot/burg/burg.cfg"
1238    else:
1239        return ogRaiseError(OG_ERR_FORMAT, "Use ogGrubHidePartitions or ogBurgHidePartitions.")
1240
1241    # Error si no existe archivo del grub
1242    if not os.path.isfile(GFCFILE):
1243        return ogRaiseError(OG_ERR_NOTFOUND, GFCFILE)
1244
1245    # Si solo hay una particion de Windows me salgo
1246    if subprocess.run(["fdisk", "-l", ogDiskToDev(), "|", "grep", "NTFS", "|", "wc", "-l"], capture_output=True, text=True).stdout.strip() == "1":
1247        return 0
1248
1249    # Elimino llamadas a parttool, se han incluido en otras ejecuciones de esta funcion.
1250    subprocess.run(["sed", "-i", "/parttool/d", GFCFILE], check=True)
1251
1252    PARTTABLETYPE = ogGetPartitionTableType(int(sys.argv[1])).lower()
1253
1254    # Entradas de Windows: numero de linea y particion. De mayor a menor.
1255    WINENTRY = subprocess.run(["awk", "/menuentry.*Windows/ {gsub(/\\)\"/, \"\"); gsub(/^.*dev/,\"\", \"\"); print NR\":/dev\"$1}", CFGFILE], capture_output=True, text=True).stdout.strip().split("\n")
1256
1257    # Particiones de Windows, pueden no estar en el grub.
1258    WINPART = subprocess.run(["fdisk", "-l", ogDiskToDev(), "|", "awk", "/NTFS/ {print $1}", "|", "sed", "1!G;h;$!d"], capture_output=True, text=True).stdout.strip().split("\n")
1259
1260    # Modifico todas las entradas de Windows.
1261    for ENTRY in WINENTRY:
1262        LINE, PART = ENTRY.split(":")
1263        TEXT = ""
1264        for PARTHIDDEN in WINPART:
1265            # Muestro la particion de la entrada actual y la de datos.
1266            if PARTHIDDEN == PART or PARTHIDDEN == PARTDATA:
1267                HIDDEN = "-"
1268            else:
1269                HIDDEN = "+"
1270            NUMDISK, NUMPART = ogDevToDisk(PARTHIDDEN)
1271            TEXT = f"\tparttool (hd{NUMDISK-1},{PARTTABLETYPE}{NUMPART}) hidden{HIDDEN} \n{TEXT}"
1272        subprocess.run(["sed", "-i", f"{LINE}a\ {TEXT}", GFCFILE], check=True)
1273
1274    # Activamos la particion que se inicia en todas las entradas de windows.
1275    subprocess.run(["sed", "-i", "/chainloader/i\\\tparttool ${root} boot+", GFCFILE], check=True)
1276
1277    CFGFILE = "path/to/config/file"
1278
1279def ogGrubDeleteEntry():
1280    # Si se solicita, mostrar ayuda.
1281    if len(sys.argv) > 1 and sys.argv[1] == "help":
1282        ogHelp(sys.argv[0], f"{sys.argv[0]} int_ndisk int_npartition int_disk_delete int_npartition_delete",
1283                f"{sys.argv[0]} 1 6 2 1")
1284        return
1285    ogBootLoaderDeleteEntry(*sys.argv[1:])
1286    return
1287
1288def ogBurgDeleteEntry():
1289    # Si se solicita, mostrar ayuda.
1290    if len(sys.argv) > 1 and sys.argv[1] == "help":
1291        ogHelp(sys.argv[0], f"{sys.argv[0]} int_ndisk int_npartition int_disk_delete int_npartition_delete",
1292                f"{sys.argv[0]} 1 6 2 1")
1293        return
1294    ogBootLoaderDeleteEntry(*sys.argv[1:])
1295    return
1296
1297def ogRefindDeleteEntry():
1298    # Si se solicita, mostrar ayuda.
1299    if len(sys.argv) > 1 and sys.argv[1] == "help":
1300        ogHelp("ogRefindDeleteEntry", "ogRefindDeleteEntry int_disk_delete int_npartition_delete", "ogRefindDeleteEntry 2 1")
1301        return
1302    EFIDISK, EFIPART = ogGetEsp().split()
1303    ogBootLoaderDeleteEntry(EFIDISK, EFIPART, *sys.argv[1:])
1304    return
1305
1306def ogBootLoaderDeleteEntry():
1307    FUNC = None
1308    DIRMOUNT = None
1309    CFGFILE = None
1310    LABEL = None
1311    MENUENTRY = None
1312    DELETEENTRY = None
1313    ENDENTRY = None
1314    ENTRY = None
1315
1316    # Si se solicita, mostrar ayuda.
1317    if len(sys.argv) > 1 and sys.argv[1] == "help":
1318        ogHelp(sys.argv[0], f"{sys.argv[0]} int_ndisk int_npartition int_disk_delete int_npartition_delete",
1319                f"{sys.argv[0]} 1 6 2 1")
1320        return
1321
1322    # Si el número de parámetros es menor que 4, salimos.
1323    if len(sys.argv) < 5:
1324        return ogRaiseError(OG_ERR_FORMAT)
1325
1326    # Nombre de la función que llama a esta.
1327    FUNC = sys._getframe().f_back.f_code.co_name
1328
1329    # Archivo de configuracion del grub
1330    DIRMOUNT = ogMount(int(sys.argv[1]), int(sys.argv[2]))
1331    # La función debe ser llamada desde ogGrubDeleteEntry, ogBurgDeleteEntry or ogRefindDeleteEntry.
1332    if FUNC == "ogGrubDeleteEntry":
1333        CFGFILE = f"{DIRMOUNT}/boot/grubMBR/boot/grub/grub.cfg"
1334    elif FUNC == "ogBurgDeleteEntry":
1335        CFGFILE = f"{DIRMOUNT}/boot/burg/burg.cfg"
1336    elif FUNC == "ogRefindDeleteEntry":
1337        CFGFILE = f"{DIRMOUNT}/EFI/refind/refind.conf"
1338    else:
1339        return ogRaiseError(OG_ERR_FORMAT, "Use ogGrubDeleteEntry, ogBurgDeleteEntry or ogRefindDeleteEntry.")
1340
1341    # Dispositivo
1342    if os.path.basename(CFGFILE) == "refind.conf":
1343        LABEL = f"Part-{int(sys.argv[3]):02d}-{int(sys.argv[4]):02d}"
1344    else:
1345        LABEL = ogDiskToDev(int(sys.argv[3]), int(sys.argv[4]))
1346
1347    # Error si no existe archivo de configuración
1348    if not os.path.isfile(CFGFILE):
1349        return ogRaiseError(OG_ERR_NOTFOUND, CFGFILE)
1350
1351    # Numero de linea de cada entrada.
1352    with open(CFGFILE, "r") as f:
1353        lines = f.readlines()
1354    MENUENTRY = [str(i+1) for i, line in enumerate(lines) if "menuentry" in line]
1355
1356    # Entradas que hay que borrar.
1357    DELETEENTRY = [str(i+1) for i, line in enumerate(lines) if f"menuentry {LABEL}" in line]
1358
1359    # Si no hay entradas para borrar, salimos con aviso
1360    if not DELETEENTRY:
1361        return ogRaiseError(OG_ERR_NOTFOUND, f"Menuentry {LABEL}")
1362
1363    # Recorremos el fichero del final hacia el principio.
1364    ENDENTRY = len(lines)
1365    for ENTRY in MENUENTRY:
1366        # Comprobamos si hay que borrar la entrada.
1367        if ENTRY in DELETEENTRY:
1368            ENDENTRY -= 1
1369            lines = lines[:int(ENTRY)-1] + lines[int(ENDENTRY):]
1370
1371        # Guardamos el número de línea de la entrada, que sera el final de la siguiente.
1372        ENDENTRY = ENTRY
1373
1374    with open(CFGFILE, "w") as f:
1375        f.writelines(lines)
1376
1377def ogBurgInstallMbr():
1378    FUNCNAME = ogBurgInstallMbr.__name__
1379    # Variables locales.
1380    BINARYAVAILABLE = None
1381    PART = None
1382    DISK = None
1383    DEVICE = None
1384    MOUNTDISK = None
1385    FIRSTAGE = None
1386    SECONSTAGE = None
1387    PREFIXSECONDSTAGE = None
1388    CHECKOS = None
1389    KERNELPARAM = None
1390    BACKUPNAME = ".backup.og"
1391    FILECFG = None
1392
1393    # Si se solicita, mostrar ayuda.
1394    if len(sys.argv) > 1 and sys.argv[1] == "help":
1395        ogHelp(FUNCNAME, f"{FUNCNAME}  int_ndiskSecondStage int_partitionSecondStage bolean_Configure_2ndStage   \"param param \"  ",
1396                f"{FUNCNAME} 1 1 FALSE ",
1397                f"{FUNCNAME} 1 1 TRUE \"nomodeset irqpoll pci=noacpi quiet splash \" ")
1398        return
1399
1400    # Error si no se reciben 2 parametros.
1401    if len(sys.argv) < 3:
1402        return ogRaiseError(OG_ERR_FORMAT)
1403
1404    # Error si no tenemos el binario burg
1405    BINARYAVAILABLE = subprocess.run(["burg-install", "-v"], capture_output=True, text=True).stdout.strip()
1406    if BINARYAVAILABLE == "NO":
1407        if os.path.exists(f"{OGLIB}/burg/burg.tgz"):
1408            subprocess.run(["tar", "xzvf", f"{OGLIB}/burg/burg.tgz", "--strip", "1"], cwd="/", capture_output=True, text=True)
1409        else:
1410            return ogRaiseError(OG_ERR_NOTEXEC, "Binary burg not found")
1411
1412    DISK = int(sys.argv[1])
1413    PART = int(sys.argv[2])
1414    CHECKOS = sys.argv[3].upper() if len(sys.argv) > 3 else "FALSE"
1415    KERNELPARAM = sys.argv[4] if len(sys.argv) > 4 else ""
1416
1417    # Controlar disco no uefi
1418    if ogIsEfiActive():
1419        return ogRaiseError(OG_ERR_NOTBIOS, "grub4dos solo soporta PC con bios legacy")
1420
1421    # Controlar particionado tipo msdos
1422    if not ogCheckStringInGroup(ogGetPartitionTableType(DISK), "MSDOS"):
1423        return ogRaiseError(OG_ERR_NOMSDOS, "grub2dos requiere particionado tipo MSDOS")
1424
1425    # Controlar existencia de disco y particion
1426    DEVICE = ogDiskToDev(DISK)
1427    if not DEVICE:
1428        return ogRaiseError(OG_ERR_NOTFOUND)
1429    MOUNTDISK = ogMount(DISK, PART)
1430    if not MOUNTDISK:
1431        return ogRaiseError(OG_ERR_PARTITION)
1432
1433    # Controlar particion segunda etapa del burg
1434    if not ogCheckStringInGroup(ogGetFsType(DISK, PART), "CACHE EXT4 EXT3 EXT2"):
1435        return ogRaiseError(OG_ERR_PARTITION, "burg.cfg soporta solo particiones linux")
1436
1437    # Controlar acceso de escritura a la particion segunda etapa del burg
1438    if ogIsReadonly(DISK, PART):
1439        return ogRaiseError(OG_ERR_NOTWRITE, f"{DISK} {PART}")
1440
1441    # Asigar la primera etapa del grub en el primer disco duro
1442    FIRSTAGE = ogDiskToDev(1)
1443
1444    # Localizar disco segunda etapa del grub
1445    SECONSTAGE = ogMount(DISK, PART)
1446
1447    # Preparar el directorio principal de la segunda etapa (y copia los binarios)
1448    if not os.path.isdir(f"{SECONSTAGE}/boot/burg/"):
1449        os.makedirs(f"{SECONSTAGE}/boot/burg/")
1450    shutil.copytree("/boot/burg/", f"{SECONSTAGE}/boot/burg/")
1451    shutil.copytree(f"{OGLIB}/burg/themes", f"{SECONSTAGE}/boot/burg/themes")
1452
1453    # No configurar la segunda etapa (grub.cfg). Parámetro FALSE
1454    if os.path.isfile(f"{SECONSTAGE}/boot/burg/burg.cfg") or os.path.isfile(f"{SECONSTAGE}/boot/burg/burg.cfg{BACKUPNAME}"):
1455        if CHECKOS == "FALSE":
1456            subprocess.run(["burg-install", "--force", f"--root-directory={SECONSTAGE}", FIRSTAGE], capture_output=True, text=True)
1457            return
1458
1459    # Configurar la segunda etapa (burg.cfg) == tercer parámetro TRUE
1460
1461    # Llamar a updateBootCache para que aloje la primera fase del ogLive
1462    updateBootCache()
1463
1464    # Configurar la sintaxis grub para evitar menus de "recovery" en el OGLive
1465    with open("/etc/default/grub", "a") as f:
1466        f.write("GRUB_DISABLE_RECOVERY=\"true\"\n")
1467        f.write("GRUB_DISABLE_LINUX_UUID=\"true\"\n")
1468
1469    # Preparar configuración segunda etapa: crear ubicacion
1470    os.makedirs(f"{SECONSTAGE}{PREFIXSECONDSTAGE}/boot/burg/")
1471
1472    # Preparar configuración segunda etapa: crear cabecera del fichero
1473    FILECFG = f"{SECONSTAGE}{PREFIXSECONDSTAGE}/boot/burg/burg.cfg"
1474
1475    # Preparar configuración segunda etapa: crear entrada del sistema operativo
1476    with open(FILECFG, "w") as f:
1477        f.write("set theme_name=OpenGnsys\n")
1478        f.write("set gfxmode=1024x768\n")
1479        f.write("set locale_dir=($root)/boot/burg/locale\n")
1480        f.write("set default=0\n")
1481        f.write("set timeout=25\n")
1482        f.write("set lang=es\n")
1483        f.write("insmod ext2\n")
1484        f.write("insmod gettext\n")
1485        f.write("if [ -s $prefix/burgenv ]; then\n")
1486        f.write("  load_env\n")
1487        f.write("fi\n")
1488        f.write("if [ ${prev_saved_entry} ]; then\n")
1489        f.write("  set saved_entry=${prev_saved_entry}\n")
1490        f.write("  save_env saved_entry\n")
1491        f.write("  set prev_saved_entry=\n")
1492        f.write("  save_env prev_saved_entry\n")
1493        f.write("  set boot_once=true\n")
1494        f.write("fi\n")
1495        f.write("function savedefault {\n")
1496        f.write("  if [ -z ${boot_once} ]; then\n")
1497        f.write("    saved_entry=${chosen}\n")
1498        f.write("    save_env saved_entry\n")
1499        f.write("  fi\n")
1500        f.write("}\n")
1501        f.write("function select_menu {\n")
1502        f.write("  if menu_popup -t template_popup theme_menu ; then\n")
1503        f.write("    free_config template_popup template_subitem menu class screen\n")
1504        f.write("    load_config ${prefix}/themes/${theme_name}/theme ${prefix}/themes/custom/theme_${theme_name}\n")
1505        f.write("    save_env theme_name\n")
1506        f.write("    menu_refresh\n")
1507        f.write("  fi\n")
1508        f.write("}\n")
1509        f.write("function toggle_fold {\n")
1510        f.write("  if test -z $theme_fold ; then\n")
1511        f.write("    set theme_fold=1\n")
1512        f.write("  else\n")
1513        f.write("    set theme_fold=\n")
1514        f.write("  fi\n")
1515        f.write("  save_env theme_fold\n")
1516        f.write("  menu_refresh\n")
1517        f.write("}\n")
1518        f.write("function select_resolution {\n")
1519        f.write("  if menu_popup -t template_popup resolution_menu ; then\n")
1520        f.write("    menu_reload_mode\n")
1521        f.write("    save_env gfxmode\n")
1522        f.write("  fi\n")
1523        f.write("}\n")
1524        f.write("if test -f ${prefix}/themes/${theme_name}/theme ; then\n")
1525        f.write("  insmod coreui\n")
1526        f.write("  menu_region.text\n")
1527        f.write("  load_string '+theme_menu { -OpenGnsys { command=\"set theme_name=OpenGnsys\" }}'\n")
1528        f.write("  load_config ${prefix}/themes/conf.d/10_hotkey\n")
1529        f.write("  load_config ${prefix}/themes/${theme_name}/theme ${prefix}/themes/custom/theme_${theme_name}\n")
1530        f.write("  insmod vbe\n")
1531        f.write("  insmod png\n")
1532        f.write("  insmod jpeg\n")
1533        f.write("  set gfxfont=\"Unifont Regular 16\"\n")
1534        f.write("  menu_region.gfx\n")
1535        f.write("  vmenu resolution_menu\n")
1536        f.write("  controller.ext\n")
1537        f.write("fi\n")
1538
1539    # Preparar configuración segunda etapa: crear entrada del sistema operativo
1540    grubSyntax(KERNELPARAM, FILECFG)
1541
1542    # Instalar el burg
1543    subprocess.run(["burg-install", "--force", f"--root-directory={SECONSTAGE}", FIRSTAGE], capture_output=True, text=True)
1544
1545def ogGrubDefaultEntry():
1546    # Si se solicita, mostrar ayuda.
1547    if len(sys.argv) > 1 and sys.argv[1] == "help":
1548        ogHelp(sys.argv[0], f"{sys.argv[0]} int_ndisk int_npartition int_disk_default_entry int_npartition_default_entry",
1549                f"{sys.argv[0]} 1 6 1 1")
1550        return
1551    ogBootLoaderDefaultEntry(*sys.argv[1:])
1552    return
1553
1554def ogBurgDefaultEntry():
1555    # Si se solicita, mostrar ayuda.
1556    if len(sys.argv) > 1 and sys.argv[1] == "help":
1557        ogHelp(sys.argv[0], f"{sys.argv[0]} int_ndisk int_npartition int_disk_default_entry int_npartition_default_entry",
1558                f"{sys.argv[0]} 1 6 1 1")
1559        return
1560    ogBootLoaderDefaultEntry(*sys.argv[1:])
1561    return
1562
1563def ogRefindDefaultEntry():
1564    EFIDISK, EFIPART = ogGetEsp().split()
1565    # Si se solicita, mostrar ayuda.
1566    if len(sys.argv) > 1 and sys.argv[1] == "help":
1567        ogHelp("ogRefindDefaultEntry", "ogRefindDefaultEntry int_disk_default_entry int_npartition_default_entry",
1568                "ogRefindDefaultEntry 1 1")
1569        return
1570    ogBootLoaderDefaultEntry(EFIDISK, EFIPART, *sys.argv[1:])
1571    return
1572
1573def ogBootLoaderDefaultEntry():
1574    # Variables locales.
1575    PART = None
1576    FUNC = None
1577    DIRMOUNT = None
1578    LABEL = None
1579    CFGFILE = None
1580    DEFAULTENTRY = None
1581    MENUENTRY = None
1582
1583    # Si se solicita, mostrar ayuda.
1584    if len(sys.argv) > 1 and sys.argv[1] == "help":
1585        ogHelp(sys.argv[0], f"{sys.argv[0]} int_ndiskSecondStage int_partitionSecondStage int_disk_default_entry int_partitions_default_entry",
1586                f"{sys.argv[0]} 1 6 1 1")
1587        return
1588
1589    # Nombre de la función que llama a esta.
1590    FUNC = sys._getframe().f_back.f_code.co_name
1591
1592    # Error si no se reciben 4 parámetros.
1593    if len(sys.argv) < 5:
1594        return ogRaiseError(OG_ERR_FORMAT)
1595
1596    # Error si no puede montar sistema de archivos.
1597    DIRMOUNT = ogMount(int(sys.argv[1]), int(sys.argv[2]))
1598    if not DIRMOUNT:
1599        return
1600
1601    # Comprobamos que exista fichero de configuración
1602    # La función debe ser llamada desde ogGrubDefaultEntry, ogBurgDefaultEntry or ogRefindDefaultEntry.
1603    if FUNC == "ogGrubDefaultEntry":
1604        CFGFILE = f"{DIRMOUNT}/boot/grubMBR/boot/grub/grub.cfg"
1605    elif FUNC == "ogBurgDefaultEntry":
1606        CFGFILE = f"{DIRMOUNT}/boot/burg/burg.cfg"
1607    elif FUNC == "ogRefindDefaultEntry":
1608        CFGFILE = f"{DIRMOUNT}/EFI/refind/refind.conf"
1609    else:
1610        return ogRaiseError(OG_ERR_FORMAT, "Use ogGrubDefaultEntry, ogBurgDefaultEntry or ogRefindDefaultEntry.")
1611
1612    # Error si no existe archivo de configuración
1613    if not os.path.isfile(CFGFILE):
1614        return ogRaiseError(OG_ERR_NOTFOUND, CFGFILE)
1615
1616    # Dispositivo
1617    if os.path.basename(CFGFILE) == "refind.conf":
1618        LABEL = f"Part-{int(sys.argv[3]):02d}-{int(sys.argv[4]):02d}"
1619    else:
1620        LABEL = ogDiskToDev(int(sys.argv[3]), int(sys.argv[4]))
1621
1622    # Número de línea de la entrada por defecto en CFGFILE (primera de la partición).
1623    with open(CFGFILE, "r") as f:
1624        lines = f.readlines()
1625    for i, line in enumerate(lines):
1626        if f"menuentry {LABEL}" in line:
1627            DEFAULTENTRY = i + 1
1628            break
1629
1630    # Si no hay entradas para borrar me salgo con aviso
1631    if not DEFAULTENTRY:
1632        return ogRaiseError(OG_ERR_NOTFOUND, f"No menuentry {LABEL}")
1633
1634    # Número de la de linea por defecto en el menú de usuario
1635    with open(CFGFILE, "r") as f:
1636        menu_entries = [i for i, line in enumerate(f) if "menuentry" in line]
1637    MENUENTRY = menu_entries.index(DEFAULTENTRY) + 1
1638
1639    if os.path.basename(CFGFILE) == "refind.conf":
1640        subprocess.run(["sed", "-i", "/default_selection.*$/d", CFGFILE], check=True)
1641        subprocess.run(["sed", "-i", f"1 i\\default_selection {MENUENTRY}", CFGFILE], check=True)
1642    else:
1643        # En grub y burg las líneas empiezan a contar desde cero
1644        MENUENTRY -= 1
1645        subprocess.run(["sed", "-i", f"s/set default=\"?[0-9]*\"?$/set default=\"{MENUENTRY}\"/g", CFGFILE], check=True)
1646
1647def ogGrubOgliveDefaultEntry():
1648    # Si se solicita, mostrar ayuda.
1649    if len(sys.argv) > 1 and sys.argv[1] == "help":
1650        ogHelp(sys.argv[0], f"{sys.argv[0]} int_ndiskSecondStage int_partitionSecondStage",
1651                f"{sys.argv[0]} 1 6")
1652        return
1653    ogBootLoaderOgliveDefaultEntry(*sys.argv[1:])
1654    return
1655
1656def ogBurgOgliveDefaultEntry():
1657    # Si se solicita, mostrar ayuda.
1658    if len(sys.argv) > 1 and sys.argv[1] == "help":
1659        ogHelp(sys.argv[0], f"{sys.argv[0]} int_ndiskSecondStage int_partitionSecondStage",
1660                f"{sys.argv[0]} 1 6")
1661        return
1662    ogBootLoaderOgliveDefaultEntry(*sys.argv[1:])
1663    return
1664
1665def ogRefindOgliveDefaultEntry():
1666    EFIDISK, EFIPART = ogGetEsp().split()
1667    # Si se solicita, mostrar ayuda.
1668    if len(sys.argv) > 1 and sys.argv[1] == "help":
1669        ogHelp("ogRefindOgliveDefaultEntry", "ogRefindOgliveDefaultEntry",
1670                "ogRefindOgliveDefaultEntry")
1671        return
1672    ogBootLoaderOgliveDefaultEntry(EFIDISK, EFIPART)
1673    return
1674
1675def ogBootLoaderOgliveDefaultEntry():
1676    # Variables locales.
1677    PART = None
1678    FUNC = None
1679    CFGFILE = None
1680    NUMENTRY = None
1681
1682    # Si se solicita, mostrar ayuda.
1683    if len(sys.argv) > 1 and sys.argv[1] == "help":
1684        ogHelp(sys.argv[0], f"{sys.argv[0]} int_ndiskSecondStage int_partitionSecondStage",
1685                f"{sys.argv[0]} 1 6")
1686        return
1687
1688    # Nombre de la función que llama a esta.
1689    FUNC = sys._getframe().f_back.f_code.co_name
1690
1691    # Error si no se reciben 2 parametros.
1692    if len(sys.argv) < 3:
1693        return ogRaiseError(OG_ERR_FORMAT)
1694
1695    # Error si no puede montar sistema de archivos.
1696    PART = ogMount(int(sys.argv[1]), int(sys.argv[2]))
1697    if not PART:
1698        return
1699
1700    # La función debe ser llamada desde ogGrubOgliveDefaultEntry, ogBurgOgliveDefaultEntry or ogRefindOgliveDefaultEntry.
1701    if FUNC == "ogGrubOgliveDefaultEntry":
1702        CFGFILE = f"{PART}/boot/grubMBR/boot/grub/grub.cfg"
1703    elif FUNC == "ogBurgOgliveDefaultEntry":
1704        CFGFILE = f"{PART}/boot/burg/burg.cfg"
1705    elif FUNC == "ogRefindOgliveDefaultEntry":
1706        CFGFILE = f"{PART}/EFI/refind/refind.conf"
1707    else:
1708        return ogRaiseError(OG_ERR_FORMAT, "Use ogGrubOgliveDefaultEntry, ogBurgOgliveDefaultEntry or ogRefindOgliveDefaultEntry.")
1709
1710    # Comprobamos que exista fichero de configuración
1711    if not os.path.isfile(CFGFILE):
1712        return ogRaiseError(OG_ERR_NOTFOUND, CFGFILE)
1713
1714    # Detectamos cual es la entrada de ogLive
1715    with open(CFGFILE, "r") as f:
1716        lines = f.readlines()
1717    for i, line in enumerate(lines):
1718        if "menuentry" in line and "OpenGnsys Live" in line:
1719            NUMENTRY = i + 1
1720            break
1721
1722    # Si no existe entrada de ogLive nos salimos
1723    if not NUMENTRY:
1724        return ogRaiseError(OG_ERR_NOTFOUND, f"menuentry OpenGnsys Live in {CFGFILE}")
1725
1726    if os.path.basename(CFGFILE) == "refind.conf":
1727        subprocess.run(["sed", "-i", "/default_selection.*$/d", CFGFILE], check=True)
1728        subprocess.run(["sed", "-i", f"1 i\\default_selection {NUMENTRY}", CFGFILE], check=True)
1729    else:
1730        NUMENTRY -= 1
1731        subprocess.run(["sed", "-i", f"s/set default=\"?[0-9]+\"?/set default=\"{NUMENTRY}\"/g", CFGFILE], check=True)
1732
1733    # Generate the help message based on the function name
1734    MSG = f"MSG_HELP_{FUNC}"
1735    help_message = f"{globals()[MSG].split('.')[0]}: {' '.join(sys.argv[1:])}"
1736    print(help_message)
1737
1738def ogGrubSecurity():
1739    # Variables locales.
1740    SECONDSTAGE = None
1741    GRUBGFC = None
1742    FILE = None
1743    USER = None
1744    PASSWD = None
1745    ENCRYPTPASSWD = None
1746
1747    # Si se solicita, mostrar ayuda.
1748    if len(sys.argv) > 1 and sys.argv[1] == "help":
1749        ogHelp(sys.argv[0], f"{sys.argv[0]} int_ndiskSecondStage int_partitionSecondStage [USER] [PASSWORD]",
1750                f"{sys.argv[0]} 1 1",
1751                f"{sys.argv[0]} 1 2 user clave")
1752        return
1753
1754    # Error si no se reciben 2 parámetros.
1755    if len(sys.argv) < 3:
1756        return ogRaiseError(OG_ERR_FORMAT, f"{sys.argv[0]} int_ndiskSecondStage int_partitionSecondStage [USER] [PASSWORD]")
1757
1758    # localizar disco segunda etapa del grub
1759    SECONDSTAGE = ogMount(int(sys.argv[1]), int(sys.argv[2]))
1760    if not SECONDSTAGE:
1761        return
1762
1763    GRUBGFC = subprocess.run(["ls", f"{SECONDSTAGE}/{{,boot/}}"
1764                                            "{{grubMBR,grubPARTITION}/boot/,}}"
1765                                            "{{grub{,2},{,efi/}EFI/*}}/"
1766                                            "{{menu.lst,grub.cfg,grub.cfg.backup.og}}"],
1767                                capture_output=True, text=True, shell=True).stdout.strip().split("\n")
1768
1769    # comprobamos que exista el archivo de configuración.
1770    if not GRUBGFC:
1771        return ogRaiseError(OG_ERR_NOTFOUND, "grub.cfg")
1772
1773    USER = sys.argv[3] if len(sys.argv) > 3 else "root"
1774    PASSWD = sys.argv[4] if len(sys.argv) > 4 else ""
1775
1776    ENCRYPTPASSWD = subprocess.run(["echo", "-e", f"{PASSWD}\n{PASSWD}"],
1777                                    capture_output=True, text=True).stdout.strip().split("\n")
1778    ENCRYPTPASSWD = subprocess.run(["grub-mkpasswd-pbkdf2"],
1779                                    input="\n".join(ENCRYPTPASSWD),
1780                                    capture_output=True, text=True).stdout.strip().split("\n")
1781    ENCRYPTPASSWD = subprocess.run(["sed", "-e", "1,2d", "-e", "s/^.*grub/grub/"],
1782                                    input="\n".join(ENCRYPTPASSWD),
1783                                    capture_output=True, text=True).stdout.strip()
1784
1785    for FILE in GRUBGFC:
1786        # Eliminamos configuración anterior
1787        subprocess.run(["sed", "-i", "-e", "/superusers/d", "-e", "/password_pbkdf2/d", FILE], check=True)
1788
1789        # Configuramos grub.cfg para que sólo permita editar o entrar en línea de comandos al usuario especificado
1790        if PASSWD != "":
1791            subprocess.run(["sed", "-i", f"1i\\password_pbkdf2 {USER} {ENCRYPTPASSWD}", FILE], check=True)
1792        subprocess.run(["sed", "-i", f"1i\\set superusers=\"{USER}\"", FILE], check=True)
1793
1794        # Permitimos que se seleccionen las entradas
1795        subprocess.run(["sed", "-i", "/\"menuentry \"/s/\"{\"/--unrestricted {\"/", FILE], check=True)
1796
1797def ogGrubSetTheme():
1798    # Si se solicita, mostrar ayuda.
1799    if len(sys.argv) > 1 and sys.argv[1] == "help":
1800        ogHelp(sys.argv[0], f"{sys.argv[0]} int_ndiskSecondStage int_partitionSecondStage str_themeName",
1801                f"{sys.argv[0]} 1 4 ThemeBasic",
1802                f"{sys.argv[0]} $(ogFindCache) ThemeBasic")
1803        return
1804    ogBootLoaderSetTheme(*sys.argv[1:])
1805    return
1806
1807def ogBurgSetTheme():
1808    # Si se solicita, mostrar ayuda.
1809    if len(sys.argv) > 1 and sys.argv[1] == "help":
1810        ogHelp(sys.argv[0], f"{sys.argv[0]} int_ndiskSecondStage int_partitionSecondStage str_themeName",
1811                f"{sys.argv[0]} 1 4 ThemeBasic",
1812                f"{sys.argv[0]} $(ogFindCache) ThemeBasic")
1813        print("Temas disponibles:", os.listdir(f"{OGLIB}/boot/burg/themes/"))
1814        return
1815    ogBootLoaderSetTheme(*sys.argv[1:])
1816    return
1817
1818def ogRefindSetTheme():
1819    PART = None
1820    DIRTHEME = None
1821    CFGFILE = None
1822
1823    # Si se solicita, mostrar ayuda.
1824    if len(sys.argv) > 1 and sys.argv[1] == "help":
1825        ogHelp(sys.argv[0], f"{sys.argv[0]} str_themeName",
1826                f"{sys.argv[0]} ThemeBasic")
1827        print(f"\nThemes in {OGLIB}/refind:\n{os.listdir(f'{OGLIB}/refind/themes/')}")
1828        return
1829
1830    # Detectamos partición ESP
1831    EFIDISK, EFIPART = ogGetEsp().split()
1832    PART = ogMount(int(EFIDISK), int(EFIPART))
1833    if not PART:
1834        return
1835
1836    DIRTHEME = f"{PART}/EFI/refind/themes"
1837    CFGFILE = f"{PART}/EFI/refind/refind.conf"
1838
1839    # Para utilizar ogBootLoaderSetTheme es necesario la entrada set theme_name
1840    if os.path.isfile(CFGFILE):
1841        subprocess.run(["sed", "-i", "1 i\\set theme_name=none", CFGFILE], check=True)
1842    else:
1843        return ogRaiseError(OG_ERR_NOTFOUND, CFGFILE)
1844
1845    # Creamos el directorio para los temas
1846    if not os.path.isdir(DIRTHEME):
1847        os.makedirs(DIRTHEME)
1848
1849    ogBootLoaderSetTheme(EFIDISK, EFIPART, *sys.argv[1:])
1850    return
1851
1852def ogBootLoaderSetTheme():
1853    # Variables locales.
1854    PART = None
1855    CFGFILE = None
1856    THEME = None
1857    NEWTHEME = None
1858    BOOTLOADER = None
1859    MSG = None
1860    NEWTHEMECFG = None
1861
1862    # Si se solicita, mostrar ayuda.
1863    if len(sys.argv) > 1 and sys.argv[1] == "help":
1864        ogHelp(sys.argv[0], f"{sys.argv[0]} int_ndiskSecondStage int_partitionSecondStage str_themeName",
1865                f"{sys.argv[0]} 1 4 ThemeBasic",
1866                f"{sys.argv[0]} $(ogFindCache) ThemeBasic")
1867        return
1868
1869    NEWTHEME = sys.argv[3]
1870
1871    # Nombre de la función que llama a esta.
1872    FUNC = sys._getframe().f_back.f_code.co_name
1873    FUNC = FUNC.split()[1]
1874
1875    # Error si no se reciben 3 parametros.
1876    if len(sys.argv) < 4:
1877        return ogRaiseError(OG_ERR_FORMAT, f"{sys.argv[0]} int_ndiskSecondStage int_partitionSecondStage str_themeName")
1878
1879    # Error si no puede montar sistema de archivos.
1880    PART = ogMount(int(sys.argv[1]), int(sys.argv[2]))
1881    if not PART:
1882        return
1883
1884    # La función debe ser llamada desde ogGrubSetTheme, ogBurgSetTheme or ogRefindSetTheme.
1885    if FUNC == "ogGrubSetTheme":
1886        BOOTLOADER = "grub"
1887        BOOTLOADERDIR = "boot/grubMBR"
1888        CFGFILE = f"{PART}/boot/grubMBR/boot/grub/grub.cfg"
1889        return ogRaiseError(OG_ERR_FORMAT, "ogGrubSetTheme not supported")
1890    elif FUNC == "ogBurgSetTheme":
1891        BOOTLOADER = "burg"
1892        BOOTLOADERDIR = "boot/burg"
1893        CFGFILE = f"{PART}/boot/burg/burg.cfg"
1894    elif FUNC == "ogRefindSetTheme":
1895        BOOTLOADER = "refind"
1896        BOOTLOADERDIR = "EFI/refind"
1897        CFGFILE = f"{PART}/EFI/refind/refind.conf"
1898    else:
1899        return ogRaiseError(OG_ERR_FORMAT, "Use ogGrubSetTheme, ogBurgSetTheme or ogRefindSetTheme.")
1900
1901    # Comprobamos que exista fichero de configuración
1902    if not os.path.isfile(CFGFILE):
1903        return ogRaiseError(OG_ERR_NOTFOUND, CFGFILE)
1904
1905    # Detectamos cual es el tema asignado
1906    with open(CFGFILE, "r") as f:
1907        lines = f.readlines()
1908    for line in lines:
1909        if line.startswith("set theme_name="):
1910            THEME = line.split("=")[1].strip()
1911            break
1912
1913    # Si no existe entrada de theme_name nos salimos
1914    if not THEME:
1915        return ogRaiseError(OG_ERR_NOTFOUND, f"theme_name in {CFGFILE}")
1916
1917    # Actualizamos el tema del servidor a la particion
1918    if os.path.isdir(f"{OGLIB}/{BOOTLOADER}/themes/{NEWTHEME}"):
1919        # Para refind es necesario que exista theme.conf en el directorio del tema.
1920        if BOOTLOADER == "refind":
1921            NEWTHEMECFG = f"{OGLIB}/{BOOTLOADER}/themes/{NEWTHEME}/theme.conf"
1922            if not os.path.isfile(NEWTHEMECFG):
1923                return ogRaiseError(OG_ERR_NOTFOUND, "theme.conf")
1924            with open(NEWTHEMECFG, "r") as f:
1925                theme_lines = f.readlines()
1926            with open(CFGFILE, "a") as f:
1927                for line in theme_lines:
1928                    if not line.startswith("#"):
1929                        f.write(line)
1930            # eliminamos "set theme" es de grub y no de refind
1931            subprocess.run(["sed", "-i", "/theme_name/d", CFGFILE], check=True)
1932        shutil.copytree(f"{OGLIB}/{BOOTLOADER}/themes/{NEWTHEME}", f"{PART}/{BOOTLOADERDIR}/themes/")
1933
1934    # Verificamos que el tema esta en la particion
1935    if not os.path.isdir(f"{PART}/{BOOTLOADERDIR}/themes/{NEWTHEME}"):
1936        return ogRaiseError(OG_ERR_NOTFOUND, f"theme_name={NEWTHEME} in {PART}/{BOOTLOADERDIR}/themes/")
1937
1938    # Cambiamos la entrada el fichero de configuración.
1939    subprocess.run(["sed", "-i", f"s/set theme_name={THEME}/set theme_name={NEWTHEME}/g", CFGFILE], check=True)
1940
1941def ogGrubSetAdminKeys():
1942    # Si se solicita, mostrar ayuda.
1943    if len(sys.argv) > 1 and sys.argv[1] == "help":
1944        ogHelp(sys.argv[0], f"{sys.argv[0]} int_ndiskSecondStage int_partitionSecondStage str_bolean",
1945                f"{sys.argv[0]} 1 4 FALSE",
1946                f"{sys.argv[0]} $(ogFindCache) ThemeBasic")
1947        return
1948    ogBootLoaderSetAdminKeys(*sys.argv[1:])
1949    return
1950
1951def ogBurgSetAdminKeys():
1952    # Si se solicita, mostrar ayuda.
1953    if len(sys.argv) > 1 and sys.argv[1] == "help":
1954        ogHelp(sys.argv[0], f"{sys.argv[0]} int_ndiskSecondStage int_partitionSecondStage str_bolean",
1955                f"{sys.argv[0]} 1 4 TRUE",
1956                f"{sys.argv[0]} $(ogFindCache) FALSE")
1957        return
1958    ogBootLoaderSetAdminKeys(*sys.argv[1:])
1959    return
1960
1961def ogBootLoaderSetAdminKeys():
1962    # Variables locales.
1963    PART = None
1964    CFGFILE = None
1965    BOOTLOADER = None
1966    BOOTLOADERDIR = None
1967
1968    # Si se solicita, mostrar ayuda.
1969    if len(sys.argv) > 1 and sys.argv[1] == "help":
1970        ogHelp(sys.argv[0], f"{sys.argv[0]} int_ndiskSecondStage int_partitionSecondStage str_bolean",
1971                f"{sys.argv[0]} 1 4 TRUE",
1972                f"{sys.argv[0]} $(ogFindCache) FALSE")
1973        return
1974
1975    # Nombre de la función que llama a esta.
1976    FUNC = sys._getframe().f_back.f_code.co_name
1977    FUNC = FUNC.split()[1]
1978
1979    # Error si no se reciben 3 parametros.
1980    if len(sys.argv) < 4:
1981        return ogRaiseError(OG_ERR_FORMAT, f"{sys.argv[0]} int_ndiskSecondStage int_partitionSecondStage str_bolean")
1982
1983    # Error si no puede montar sistema de archivos.
1984    PART = ogMount(int(sys.argv[1]), int(sys.argv[2]))
1985    if not PART:
1986        return
1987
1988    # La función debe ser llamada desde ogGrubSetAdminKeys or ogBurgSetAdminKeys.
1989    if FUNC == "ogGrubSetAdminKeys":
1990        BOOTLOADER = "grub"
1991        BOOTLOADERDIR = "grubMBR"
1992        CFGFILE = f"{PART}/boot/grubMBR/boot/grub/grub.cfg"
1993        return ogRaiseError(OG_ERR_FORMAT, "ogGrubSetAdminKeys not supported")
1994    elif FUNC == "ogBurgSetAdminKeys":
1995        BOOTLOADER = "burg"
1996        BOOTLOADERDIR = "burg"
1997        CFGFILE = f"{PART}/boot/burg/burg.cfg"
1998    else:
1999        return ogRaiseError(OG_ERR_FORMAT, "Use ogGrubSetAdminKeys")
2000
2001    # Comprobamos que exista fichero de configuración
2002    if not os.path.isfile(CFGFILE):
2003        return ogRaiseError(OG_ERR_NOTFOUND, CFGFILE)
2004
2005    if sys.argv[3].lower() == "true":
2006        shutil.move(f"{OGCAC}/boot/{BOOTLOADERDIR}/themes/conf.d/10_hotkey.disabled", f"{OGCAC}/boot/{BOOTLOADERDIR}/themes/conf.d/10_hotkey")
2007    elif sys.argv[3].lower() == "false":
2008        shutil.move(f"{OGCAC}/boot/{BOOTLOADERDIR}/themes/conf.d/10_hotkey", f"{OGCAC}/boot/{BOOTLOADERDIR}/themes/conf.d/10_hotkey.disabled")
2009    else:
2010        return ogRaiseError(OG_ERR_FORMAT, "str bolean unknown")
2011   
2012def ogGrubSetTimeOut():
2013    # Si se solicita, mostrar ayuda.
2014    if len(sys.argv) > 1 and sys.argv[1] == "help":
2015        ogHelp(sys.argv[0], f"{sys.argv[0]} int_ndiskSecondStage int_partitionSecondStage int_timeout_seconds",
2016                f"{sys.argv[0]} 1 4 50",
2017                f"{sys.argv[0]} $(ogFindCache) 50")
2018        return
2019    ogBootLoaderSetTimeOut(*sys.argv[1:])
2020    return
2021
2022def ogBurgSetTimeOut():
2023    # Si se solicita, mostrar ayuda.
2024    if len(sys.argv) > 1 and sys.argv[1] == "help":
2025        ogHelp(sys.argv[0], f"{sys.argv[0]} int_ndiskSecondStage int_partitionSecondStage str_timeout_seconds",
2026                f"{sys.argv[0]} 1 4 50",
2027                f"{sys.argv[0]} $(ogFindCache) 50")
2028        return
2029    ogBootLoaderSetTimeOut(*sys.argv[1:])
2030    return
2031
2032def ogRefindSetTimeOut():
2033    EFIDISK, EFIPART = ogGetEsp().split()
2034    # Si se solicita, mostrar ayuda.
2035    if len(sys.argv) > 1 and sys.argv[1] == "help":
2036        ogHelp(sys.argv[0], f"{sys.argv[0]} int_timeout_seconds",
2037                f"{sys.argv[0]} 50")
2038        return
2039    ogBootLoaderSetTimeOut(EFIDISK, EFIPART, *sys.argv[1:])
2040    return
2041
2042def ogBootLoaderSetTimeOut():
2043    # Variables locales.
2044    PART = None
2045    CFGFILE = None
2046    TIMEOUT = None
2047    BOOTLOADER = None
2048    BOOTLOADERDIR = None
2049    MSG = None
2050
2051    # Si se solicita, mostrar ayuda.
2052    if len(sys.argv) > 1 and sys.argv[1] == "help":
2053        ogHelp(sys.argv[0], f"{sys.argv[0]} int_ndiskSecondStage int_partitionSecondStage int_timeout_seconds",
2054                f"{sys.argv[0]} 1 4 50",
2055                f"{sys.argv[0]} $(ogFindCache) 50")
2056        return
2057
2058    # Nombre de la función que llama a esta.
2059    FUNC = sys._getframe().f_back.f_code.co_name
2060    FUNC = FUNC.split()[1]
2061
2062    # Error si no se reciben 3 parametros.
2063    if len(sys.argv) < 4:
2064        return ogRaiseError(OG_ERR_FORMAT, f"{sys.argv[0]} int_ndiskSecondStage int_partitionSecondStage int_timeout_seconds")
2065
2066    # Error si no puede montar sistema de archivos.
2067    PART = ogMount(int(sys.argv[1]), int(sys.argv[2]))
2068    if not PART:
2069        return
2070
2071    # La función debe ser llamada desde ogGrubSetTimeOut, ogBurgSetTimeOut or ogRefindSetTimeOut.
2072    if FUNC == "ogGrubSetTimeOut":
2073        BOOTLOADER = "grub"
2074        BOOTLOADERDIR = "boot/grubMBR"
2075        CFGFILE = f"{PART}/boot/grubMBR/boot/grub/grub.cfg"
2076    elif FUNC == "ogBurgSetTimeOut":
2077        BOOTLOADER = "burg"
2078        BOOTLOADERDIR = "boot/burg"
2079        CFGFILE = f"{PART}/boot/burg/burg.cfg"
2080    elif FUNC == "ogRefindSetTimeOut":
2081        BOOTLOADER = "refind"
2082        BOOTLOADERDIR = "EFI/refind"
2083        CFGFILE = f"{PART}/EFI/refind/refind.conf"
2084    else:
2085        return ogRaiseError(OG_ERR_FORMAT, "Use ogGrubSetTimeOut, ogBurgSetTimeOut or ogRefindSetTimeOut.")
2086
2087    # Comprobamos que exista fichero de configuración
2088    if not os.path.isfile(CFGFILE):
2089        return ogRaiseError(OG_ERR_NOTFOUND, CFGFILE)
2090
2091    # Asignamos el timeOut.
2092    if BOOTLOADER == "refind":
2093        subprocess.run(["sed", "-i", f"s/timeout.*$/timeout {sys.argv[3]}/g", CFGFILE], check=True)
2094    else:
2095        subprocess.run(["sed", "-i", f"s/timeout=.*$/timeout={sys.argv[3]}/g", CFGFILE], check=True)
2096
2097def ogGrubSetResolution():
2098    # Si se solicita, mostrar ayuda.
2099    if len(sys.argv) > 1 and sys.argv[1] == "help":
2100        ogHelp(sys.argv[0], f"{sys.argv[0]} int_ndiskSecondStage int_partitionSecondStage [str_resolution]",
2101                f"{sys.argv[0]} 1 4 1024x768",
2102                f"{sys.argv[0]} $(ogFindCache) 1024x768",
2103                f"{sys.argv[0]} 1 4")
2104        return
2105    ogBootLoaderSetResolution(*sys.argv[1:])
2106    return
2107
2108def ogBurgSetResolution():
2109    # Si se solicita, mostrar ayuda.
2110    if len(sys.argv) > 1 and sys.argv[1] == "help":
2111        ogHelp(sys.argv[0], f"{sys.argv[0]} int_ndiskSecondStage int_partitionSecondStage [str_resolution]",
2112                f"{sys.argv[0]} 1 4 1024x768",
2113                f"{sys.argv[0]} $(ogFindCache) 1024x768",
2114                f"{sys.argv[0]} 1 4")
2115        return
2116    ogBootLoaderSetResolution(*sys.argv[1:])
2117    return
2118
2119def ogBootLoaderSetResolution():
2120    # Variables locales.
2121    PART = None
2122    CFGFILE = None
2123    RESOLUTION = None
2124    NEWRESOLUTION = None
2125    DEFAULTRESOLUTION = "1024x768"
2126    BOOTLOADER = None
2127    BOOTLOADERDIR = None
2128    MSG = None
2129
2130    # Si se solicita, mostrar ayuda.
2131    if len(sys.argv) > 1 and sys.argv[1] == "help":
2132        ogHelp(sys.argv[0], f"{sys.argv[0]} int_ndiskSecondStage int_partitionSecondStage [str_resolution]",
2133                f"{sys.argv[0]} 1 4 1024x768",
2134                f"{sys.argv[0]} $(ogFindCache) 1024x768",
2135                f"{sys.argv[0]} 1 4")
2136        return
2137
2138    # Nombre de la función que llama a esta.
2139    FUNC = sys._getframe().f_back.f_code.co_name
2140    FUNC = FUNC.split()[1]
2141
2142    # Error si no se reciben 2 parametros.
2143    if len(sys.argv) < 3:
2144        return ogRaiseError(OG_ERR_FORMAT, f"{sys.argv[0]} int_ndiskSecondStage int_partitionSecondStage [str_resolution]")
2145
2146    # Error si no puede montar sistema de archivos.
2147    PART = ogMount(int(sys.argv[1]), int(sys.argv[2]))
2148    if not PART:
2149        return
2150
2151    # La función debe ser llamada desde ogGrubSetResolution, ogBurgSetResolution or ogRefindSetResolution.
2152    if FUNC == "ogGrubSetResolution":
2153        BOOTLOADER = "grub"
2154        BOOTLOADERDIR = "boot/grubMBR"
2155        CFGFILE = f"{PART}/boot/grubMBR/boot/grub/grub.cfg"
2156        return ogRaiseError(OG_ERR_FORMAT, "ogGrubSetResolution not supported")
2157    elif FUNC == "ogBurgSetResolution":
2158        BOOTLOADER = "burg"
2159        BOOTLOADERDIR = "boot/burg"
2160        CFGFILE = f"{PART}/boot/burg/burg.cfg"
2161    else:
2162        return ogRaiseError(OG_ERR_FORMAT, "Use ogGrubSetResolution, ogBurgSetResolution or ogRefindSetResolution.")
2163
2164    DEFAULTRESOLUTION = "1024x768"
2165
2166    # Comprobamos que exista fichero de configuración
2167    if not os.path.isfile(CFGFILE):
2168        return ogRaiseError(OG_ERR_NOTFOUND, CFGFILE)
2169
2170    # Controlar variable a considerar vga (default template) o video (menu)
2171    # Si solo dos parametros autoconfiguracion basado en el parametro vga de las propiedad menu. si no hay menu asignado es 788 por defecto
2172    if len(sys.argv) == 3:
2173        if "video" in globals() and video:
2174            NEWRESOLUTION = video.split(":")[1].split("-")[0]
2175        if "vga" in globals() and vga:
2176            if vga in ["788", "789", "814"]:
2177                NEWRESOLUTION = "800x600"
2178            elif vga in ["791", "792", "824"]:
2179                NEWRESOLUTION = "1024x768"
2180            elif vga == "355":
2181                NEWRESOLUTION = "1152x864"
2182            elif vga in ["794", "795", "829"]:
2183                NEWRESOLUTION = "1280x1024"
2184    elif len(sys.argv) == 4:
2185        # Comprobamos que el parametro 3 cumple formato NNNNxNNNN
2186        if re.match(r"[0-9]{3,4}[x][0-9]{3,4}$", sys.argv[3]):
2187            NEWRESOLUTION = sys.argv[3]
2188        else:
2189            return ogRaiseError(OG_ERR_FORMAT, "param 3 is not a valid resolution: 800x600, 1024x768, 1152x864, 1280x1024, 1600x1200")
2190
2191    # Si no existe NEWRESOLUTION asignamos la DEFAULTRESOLUTION
2192    if not NEWRESOLUTION:
2193        NEWRESOLUTION = DEFAULTRESOLUTION
2194
2195    # Cambiamos la entrada el fichero de configuración.
2196    subprocess.run(["sed", "-i", f"s/gfxmode=.*$/gfxmode={NEWRESOLUTION}/g", CFGFILE], check=True)
2197
2198def ogRefindSetResolution():
2199    # Variables locales.
2200    PART = None
2201    CFGFILE = None
2202
2203    # Si se solicita, mostrar ayuda.
2204    if len(sys.argv) > 1 and sys.argv[1] == "help":
2205        ogHelp(sys.argv[0], f"{sys.argv[0]} int_resolution1 [int_resolution2]",
2206                f"{sys.argv[0]} 1366 768",
2207                f"{sys.argv[0]} 1")
2208        return
2209
2210    # Error si no se reciben 2 parametros.
2211    if len(sys.argv) < 2:
2212        return ogRaiseError(OG_ERR_FORMAT, f"{sys.argv[0]} int_resolution1 [int_resolution2]")
2213
2214    # Error si no puede montar sistema de archivos.
2215    PART = ogMount(ogGetEsp())
2216    if not PART:
2217        return
2218
2219    # Comprobamos que exista fichero de configuración
2220    CFGFILE = f"{PART}/EFI/refind/refind.conf"
2221    if not os.path.isfile(CFGFILE):
2222        return ogRaiseError(OG_ERR_NOTFOUND, CFGFILE)
2223
2224    # Borramos resolucion anterior y configuramos la nueva
2225    subprocess.run(["sed", "-i", "/^resolution/d", CFGFILE], check=True)
2226    subprocess.run(["sed", "-i", f"1 i\\resolution {sys.argv[1]} {sys.argv[2]}", CFGFILE], check=True)
2227
2228def ogRefindInstall(bool_autoconfig):
2229    # Variables locales.
2230    CONFIG = bool_autoconfig
2231    EFIDISK, EFIPART = ogGetEsp().split()
2232    EFIDEVICE = ogDiskToDev(EFIDISK, EFIPART)
2233    EFIMNT = ogMount(EFIDISK, EFIPART)
2234    EFIDIR = f"{EFIMNT}/EFI"
2235    SHIM = ogGetPath("/usr/lib/shim/shimx64.efi.signed")
2236
2237    # Si se solicita, mostrar ayuda.
2238    if CONFIG == "help":
2239        ogHelp("ogRefindInstall", "ogRefindInstall boolean_autoconfig", "ogRefindInstall TRUE")
2240        return
2241
2242    # Error si no se reciben 2 parametros.
2243    if not bool_autoconfig:
2244        ogRaiseError(OG_ERR_FORMAT, "ogRefindInstall boolean_autoconfig")
2245        return
2246
2247    # Error si no puede montar sistema de archivos.
2248    if not EFIMNT:
2249        ogRaiseError(OG_ERR_PARTITION, "mount ESP")
2250        return
2251
2252    # Comprobamos que exista shimx64
2253    if not SHIM:
2254        ogRaiseError(OG_ERR_NOTFOUND, "shimx64.efi.signed")
2255        return
2256
2257    # Si existe configuración anterior de refind la borro
2258    if os.path.isdir(f"{EFIDIR}/refind"):
2259        shutil.rmtree(f"{EFIDIR}/refind")
2260
2261    # Instalamos rEFInd.
2262    subprocess.run(["refind-install", "--yes", "--alldrivers", "--root", EFIMNT, "--shim", SHIM])
2263
2264    # Firmo refind con certificado de OpenGnsys
2265    shutil.move(f"{EFIDIR}/refind/grubx64.efi", f"{EFIDIR}/refind/grubx64.efi-unsigned")
2266    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"])
2267
2268    # Copio los certificados
2269    shutil.copytree("/etc/refind.d/keys", f"{EFIDIR}/refind/keys")
2270    # Copio certificado opengnsys
2271    shutil.copy(f"{OGETC}/ssl/certs/opengnsys.*", f"{EFIDIR}/refind/keys")
2272
2273    # Ponemos la entrada en NVRAM en el segundo lugar del orden de arranque
2274    NEWORDER = ogNvramGetOrder().split(",")
2275    NEWORDER[0], NEWORDER[1] = NEWORDER[1], NEWORDER[0]
2276    ogNvramSetOrder(",".join(NEWORDER))
2277
2278    # Borramos configuración linux
2279    if os.path.isfile(f"{EFIMNT}/boot/refind_linux.conf"):
2280        shutil.move(f"{EFIMNT}/boot/refind_linux.conf", f"{EFIMNT}/boot/refind_linux.conf.ogbackup")
2281
2282    # Eliminamos punto de montaje (por si ejecutamos más de una vez)
2283    subprocess.run(["umount", f"{EFIMNT}/boot/efi"])
2284
2285    # Para la configuración del ogLive
2286    ogMountCache()
2287    if ogMountCache() == 0:
2288        # Detectamos si hay ogLive
2289        CACHEDEVICE = ogDiskToDev(ogFindCache())
2290        OGLIVE = glob.glob(f"{OGCAC}/boot/ogvmlinuz*")[0]
2291        # Obtenemos parametros del kernel y sustituimos root
2292        # La línea de opciones no puede contener la cadena initrd.
2293        CMDLINE = " ".join(sys.argv[3:])
2294        CMDLINE = f"root={CACHEDEVICE} {CMDLINE.replace('ogvmlinuz', '')}"
2295
2296        # Icono para la entrada de menú
2297        OGICON = glob.glob(f"{OGLIB}/refind/icons/so_opengnsys.png")
2298        OGICON = OGICON[0] if OGICON else f"{EFIDIR}/refind/icons/os_unknown.png"
2299        shutil.copy(OGICON, f"{OGCAC}/.VolumeIcon.png")
2300
2301    # Configuramos rEFInd si es necesario
2302    CFGFILE = f"{EFIDIR}/refind/refind.conf"
2303    if CONFIG == "TRUE":
2304        with open(CFGFILE, "a") as f:
2305            f.write("\n\n# Configuración OpenGnsys\n")
2306            # Excluimos dispositivos distintos de ESP y CACHE
2307            DEVICES = subprocess.run(["blkid", "-s", "PARTUUID"], capture_output=True, text=True).stdout
2308            DEVICES = DEVICES.split("\n")
2309            DEVICES = [device.split("=")[1].replace('"', '') for device in DEVICES if device]
2310            DEVICES = [device for device in DEVICES if device != EFIDEVICE and device != CACHEDEVICE]
2311            DEVICES = " ".join(DEVICES)
2312            f.write(f"dont_scan_volumes {DEVICES}\n")
2313            # Excluimos en la ESP los directorios de los sistemas operativos
2314            f.write("dont_scan_dirs EFI/microsoft,EFI/ubuntu,EFI/grub\n")
2315            f.write("use_graphics_for osx,linux,windows\n")
2316            f.write("showtools reboot, shutdown\n")
2317
2318        # Configuramos ogLive
2319        if OGLIVE:
2320            # Cambiamos nombre de kernel e initrd para que lo detecte refind
2321            OGLIVEDIR = os.path.dirname(OGLIVE)
2322            shutil.copy(OGLIVE, f"{OGLIVE}.efi")
2323            shutil.copy(f"{OGLIVEDIR}/oginitrd.img", f"{OGLIVEDIR}/initrd.img")
2324
2325            # Incluimos el directorio de ogLive.
2326            with open(CFGFILE, "a") as f:
2327                f.write(f"also_scan_dirs +,boot/{os.path.basename(OGLIVEDIR)}\n")
2328            # Fichero de configuración de refind para kernel de linux.
2329            LNXCFGFILE = f"{OGLIVEDIR}/refind_linux.conf"
2330            with open(LNXCFGFILE, "w") as f:
2331                f.write(f"\"OpenGnsys Live\" \"{CMDLINE}\"\n")
2332
2333            # Ponemos ogLive como la entrada por defecto
2334            NUMENTRY = len(glob.glob(f"{EFIDIR}/Part-??-??"))
2335            with open(CFGFILE, "a") as f:
2336                f.write(f"default_selection {NUMENTRY+1}\n")
2337    else:
2338        # Renombramos la configuración por defecto
2339        shutil.move(CFGFILE, f"{CFGFILE}.auto")
2340
2341        # Creamos nueva configuración
2342        with open(CFGFILE, "w") as f:
2343            f.write("# Configuración OpenGnsys\n")
2344            f.write("timeout 20\n")
2345            f.write("showtools reboot, shutdown\n")
2346            f.write("\nscanfor manual\n")
2347            # Configuración para sistemas restaurados con OpenGnsys
2348            for DIR in glob.glob("/mnt/sda1/EFI/Part-*-*"):
2349                DIRNAME = os.path.basename(DIR)
2350                f.write(f"menuentry \"{DIRNAME}\" {{\n")
2351                f.write(f"    loader /EFI/{DIRNAME}/Boot/ogloader.efi\n")
2352                if os.path.isfile(f"{DIR}/Boot/bootmgfw.efi"):
2353                    f.write("    icon /EFI/refind/icons/os_win8.png\n")
2354                if os.path.isfile(f"{DIR}/Boot/grubx64.efi"):
2355                    f.write("    icon /EFI/refind/icons/os_linux.png\n")
2356                f.write("}\n")
2357            # Configuración ogLive si secureboot no está activado
2358            if "secureboot" not in subprocess.run(["dmesg"], capture_output=True, text=True).stdout:
2359                if OGLIVE:
2360                    f.write("menuentry \"OpenGnsys Live\" {\n")
2361                    f.write("    volume CACHE\n")
2362                    f.write("    ostype Linux\n")
2363                    f.write(f"    loader /boot/{os.path.basename(os.path.dirname(OGLIVE))}/ogvmlinuz\n")
2364                    f.write(f"    initrd /boot/{os.path.basename(os.path.dirname(OGLIVE))}/oginitrd.img\n")
2365                    f.write(f"    options \"{CMDLINE}\"\n")
2366                    f.write("}\n")
2367
2368                    # Ponemos ogLive como la entrada por defecto
2369                    subprocess.run(["sed", "-i", "1 i\default_selection \"OpenGnsys Live\"", CFGFILE], check=True)
2370
2371def ogGrub4dosInstallMbr():
2372    # Variables locales.
2373    DISK = None
2374    PART = None
2375    DEVICE = None
2376    MOUNTDISK = None
2377    GRUBDISK = None
2378    BINBDIR = None
2379
2380    # Si se solicita, mostrar ayuda.
2381    if len(sys.argv) > 1 and sys.argv[1] == "help":
2382        ogHelp(sys.argv[0], f"{sys.argv[0]} int_ndisk int_part",
2383                f"{sys.argv[0]} 1 1")
2384        return
2385
2386    # Error si no se recibe 2 parámetros.
2387    if len(sys.argv) < 3:
2388        return ogRaiseError(OG_ERR_FORMAT, f"{sys.argv[0]} int_ndisk int_part")
2389
2390    DISK = sys.argv[1]
2391    PART = sys.argv[2]
2392
2393    # Controlar existencia de disco y particion
2394    DEVICE = ogDiskToDev(DISK)
2395    if not DEVICE:
2396        return ogRaiseError(OG_ERR_NOTFOUND)
2397    MOUNTDISK = ogMount(DISK, PART)
2398    if not MOUNTDISK:
2399        return ogRaiseError(OG_ERR_PARTITION)
2400
2401    # Controlar acceso de escritura a la particion
2402    if ogIsReadonly(DISK, PART):
2403        return ogRaiseError(OG_ERR_NOTWRITE, f": {DISK} {PART}")
2404
2405    # Controlar disco no uefi
2406    if ogIsEfiActive():
2407        return ogRaiseError(OG_ERR_NOTBIOS, ": grub4dos solo soporta PC con bios legacy")
2408
2409    # Controlar particionado tipo msdos
2410    if not ogCheckStringInGroup(ogGetPartitionTableType(DISK), "MSDOS"):
2411        return ogRaiseError(OG_ERR_NOMSDOS, ": grub2dos requiere particionado tipo MSDOS")
2412
2413    # Controlar la existencia del grub4dos con acceso a ntfs
2414    BINDIR = f"{OGLIB}/grub4dos/grub4dos-0.4.6a"
2415    if not os.path.isfile(f"{BINDIR}/bootlace.com"):
2416        return ogRaiseError(OG_ERR_NOTFOUND, f": {BINDIR}/bootlace.com")
2417
2418    # instalar el bootloader de grlrd en el MBR
2419    subprocess.run([f"{BINDIR}/bootlace64.com", DEVICE], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
2420
2421    # copiar grld a la particion
2422    shutil.copy(f"{BINDIR}/grldr", MOUNTDISK)
2423
2424    # Instalar y configurar grub4dos
2425    if os.path.isfile(f"{MOUNTDISK}/boot/grub/menu.lst"):
2426        os.remove(f"{MOUNTDISK}/boot/grub/menu.lst")
2427        os.rmdir(f"{MOUNTDISK}/boot/grub")
2428
2429    if not os.path.isfile(f"{MOUNTDISK}/boot/grub/menu.lst"):
2430        os.makedirs(f"{MOUNTDISK}/boot/grub")
2431        with open(f"{MOUNTDISK}/boot/grub/menu.lst", "w") as f:
2432            GRUBDISK = int(DISK) - 1
2433            f.write(f"##NO-TOCAR-ESTA-LINEA MBR\n")
2434            f.write(f"timeout 0\n")
2435            f.write(f"title  MBR\n")
2436            f.write(f"root (hd{GRUBDISK},0)\n")
2437            f.write(f"chainloader (hd{GRUBDISK},0)+1\n")
2438            f.write(f"boot\n")
Note: See TracBrowser for help on using the repository browser.