refs #1699 add ogBoot

pull/5/head
Natalia Serrano 2025-03-19 11:30:19 +01:00
parent 7165dd552a
commit caec7bfc08
3 changed files with 219 additions and 11 deletions

View File

@ -0,0 +1,45 @@
#!/usr/bin/python3
import sys
import argparse
from SystemLib import ogHelp
from BootLib import ogBoot
if 2 == len (sys.argv) and 'help' == sys.argv[1]:
#parser.print_help() sale en inglés aunque la locale indique otra cosa
ogHelp ('ogBoot', 'ogBoot int_ndisk int_nfilesys [ NVRAMPERM ] [str_kernel str_initrd str_kernelparams]', ['ogBoot 1 2 "/boot/vmlinuz /boot/initrd.img root=/dev/sda2 ro"', 'ogBoot 1 2 NVRAMPERM'])
sys.exit (0)
parser = argparse.ArgumentParser (add_help=False)
if 3 == len (sys.argv):
parser.add_argument ('disk')
parser.add_argument ('par')
elif 4 == len (sys.argv):
parser.add_argument ('disk')
parser.add_argument ('par')
parser.add_argument ('nvramperm_or_params')
elif 5 == len (sys.argv):
parser.add_argument ('disk')
parser.add_argument ('par')
parser.add_argument ('nvramperm')
parser.add_argument ('params')
args = parser.parse_args()
if 3 == len (sys.argv):
ret = ogBoot (args.disk, args.par)
elif 4 == len (sys.argv):
if 'NVRAMPERM' == args.nvramperm_or_params.upper():
nvramperm = True
params = ''
else:
nvramperm = False
params = args.nvramperm_or_params
ret = ogBoot (args.disk, args.par, nvramperm, params)
elif 5 == len (sys.argv):
ret = ogBoot (args.disk, args.par, not not args.nvramperm, args.params)
if ret is not None:
if ret == True: sys.exit (0)
elif ret == False: sys.exit (1)
else: print (ret)

View File

@ -39,6 +39,168 @@ import CacheLib
#@note En Linux, si no se indican los parámetros de arranque se detectan de la opción por defecto del cargador GRUB.
#@note En Linux, debe arrancarse la partición del directorio \c /boot
#*/ ##
def ogBoot (disk, par, nvramperm=False, params=''):
# Detectar tipo de sistema de archivos y montarlo.
part = DiskLib.ogDiskToDev (disk, par)
if not part: return None
type = InventoryLib.ogGetOsType (disk, par)
if not type: return None
# Error si no puede montar sistema de archivos.
mntdir = FileSystemLib.ogMount (disk, par)
if not mntdir: return None
#params = None
#if 'NVRAMPERM' == nvramperm.upper():
# nvramperm = True
#else:
# params = nvramperm
# nvramperm = False
if 'Linux' == type or 'Android' == type:
# Si no se indican, obtiene los parámetros de arranque para Linux.
if not params:
params = ogLinuxBootParameters (disk, par)
# Si no existe y el UEFI buscar en particion ESP
if not params and InventoryLib.ogIsEfiActive():
esp = DiskLib.ogGetEsp()
efidisk, efipart = esp.split()
params = ogLinuxBootParameters (efidisk, efipart)
params += ' ' + esp
# Si no existe, buscar sistema de archivo /boot en /etc/fstab.
if not params and os.path.exists (f'{mntdir}/etc/fstab'):
# Localizar S.F. /boot en /etc/fstab del S.F. actual.
dev = None
with open (f'{mntdir}/etc/fstab', 'r') as fd:
while True:
l = fd.readline()
if not l: break
parts = l.split()
if '#' != parts[0] and '/boot' == parts[1]:
dev = parts[0]
break
if dev:
fstab_part = DiskLib.ogDevToDisk (dev)
else:
return None
# Montar S.F. de /boot.
fstab_disk, fstab_par = fstab_part.split()
mntdir = FileSystemLib.ogMount (fstab_disk, fstab_par)
if not mntdir: return None
# Buscar los datos de arranque.
params = ogLinuxBootParameters (fstab_disk, fstab_par)
kernel = initrd = append = None
if params:
kernel, initrd, append = params.split (maxsplit=2)
# Si no hay kernel, no hay sistema operativo.
if not kernel or not os.path.exists (f'{mntdir}/{kernel}'):
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTOS, f'{disk} {par} ({type})')
return None
# Arrancar de partición distinta a la original.
if os.path.exists (f'{mntdir}/etc'):
append = re.sub ('root=[-+=_/a-zA-Z0-9]* ', f'root={part} ', append)
# Comprobar tipo de sistema.
if InventoryLib.ogIsEfiActive():
# Comprobar si el Kernel está firmado.
file_out = subprocess.run (['file', '-k', f'{mntdir}/{kernel}'], capture_output=True, text=True).stdout
if not file_out or not 'EFI app' in file_out:
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTOS, f'{disk} {par} ({type}, EFI)')
return None
bootlabel = f'Part-{int(disk):02d}-{int(par):02d}'
bootloader = 'shimx64.efi'
# Obtener parcición EFI.
esp = DiskLib.ogGetEsp()
#efidisk, efipart = esp.split()
# TODO: Comprobamos que existe la BOOTLABEL, si no buscamos por sistema operativo
if '' == FileLib.ogGetPath (src=esp, file=f'EFI/{bootlabel}'):
osversion = InventoryLib.ogGetOsVersion (disk, par)
if 'SUSE' in osversion:
bootlabel = 'opensuse'
elif 'Fedora' in osversion:
bootlabel = 'fedora'
elif 'Ubuntu' in osversion:
bootlabel = 'ubuntu'
else:
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'{esp} Boot loader')
return None
# Crear orden de arranque (con unos valores por defecto).
UEFILib.ogNvramAddEntry (bootlabel, f'/EFI/{bootlabel}/Boot/{bootloader}', nvramperm)
# Marcar próximo arranque y reiniciar.
UEFILib.ogNvramSetNext (bootlabel)
subprocess.run (['reboot'])
else:
# Arranque BIOS: configurar kernel Linux con los parámetros leídos de su GRUB.
subprocess.run (['kexec', '-l', f'{mntdir}{kernel}', f'--append={append}', f'--initrd={mntdir}{initrd}'])
subprocess.Popen (['kexec', '-e'])
elif 'Windows' == type:
# Comprobar tipo de sistema.
if InventoryLib.ogIsEfiActive():
bootlabel = f'Part-{int(disk):02d}-{int(par):02d}'
# Obtener parcición EFI.
esp = DiskLib.ogGetEsp()
efidisk, efipart = esp.split()
if not efipart:
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, 'ESP')
return None
efidir = FileSystemLib.ogMount (efidisk, efipart)
if not efidir: return None
# Comprobar cargador (si no existe buscar por defecto en ESP).
loader = FileLib.ogGetPath (file=f'{efidir}/EFI/{bootlabel}/Boot/bootmgfw.efi')
if not loader:
bootlabel = 'Microsoft'
loader = FileLib.ogGetPath (file=f'{efidir}/EFI/Microsoft/Boot/bootmgfw.efi')
if not loader:
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTOS, f'{disk} {par} ({type}, EFI)')
return None
# Crear orden de arranque (con unos valores por defecto).
l = re.sub ('^.*EFI(.*)$', r'\1', loader)
UEFILib.ogNvramAddEntry (bootlabel, l, nvramperm)
# Marcar próximo arranque y reiniciar.
UEFILib.ogNvramSetNext (bootlabel)
subprocess.run (['reboot'])
else:
# Arranque BIOS: comprueba si hay un cargador de Windows.
for f in ['io.sys', 'ntldr', 'bootmgr']:
file = FileLib.ogGetPath (src=f'{disk} {par}', file=f)
if file: loader=f
if not loader:
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTOS, f'{disk} {par} ({type})')
return None
winboot = os.environ.get ('winboot', '')
if 'kexec' == winboot:
# Modo de arranque en caliente (con kexec).
for f in glob.glob (f'{ogGlobals.OGLIB}/grub4dos/*'):
shutil.copy2 (f, mntdir)
disk0 = int(disk)-1
par0 = int(par)-1
subprocess.run (['kexec', '-l', f'{mntdir}/grub.exe', '--append=--config-file=root (hd{disk0},{par0}); chainloader (hd{disk0},{par0})/{loader}; tpm --init'])
subprocess.Popen (['kexec', '-e'])
else:
# Modo de arranque por reinicio (con reboot).
subprocess.run (['dd', 'if=/dev/zero', f'of={mntdir}/ogboot.me', 'bs=1024', 'count=3'])
subprocess.run (['dd', 'if=/dev/zero', f'of={mntdir}/ogboot.firstboot', 'bs=1024', 'count=3'])
subprocess.run (['dd', 'if=/dev/zero', f'of={mntdir}/ogboot.secondboot', 'bs=1024', 'count=3'])
v = RegistryLib.ogGetRegistryValue (mntdir, 'SOFTWARE', r'\Microsoft\Windows\CurrentVersion\Run\ogcleannboot')
if not v:
RegistryLib.ogAddRegistryValue (mntdir, 'SOFTWARE', r'\Microsoft\Windows\CurrentVersion\Run\ogcleanboot')
RegistryLib.ogSetRegistryValue (mntdir, 'SOFTWARE', r'\Microsoft\Windows\CurrentVersion\Run\ogcleanboot', r'cmd /c del c:\ogboot.*')
# Activar la partición.
DiskLib.ogSetPartitionActive (disk, par)
subprocess.run (['reboot'])
elif 'MacOS' == type:
# Modo de arranque por reinicio.
# Nota: el cliente tiene que tener configurado correctamente Grub.
if not os.path.exists (f'{mntdir}/boot.mac'):
open (f'{mntdir}/boot.mac', 'w').close()
subprocess.run (['reboot'])
elif 'GrubLoader' == type:
# Reiniciar.
#subprocess.run (['reboot'])
pass
else:
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTOS, f'{disk} {par} ({type})')
return None
#/**
@ -492,6 +654,9 @@ def ogGrubInstallMbr (disk, par, checkos='FALSE', kernelparam=''):
if InventoryLib.ogIsEfiActive():
esp = DiskLib.ogGetEsp()
if not esp:
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, 'ESP')
return None
efidisk, efipart = esp.split()
# Comprobamos que exista ESP y el directorio para ubuntu
efisecondstage = FileSystemLib.ogMount (efidisk, efipart)

View File

@ -42,8 +42,8 @@ def ogNvramActiveEntry (entry):
numentries.append (words[0][4:8])
except ValueError:
for l in efibootmgr_out.splitlines():
words = l.split (maxsplit=1)
if len(words) < 2: continue
words = l.split (maxsplit=2)
if len(words) < 3: continue
if words[1] == entry:
numentries.append (words[0][4:8])
@ -135,8 +135,6 @@ def ogCopyEfiBootLoader (disk, par):
bootlabel = f'Part-{int(disk):02d}-{int(par):02d}'
osversion = InventoryLib.ogGetOsVersion (disk, par)
print (f'bootlabel ({bootlabel})')
print (f'osversion ({osversion})')
if 'Windows 1' in osversion:
loader = None
for i in f'{efidir}/EFI/Microsoft/Boot/bootmgfw.efi', f'{efidir}/EFI/{bootlabel}/Boot/bootmgfw.efi':
@ -180,8 +178,8 @@ def ogNvramDeleteEntry (entry):
numentries.append (words[0][4:8])
except ValueError:
for l in efibootmgr_out.splitlines():
words = l.split (maxsplit=1)
if len(words) < 2: continue
words = l.split (maxsplit=2)
if len(words) < 3: continue
if words[1] == entry:
numentries.append (words[0][4:8])
@ -325,8 +323,8 @@ def ogNvramInactiveEntry (entry):
numentries.append (words[0][4:8])
except ValueError:
for l in efibootmgr_out.splitlines():
words = l.split (maxsplit=1)
if len(words) < 2: continue
words = l.split (maxsplit=2)
if len(words) < 3: continue
if words[1] == entry:
numentries.append (words[0][4:8])
@ -487,8 +485,8 @@ def ogNvramSetNext (entry):
numentries.append (words[0][4:8])
except ValueError:
for l in efibootmgr_out.splitlines():
words = l.split (maxsplit=1)
if len(words) < 2: continue
words = l.split (maxsplit=2)
if len(words) < 3: continue
if words[1] == entry:
numentries.append (words[0][4:8])
@ -496,7 +494,7 @@ def ogNvramSetNext (entry):
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'NVRAM entry "{entry}"')
return
if 1 != len(numentries):
if 1 != len (numentries):
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_GENERIC, f'more than one entry found')
return