From b00e622946cb37fb20e00f27d43f9fef37ec260e Mon Sep 17 00:00:00 2001 From: Irina Gómez Date: Mon, 15 Apr 2019 10:47:20 +0200 Subject: #802 #888 Functions for the NVRAM management. Functions in UEFI.lib ordered in alphabetical order. --- client/engine/System.lib | 1 + client/engine/UEFI.lib | 400 ++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 342 insertions(+), 59 deletions(-) (limited to 'client/engine') diff --git a/client/engine/System.lib b/client/engine/System.lib index d016be13..77f77b48 100755 --- a/client/engine/System.lib +++ b/client/engine/System.lib @@ -243,6 +243,7 @@ case "$CODE" in $OG_ERR_DONTSYNC_IMAGE) MSG="$MSG_ERR_DONTSYNC_IMAGE \"$2\"" ;; $OG_ERR_NOTDIFFERENT) MSG="$MSG_ERR_NOTDIFFERENT \"$2\"" ;; $OG_ERR_SYNCHRONIZING) MSG="$MSG_ERR_SYNCHRONIZING \"$2\"" ;; + $OG_ERR_NOTUEFI) MSG="$MSG_ERR_NOTUEFI \"$2\"" ;; *) MSG="$MSG_ERR_GENERIC"; CODE=$OG_ERR_GENERIC ;; esac diff --git a/client/engine/UEFI.lib b/client/engine/UEFI.lib index fea81135..4c1345a6 100644 --- a/client/engine/UEFI.lib +++ b/client/engine/UEFI.lib @@ -2,6 +2,193 @@ # Libreria provisional para uso de UEFI # Las funciones se incluirán las librerías ya existentes +#/** +# ogActiveNvramEntry +#@brief Borra entrada de la NVRAM identificada por la etiqueta o el orden +#@param Num_order_entry | Label_entry Número de orden o la etiqueta de la entrada a borrar. +#@return (nada) +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTUEFI UEFI no activa. +#@exception OG_ERR_NOTFOUND fichero o dispositivo no encontrado. +#*/ ## +function ogActiveNvramEntry () { +local NUMENTRY + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME [ Num_order_entry | Label_entry ] " \ + "$FUNCNAME 2" \ + "$FUNCNAME \"Windows Boot Manager\"" + return +fi + +# Error si no se recibe 1 parámetro. +[ $# -eq 1 ] || ogRaiseError $OG_ERR_FORMAT "$FUNCNAME [ Num_order_entry | Label_entry ]" || return $? + +# Si no es equipo UEFI salir con error +ogIsEfiActive || ogRaiseError $OG_ERR_NOTUEFI || return $? + +# Distingo si es número de orden o etiqueta +if [[ $1 =~ ^([0-9a-FA-F]+)*$ ]]; then + NUMENTRY=$( efibootmgr |awk -v NUM="$(printf %04x 0x$1|tr '[:lower:]' '[:upper:]')" '{ if($1~NUM) print substr($1,5,4)}') +else + NUMENTRY=$(efibootmgr |awk -v LABEL="$1" '{ if(substr($0, index($0,$2))==LABEL) print substr($1,5,4)}') +fi + +[ "$NUMENTRY" == "" ] && return $(ogRaiseError $OG_ERR_NOTFOUND "NVRAM entry '$1'") + +efibootmgr -a -b $NUMENTRY &>/dev/null +} + + +#/** +# ogCopyEfiBootLoader int_ndisk str_repo path_image +#@brief Copia el cargador de arranque desde la partición EFI a la de sistema. +#@param int_ndisk nº de orden del disco +#@param int_part nº de partición +#@return (nada, por determinar) +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND fichero o dispositivo no encontrado. +#@note Si existe el cargador en la partición de sistema no es válido +#*/ ## +function ogCopyEfiBootLoader () { +# Variables locales +local MNTDIR EFIDIR BOOTLABEL OSVERSION LOADER f + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_part" \ + "$FUNCNAME 1 2" + return +fi + +# Error si no se reciben 2 arámetros. +[ $# == 2 ] || ogRaiseError $OG_ERR_FORMAT "$FUNCNAME int_ndisk int_part" || return $? + +# Comprobamos que exista partición de sistema y la ESP +MNTDIR=$(ogMount $1 $2) || ogRaiseError $OG_ERR_PARTITION "$DISK $PART" || return $? +EFIDIR=$(ogMount $(ogGetEsp)) || ogRaiseError $OG_ERR_PARTITION "ESP" || return $? + +# Comprobamos que exista el cargador +BOOTLABEL=$(printf "Part-%02d-%02d" $1 $2) +OSVERSION=$(ogGetOsVersion $1 $2) +case $OSVERSION in + *Windows\ 10*) + for f in $EFIDIR/EFI/{$BOOTLABEL,Microsoft}/Boot/bootmgfw.efi; do + [ -r $f ] && LOADER=$f + done + [ -n "$LOADER" ] || ogRaiseError $OG_ERR_NOTOS "$1 $2 ($OSVERSION, EFI)" || return $? + # Si existe el directorio Boot lo borramos + [ -d $MNTDIR/Boot ] && rm -rf $MNTDIR/Boot + DIRLOADER=$(realpath "${LOADER%/*}/..") + cp -r ${DIRLOADER}/Boot $MNTDIR + ;; +esac +} + + +#/** +# ogDeleteNvramEntry +#@brief Borra entrada de la NVRAM identificada por la etiqueta o el orden +#@param Num_order_entry | Label_entry Número de orden o la etiqueta de la entrada a borrar. +#@return (nada) +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTUEFI UEFI no activa. +#@exception OG_ERR_NOTFOUND fichero o dispositivo no encontrado (entrada en NVRAM). +#*/ ## +function ogDeleteNvramEntry () { +local NUMENTRY + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME [ Num_order_entry | Label_entry ] " \ + "$FUNCNAME 2" \ + "$FUNCNAME \"Windows Boot Manager\"" + return +fi + +# Error si no se recibe 1 parámetro. +[ $# -eq 1 ] || ogRaiseError $OG_ERR_FORMAT "$FUNCNAME [ Num_order_entry | Label_entry ]" || return $? + +# Si no es equipo UEFI salir con error +ogIsEfiActive || ogRaiseError $OG_ERR_NOTUEFI || return $? + +# Distingo si es número de orden o etiqueta +if [[ $1 =~ ^([0-9a-FA-F]+)*$ ]]; then + NUMENTRY=$( efibootmgr |awk -v NUM="$(printf %04x 0x$1|tr '[:lower:]' '[:upper:]')" '{ if($1~NUM) print substr($1,5,4)}') +else + NUMENTRY=$(efibootmgr |awk -v LABEL="$1" '{ if(substr($0, index($0,$2))==LABEL) print substr($1,5,4)}') +fi + +[ "$NUMENTRY" == "" ] && return $(ogRaiseError $OG_ERR_NOTFOUND "NVRAM entry '$1'") + +efibootmgr -B -b $NUMENTRY &>/dev/null +} + + +#/** +# ogGetNvramCurrentEntry +#@brief Muestra la entrada del gestor de arranque (NVRAM) que ha inciado el equipo. +#@return Orden de las entradas +#@exception OG_ERR_NOTUEFI UEFI no activa. +#*/ ## +function ogGetNvramCurrentEntry () { + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME" \ + "$FUNCNAME" + return +fi + +# Si no es equipo UEFI salir con error +ogIsEfiActive || ogRaiseError $OG_ERR_NOTUEFI || return $? + +efibootmgr| awk '{if ($1~/BootCurrent/) bootentry=$2; if ($1~bootentry) printf "%s %s %s\n", gensub(/^0{1,3}/,"",1,substr($1,5,4))," ", substr($0, index($0,$2))}' +} + + +# ogGetNvramOrder +#@brief Muestra el orden de las entradas de la NVRAM +#@return Orden de las entradas +#@exception OG_ERR_NOTUEFI UEFI no activa. +#*/ ## +function ogGetNvramOrder (){ +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME" \ + "$FUNCNAME" + return +fi + +# Si no es equipo UEFI salir con error +ogIsEfiActive || ogRaiseError $OG_ERR_NOTUEFI || return $? + +efibootmgr|awk '{ if ($1 == "BootOrder:") print $2}' +} + + +#/** +# ogGetNvramTimeout +#@brief Muestra el tiempo de espera del gestor de arranque (NVRAM) +#@return Timeout de la NVRAM +#@exception OG_ERR_NOTUEFI UEFI no activa. +#*/ ## +function ogGetNvramTimeout (){ +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME" \ + "$FUNCNAME" + return +fi + +# Si no es equipo UEFI salir con error +ogIsEfiActive || ogRaiseError $OG_ERR_NOTUEFI || return $? + +efibootmgr|awk '{ if ($1 == "Timeout:") print substr($0, index($0,$2))}' +} + + #/** # ogGrubUefiConf int_ndisk int_part str_dir_grub #@brief Genera el fichero grub.cfg de la ESP @@ -49,90 +236,68 @@ EOT #cp $EFIGRUBDIR/grub.cfg "$EFIDIR/EFI/$BOOTLABEL/grub.cfg" } + #/** -# ogUuidChange int_ndisk str_repo -#@brief Reemplaza el UUID de un sistema de ficheros. -#@param int_ndisk nº de orden del disco -#@param int_part nº de partición -#@return (nada, por determinar) +# ogInactiveNvramEntry +#@brief Inactiva entrada de la NVRAM identificada por la etiqueta o el orden +#@param Num_order_entry | Label_entry Número de orden o la etiqueta de la entrada a borrar. +#@return (nada) #@exception OG_ERR_FORMAT formato incorrecto. #@exception OG_ERR_NOTFOUND fichero o dispositivo no encontrado. +#@exception OG_ERR_NOTUEFI UEFI no activa. #*/ ## -function ogUuidChange () { -local MNTDIR DEVICE UUID NEWUUID f +function ogInactiveNvramEntry () { +local NUMENTRY # Si se solicita, mostrar ayuda. if [ "$*" == "help" ]; then - ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_part" \ - "$FUNCNAME 1 2" + ogHelp "$FUNCNAME" "$FUNCNAME [ Num_order_entry | Label_entry ] " \ + "$FUNCNAME 2" \ + "$FUNCNAME \"Windows Boot Manager\"" return fi -# Error si no se reciben al menos 2 parámetros. -[ $# -eq 2 ] || ogRaiseError $OG_ERR_FORMAT "$FUNCNAME int_ndisk int_part" || return $? +# Error si no se recibe 1 parámetro. +[ $# -eq 1 ] || ogRaiseError $OG_ERR_FORMAT "$FUNCNAME [ Num_order_entry | Label_entry ]" || return $? -# Comprobamos que exista la partición -MNTDIR=$(ogMount $1 $2) || ogRaiseError $OG_ERR_NOTFOUND "Device $1 $2" || return $? -DEVICE=$(ogDiskToDev $1 $2) -UUID=$(blkid -o value -s UUID $DEVICE) -NEWUUID=$(cat /proc/sys/kernel/random/uuid) +# Si no es equipo UEFI salir con error +ogIsEfiActive || ogRaiseError $OG_ERR_NOTUEFI || return $? -# Cambiamos UUID a la partición -ogUnmount $1 $2 -tune2fs $DEVICE -U $NEWUUID +# Distingo si es número de orden o etiqueta +if [[ $1 =~ ^([0-9a-FA-F]+)*$ ]]; then + NUMENTRY=$( efibootmgr |awk -v NUM="$(printf %04x 0x$1|tr '[:lower:]' '[:upper:]')" '{ if($1~NUM) print substr($1,5,4)}') +else + NUMENTRY=$(efibootmgr |awk -v LABEL="$1" '{ if(substr($0, index($0,$2))==LABEL) print substr($1,5,4)}') +fi -# Cambiamos UUID en la configuración (fstab y grub) -ogMount $1 $2 -for f in $MNTDIR/etc/fstab $MNTDIR/{,boot/}{{grubMBR,grubPARTITION}/boot/,}{grub{,2},{,efi/}EFI/*}/{menu.lst,grub.cfg}; do - [ -r $f ] && sed -i s/$UUID/$NEWUUID/g $f -done +[ "$NUMENTRY" == "" ] && return $(ogRaiseError $OG_ERR_NOTFOUND "NVRAM entry '$1'") + +efibootmgr -A -b $NUMENTRY &>/dev/null } + #/** -# ogCopyEfiBootLoader int_ndisk str_repo path_image -#@brief Copia el cargador de arranque desde la partición EFI a la de sistema. -#@param int_ndisk nº de orden del disco -#@param int_part nº de partición -#@return (nada, por determinar) -#@exception OG_ERR_FORMAT formato incorrecto. -#@exception OG_ERR_NOTFOUND fichero o dispositivo no encontrado. -#@note Si existe el cargador en la partición de sistema no es válido +# ogListNvramEntry +#@brief Lista las entradas de la NVRAN (sólo equipos UEFI) +#@return Entradas de la NVRAM con el formato: orden etiqueta [* (si está activa) ] +#@exception OG_ERR_NOTUEFI UEFI no activa. #*/ ## -function ogCopyEfiBootLoader () { -# Variables locales -local MNTDIR EFIDIR BOOTLABEL OSVERSION LOADER f +function ogListNvramEntry () { # Si se solicita, mostrar ayuda. if [ "$*" == "help" ]; then - ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_part" \ - "$FUNCNAME 1 2" + ogHelp "$FUNCNAME" "$FUNCNAME" \ + "$FUNCNAME" return fi -# Error si no se reciben 2 arámetros. -[ $# == 2 ] || ogRaiseError $OG_ERR_FORMAT "$FUNCNAME int_ndisk int_part" || return $? - -# Comprobamos que exista partición de sistema y la ESP -MNTDIR=$(ogMount $1 $2) || ogRaiseError $OG_ERR_PARTITION "$DISK $PART" || return $? -EFIDIR=$(ogMount $(ogGetEsp)) || ogRaiseError $OG_ERR_PARTITION "ESP" || return $? +# Si no es equipo UEFI salir con error +ogIsEfiActive || ogRaiseError $OG_ERR_NOTUEFI || return $? -# Comprobamos que exista el cargador -BOOTLABEL=$(printf "Part-%02d-%02d" $1 $2) -OSVERSION=$(ogGetOsVersion $1 $2) -case $OSVERSION in - *Windows\ 10*) - for f in $EFIDIR/EFI/{$BOOTLABEL,Microsoft}/Boot/bootmgfw.efi; do - [ -r $f ] && LOADER=$f - done - [ -n "$LOADER" ] || ogRaiseError $OG_ERR_NOTOS "$1 $2 ($OSVERSION, EFI)" || return $? - # Si existe el directorio Boot lo borramos - [ -d $MNTDIR/Boot ] && rm -rf $MNTDIR/Boot - DIRLOADER=$(realpath "${LOADER%/*}/..") - cp -r ${DIRLOADER}/Boot $MNTDIR - ;; -esac +efibootmgr |awk '{if($1~/Boot[[:digit:]]/) ; active="" ;if ($1~/*/) active="*"; if($1~/Boot[[:digit:]]/) printf "%4s %s %s %s\n", gensub(/^0{1,3}/,"",1,substr($1,5,4))," ", substr($0, index($0,$2)), active}' } + #/** # ogRestoreEfiBootLoader int_ndisk str_repo #@brief Copia el cargador de arranque de la partición de sistema a la partición EFI. @@ -183,6 +348,7 @@ esac } +#/** # ogRestoreUuidPartitions #@brief Restaura los uuid de las particiones y la tabla de particiones #@param int_ndisk nº de orden del disco @@ -191,6 +357,7 @@ esac #@param str_imgname nombre de la imagen #@exception OG_ERR_FORMAT Formato incorrecto. #@exception OG_ERR_NOTFOUND No encontrado fichero de información de la imagen (con uuid) +#*/ ## function ogRestoreUuidPartitions () { local DISK PART IMGNAME INFOFILE DEVICE DATA GUID UUID IMGGUID local EFIDEVICE EFIDATA EFIGUID EFIUUID EFIUUID IMGEFIGUID @@ -246,9 +413,10 @@ echo sgdisk -U "$IMGEFIGUID" "$EFIDEVICE" partprobe fi fi - } + +#/** # ogSaveImageInfo #@brief Crea un fichero con la información de la imagen. #@param int_ndisk nº de orden del disco @@ -257,6 +425,7 @@ fi #@param str_imgname nombre de la imagen #@exception OG_ERR_FORMAT formato incorrecto. #@exception OG_ERR_NOTFOUND fichero o dispositivo no encontrado. +#*/ ## function ogSaveImageInfo () { local DISK PART IMGDIR IMGNAME INFO INFOFILE DEVICE DATA GUID local EFIPARTDEVICE EFIDEVICE EFIDATA EFIGUID @@ -313,3 +482,116 @@ cat << EOT | jq . > $INFOFILE $INFO EOT } + + +#/** +# ogSetNvramOrder +#@brief Configura el orden de las entradas de la NVRAM +#@param Orden de las entradas separadas por espacios +#@return (nada) +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTUEFI UEFI no activa. +#@exception OG_ERR_NOTFOUND fichero o dispositivo no encontrado (entrada NVRAM). +#*/ ## +function ogSetNvramOrder (){ +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME Num_order1 [ Num_order2 ] ... " \ + "$FUNCNAME 1 3" + return +fi +# +# Error si no se recibe al menos 1 parámetro. +[ $# -ge 1 ] || ogRaiseError $OG_ERR_FORMAT "$FUNCNAME Num_order1 [ Num_order2 ] ..." || return $? + +# Si no es equipo UEFI salir con error +ogIsEfiActive || ogRaiseError $OG_ERR_NOTUEFI || return $? + +# Comprobamos que sean números +[[ "$@" =~ ^([0-9a-fA-F ]+)*$ ]] || ogRaiseError $OG_ERR_FORMAT "$FUNCNAME Num_order1 [ Num_order2 ] ..." || return $? + +# Entradas de la NVRAM actuales +NUMENTRYS=$(efibootmgr|awk '{ if ($1~/Boot[0-9a-fA-F]+/) printf "0%s ", substr($1,5,4)}') + +ORDER="" +for ARG in $@; do + # Si no existe la entrada me salgo + ARG=$(printf %04x 0x$ARG) + echo $NUMENTRYS | grep "$ARG" &>/dev/null || ogRaiseError $OG_ERR_NOTFOUND "NVRAM entry order \"$ARG\"" || return $? + ORDER=${ORDER},$ARG +done + +# Cambiamos el orden +efibootmgr -o ${ORDER#,} &>/dev/null +} + + +#/** +# ogSetNvramTimeout +#@brief Configura el tiempo de espera de la NVRAM +#@param Orden de las entradas separadas por espacios +#@return (nada) + +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND fichero o dispositivo no encontrado. +#*/ ## +function ogSetNvramTimeout (){ +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_Timeout (seg)" \ + "$FUNCNAME 2" + return +fi +# +# Si no es equipo UEFI salir con error +ogIsEfiActive || ogRaiseError $OG_ERR_NOTUEFI || return $? + +# Error si no se recibe 1 parámetro. +[ $# -eq 1 ] || ogRaiseError $OG_ERR_FORMAT "$FUNCNAME int_Timeout (seg)" || return $? + +# Comprobamos que sea un número +[[ "$1" =~ ^([0-9 ]+)*$ ]] || ogRaiseError $OG_ERR_FORMAT "$FUNCNAME int_Timeout (seg)" || return $? + +# Cambiamos el orden +efibootmgr -t $1 &>/dev/null +} + + +#/** +# ogUuidChange int_ndisk str_repo +#@brief Reemplaza el UUID de un sistema de ficheros. +#@param int_ndisk nº de orden del disco +#@param int_part nº de partición +#@return (nada, por determinar) +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND fichero o dispositivo no encontrado. +#*/ ## +function ogUuidChange () { +local MNTDIR DEVICE UUID NEWUUID f + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_part" \ + "$FUNCNAME 1 2" + return +fi + +# Error si no se reciben al menos 2 parámetros. +[ $# -eq 2 ] || ogRaiseError $OG_ERR_FORMAT "$FUNCNAME int_ndisk int_part" || return $? + +# Comprobamos que exista la partición +MNTDIR=$(ogMount $1 $2) || ogRaiseError $OG_ERR_NOTFOUND "Device $1 $2" || return $? +DEVICE=$(ogDiskToDev $1 $2) +UUID=$(blkid -o value -s UUID $DEVICE) +NEWUUID=$(cat /proc/sys/kernel/random/uuid) + +# Cambiamos UUID a la partición +ogUnmount $1 $2 +tune2fs $DEVICE -U $NEWUUID + +# Cambiamos UUID en la configuración (fstab y grub) +ogMount $1 $2 +for f in $MNTDIR/etc/fstab $MNTDIR/{,boot/}{{grubMBR,grubPARTITION}/boot/,}{grub{,2},{,efi/}EFI/*}/{menu.lst,grub.cfg}; do + [ -r $f ] && sed -i s/$UUID/$NEWUUID/g $f +done +} -- cgit v1.2.3-18-g5258