From 3e64d7377c1dcaf9e2372639a51e70a88870091b Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Wed, 11 Dec 2024 10:43:41 +0100 Subject: [PATCH] refs #1218 add all ogNvram...() functions --- client/lib/engine/bin/UEFILib.py | 313 +++++++++++++++++++++++++++++++ 1 file changed, 313 insertions(+) diff --git a/client/lib/engine/bin/UEFILib.py b/client/lib/engine/bin/UEFILib.py index ecfd411..1a979f6 100644 --- a/client/lib/engine/bin/UEFILib.py +++ b/client/lib/engine/bin/UEFILib.py @@ -21,6 +21,39 @@ import InventoryLib #@exception OG_ERR_NOTUEFI UEFI no activa. #@exception OG_ERR_NOTFOUND fichero o dispositivo no encontrado. #*/ ## +#ogNvramActiveEntry ('2') +#ogNvramActiveEntry ('Windows Boot Manager') +def ogNvramActiveEntry (entry): + if not InventoryLib.ogIsEfiActive(): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTUEFI, '') + return + + numentries = [] + efibootmgr_out = subprocess.run (['efibootmgr'], capture_output=True, text=True).stdout + try: + foo = int (entry, 16) ## raises ValueError if entry doesn't look like hexadecimal + num = f'{foo:04x}'.upper() + for l in efibootmgr_out.splitlines(): + words = l.split() + if len(words) < 2: continue + if num in words[0]: + numentries.append (words[0][4:8]) + except ValueError: + for l in efibootmgr_out.splitlines(): + words = l.split (maxsplit=1) + if len(words) < 2: continue + if words[1] == entry: + numentries.append (words[0][4:8]) + + if not numentries: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'NVRAM entry "{entry}"') + return + + if 1 != len(numentries): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_GENERIC, f'more than one entry found') + return + + subprocess.run (['efibootmgr', '-a', '-b', numentries[0]], capture_output=True, text=True) #/** # ogNvramAddEntry @@ -33,6 +66,43 @@ import InventoryLib #@exception OG_ERR_NOTUEFI UEFI no activa. #@exception OG_ERR_NOTFOUND fichero o dispositivo no encontrado. #*/ ## +#ogNvramAddEntry ('1', '2', True) +#ogNvramAddEntry ('grub', '/EFI/grub/grubx64.efi', True) +#ogNvramAddEntry ('Windows', '/EFI/Microsoft/Boot/bootmgfw.efi') +def ogNvramAddEntry (bootlbl, bootldr, nvram_set=False): + if not InventoryLib.ogIsEfiActive(): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTUEFI, '') + return + + esp = DiskLib.ogGetEsp() + if not esp: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, 'ESP') + return + efidisk, efipar = esp.split() + + try: + foo = int(bootlbl) + int(bootldr) ## raises ValueError if bootlbl/bootldr don't look like numbers + bootlabel = f'Part-{int(bootlbl):02d}-{int(bootldr):02d}' + bootloader = f'/EFI/{bootlabel}/Boot/ogloader.efi' + except ValueError: + bootlabel = bootlbl + bootloader = bootldr + + ogNvramDeleteEntry (bootlabel) + + dev = DiskLib.ogDiskToDev (efidisk) + subprocess.run (['efibootmgr', '-C', '-d', dev, '-p', efipar, '-L', bootlabel, '-l', bootloader]) + + if nvram_set: + efibootmgr_out = subprocess.run (['efibootmgr'], capture_output=True, text=True).stdout + for l in efibootmgr_out.splitlines(): + words = l.split (maxsplit=1) + if len(words) < 2: continue + if words[1] == bootlabel: + numentry = words[0][4:8] + order = ogNvramGetOrder() + ogNvramSetOrder (order + [numentry]) + #/** @@ -56,6 +126,40 @@ import InventoryLib #@exception OG_ERR_NOTUEFI UEFI no activa. #@exception OG_ERR_NOTFOUND fichero o dispositivo no encontrado (entrada en NVRAM). #*/ ## +#ogNvramDeleteEntry ('2') +#ogNvramDeleteEntry ('Windows Boot Manager') +def ogNvramDeleteEntry (entry): + if not InventoryLib.ogIsEfiActive(): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTUEFI, '') + return + + numentries = [] + efibootmgr_out = subprocess.run (['efibootmgr'], capture_output=True, text=True).stdout + try: + foo = int (entry, 16) ## raises ValueError if entry doesn't look like hexadecimal + num = f'{foo:04x}'.upper() + for l in efibootmgr_out.splitlines(): + words = l.split() + if len(words) < 2: continue + if num in words[0]: + numentries.append (words[0][4:8]) + except ValueError: + for l in efibootmgr_out.splitlines(): + words = l.split (maxsplit=1) + if len(words) < 2: continue + if words[1] == entry: + numentries.append (words[0][4:8]) + + if not numentries: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'NVRAM entry "{entry}"') + return + + if 1 != len(numentries): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_GENERIC, f'more than one entry found') + return + + subprocess.run (['efibootmgr', '-B', '-b', numentries[0]], capture_output=True, text=True) + #/** @@ -64,6 +168,24 @@ import InventoryLib #@return Entrada con la que se ha iniciado el equipo #@exception OG_ERR_NOTUEFI UEFI no activa. #*/ ## +def ogNvramGetCurrent(): + if not InventoryLib.ogIsEfiActive(): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTUEFI, '') + return + + bootentry = '9999' + ret = None + efibootmgr_out = subprocess.run (['efibootmgr'], capture_output=True, text=True).stdout + for l in efibootmgr_out.splitlines(): + words = l.split (maxsplit=1) + if len(words) < 2: continue + if 'BootCurrent' in words[0]: + bootentry = words[1] + continue + if bootentry in words[0]: + num = words[0][4:8].strip ('0') or '0' + ret = f'{num} {words[1]}' + return ret # ogNvramGetNext @@ -71,6 +193,19 @@ import InventoryLib #@return Entrada que se utilizará en el próximo arranque #@exception OG_ERR_NOTUEFI UEFI no activa. #*/ ## +def ogNvramGetNext(): + if not InventoryLib.ogIsEfiActive(): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTUEFI, '') + return + + ret = None + efibootmgr_out = subprocess.run (['efibootmgr'], capture_output=True, text=True).stdout + for l in efibootmgr_out.splitlines(): + words = l.split (maxsplit=1) + if len(words) < 2: continue + if 'BootNext' in words[0]: + ret = words[1] + return ret # ogNvramGetOrder @@ -78,6 +213,19 @@ import InventoryLib #@return Orden de las entradas #@exception OG_ERR_NOTUEFI UEFI no activa. #*/ ## +def ogNvramGetOrder(): + if not InventoryLib.ogIsEfiActive(): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTUEFI, '') + return + + ret = [] + efibootmgr_out = subprocess.run (['efibootmgr'], capture_output=True, text=True).stdout + for l in efibootmgr_out.splitlines(): + words = l.split() + if len(words) < 2: continue + if 'BootOrder:' == words[0]: + ret = words[1].split (',') + return ret #/** @@ -86,6 +234,19 @@ import InventoryLib #@return Timeout de la NVRAM #@exception OG_ERR_NOTUEFI UEFI no activa. #*/ ## +def ogNvramGetTimeout(): + if not InventoryLib.ogIsEfiActive(): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTUEFI, '') + return + + ret = None + efibootmgr_out = subprocess.run (['efibootmgr'], capture_output=True, text=True).stdout + for l in efibootmgr_out.splitlines(): + words = l.split (maxsplit=1) + if len(words) < 2: continue + if 'Timeout:' == words[0]: + ret = words[1] + return ret #/** @@ -110,6 +271,39 @@ import InventoryLib #@exception OG_ERR_NOTFOUND fichero o dispositivo no encontrado. #@exception OG_ERR_NOTUEFI UEFI no activa. #*/ ## +#ogNvramInactiveEntry ('2') +#ogNvramInactiveEntry ('Windows Boot Manager') +def ogNvramInactiveEntry (entry): + if not InventoryLib.ogIsEfiActive(): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTUEFI, '') + return + + numentries = [] + efibootmgr_out = subprocess.run (['efibootmgr'], capture_output=True, text=True).stdout + try: + foo = int (entry, 16) ## raises ValueError if entry doesn't look like hexadecimal + num = f'{foo:04x}'.upper() + for l in efibootmgr_out.splitlines(): + words = l.split() + if len(words) < 2: continue + if num in words[0]: + numentries.append (words[0][4:8]) + except ValueError: + for l in efibootmgr_out.splitlines(): + words = l.split (maxsplit=1) + if len(words) < 2: continue + if words[1] == entry: + numentries.append (words[0][4:8]) + + if not numentries: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'NVRAM entry "{entry}"') + return + + if 1 != len(numentries): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_GENERIC, f'more than one entry found') + return + + subprocess.run (['efibootmgr', '-A', '-b', numentries[0]], capture_output=True, text=True) #/** @@ -118,6 +312,21 @@ import InventoryLib #@return Entradas de la NVRAM con el formato: orden etiqueta [* (si está activa) ] #@exception OG_ERR_NOTUEFI UEFI no activa. #*/ ## +def ogNvramList (): + if not InventoryLib.ogIsEfiActive(): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTUEFI, '') + return + + ret = '' + efibootmgr_out = subprocess.run (['efibootmgr'], capture_output=True, text=True).stdout + for l in efibootmgr_out.splitlines(): + words = l.split (maxsplit=1) + if len(words) < 2: continue + if re.search ('Boot[0-9]', words[0]): + active = '*' if '*' in words[0] else '' + num = words[0][4:8].strip ('0') or '0' + ret += '{:>4s} {} {}'.format (num, words[1], active) + return ret #/** @@ -126,6 +335,32 @@ import InventoryLib #@return (nada) #@exception OG_ERR_NOTUEFI UEFI no activa. #*/ ## +def ogNvramPxeFirstEntry(): + if not InventoryLib.ogIsEfiActive(): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTUEFI, '') + return + + num = '' + efibootmgr_out = subprocess.run (['efibootmgr'], capture_output=True, text=True).stdout + for l in efibootmgr_out.splitlines(): + if re.search ('IP[vV]{0,1}4', l): + num = l[4:8].strip ('0') or '0' + numentry = f'{int(num):04x}'.upper() + + o = ogNvramGetOrder() + if not o: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_GENERIC, f'ogNvramGetOrder returned an empty list') + return + + # Si la entrada es la primera nos salimos. + if numentry == o[0]: + return True + + # Si la entrada ya existe la borramos. + order = [numentry] + list (filter (lambda x: x if x!=numentry else [], order)) + ogNvramSetOrder (order) + + return True #/** @@ -198,6 +433,39 @@ def ogRestoreEfiBootLoader (disk, par): #@exception OG_ERR_NOTUEFI UEFI no activa. #@exception OG_ERR_NOTFOUND fichero o dispositivo no encontrado. #*/ ## +#ogNvramSetNext ('2') +#ogNvramSetNext ('Windows Boot Manager') +def ogNvramSetNext (entry): + if not InventoryLib.ogIsEfiActive(): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTUEFI, '') + return + + numentries = [] + efibootmgr_out = subprocess.run (['efibootmgr'], capture_output=True, text=True).stdout + try: + foo = int (entry, 16) ## raises ValueError if entry doesn't look like hexadecimal + num = f'{foo:04x}'.upper() + for l in efibootmgr_out.splitlines(): + words = l.split() + if len(words) < 2: continue + if num in words[0]: + numentries.append (words[0][4:8]) + except ValueError: + for l in efibootmgr_out.splitlines(): + words = l.split (maxsplit=1) + if len(words) < 2: continue + if words[1] == entry: + numentries.append (words[0][4:8]) + + if not numentries: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'NVRAM entry "{entry}"') + return + + if 1 != len(numentries): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_GENERIC, f'more than one entry found') + return + + subprocess.run (['efibootmgr', '-n', numentries[0]], capture_output=True, text=True) #/** # ogNvramSetOrder @@ -208,6 +476,38 @@ def ogRestoreEfiBootLoader (disk, par): #@exception OG_ERR_NOTUEFI UEFI no activa. #@exception OG_ERR_NOTFOUND fichero o dispositivo no encontrado (entrada NVRAM). #*/ ## +#ogNvramSetOrder (['1', '3']) +def ogNvramSetOrder (order): + mntdir = FileSystemLib.ogMount (disk, par) + if not mntdir: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, f'{disk} {par}') + return + + try: + for i in order: + foo = int (i, 16) + except ValueError: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, 'ogNvramSetOrder ([array or hex values])') + return + + # Entradas de la NVRAM actuales + numentries = [] + efibootmgr_out = subprocess.run (['efibootmgr'], capture_output=True, text=True).stdout + for l in efibootmgr_out.splitlines(): + words = l.split() + if len(words) < 2: continue + if re.search ('Boot[0-9a-fA-F]{4}', words[0]): + numentries.append ('0' + words[0][4:8]) + + new_order = [] + for o in order: + h = f'{int(o):04x}'.upper() + if h not in numentries: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'NVRAM entry order "{h}"') + return + new_order.append (h) + + subprocess.run (['efibootmgr', '-o', ','.join (new_order)]) #/** @@ -219,6 +519,19 @@ def ogRestoreEfiBootLoader (disk, par): #@exception OG_ERR_FORMAT formato incorrecto. #@exception OG_ERR_NOTFOUND fichero o dispositivo no encontrado. #*/ ## +#ogNvramSetTimeout ('2') +def ogNvramSetTimeout (t) { + if not InventoryLib.ogIsEfiActive(): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTUEFI, '') + return + + try: + num = int (t) ## raises ValueError if t doesn't look like a number + except ValueError: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, 'ogNvramSetTimeout (timeout)' + return + + subprocess.run (['efibootmgr', '-t', t]) #/**