refs #1699 add ogBoot
parent
7165dd552a
commit
caec7bfc08
|
@ -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)
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in New Issue