#! /bin/sh
# SPDX-License-Identifier: GPL-3.0-only
# vim: set ts=4 sw=4 sts=4 noet:
#
# Spectre & Meltdown checker
#
# Check for the latest version at:
# https://github.com/speed47/spectre-meltdown-checker
# git clone https://github.com/speed47/spectre-meltdown-checker.git
# or wget https://meltdown.ovh -O spectre-meltdown-checker.sh
# or curl -L https://meltdown.ovh -o spectre-meltdown-checker.sh
#
# Stephane Lesimple
#
VERSION='0.46+'

trap 'exit_cleanup' EXIT
trap '_warn "interrompido, limpando..."; exit_cleanup; exit 1' INT
exit_cleanup()
{
	saved_ret=$?
	# cleanup the temp decompressed config & kernel image
	[ -n "${dumped_config:-}" ] && [ -f "$dumped_config" ] && rm -f "$dumped_config"
	[ -n "${kerneltmp:-}"     ] && [ -f "$kerneltmp"     ] && rm -f "$kerneltmp"
	[ -n "${kerneltmp2:-}"    ] && [ -f "$kerneltmp2"    ] && rm -f "$kerneltmp2"
	[ -n "${mcedb_tmp:-}"     ] && [ -f "$mcedb_tmp"     ] && rm -f "$mcedb_tmp"
	[ -n "${intel_tmp:-}"     ] && [ -d "$intel_tmp"     ] && rm -rf "$intel_tmp"
	[ -n "${linuxfw_tmp:-}"   ] && [ -f "$linuxfw_tmp"   ] && rm -f "$linuxfw_tmp"
	[ "${mounted_debugfs:-}" = 1 ] && umount /sys/kernel/debug 2>/dev/null
	[ "${mounted_procfs:-}"  = 1 ] && umount "$procfs" 2>/dev/null
	[ "${insmod_cpuid:-}"    = 1 ] && rmmod cpuid 2>/dev/null
	[ "${insmod_msr:-}"      = 1 ] && rmmod msr 2>/dev/null
	[ "${kldload_cpuctl:-}"  = 1 ] && kldunload cpuctl 2>/dev/null
	[ "${kldload_vmm:-}"     = 1 ] && kldunload vmm    2>/dev/null
	exit $saved_ret
}

# if we were git clone'd, adjust VERSION
if [ -d "$(dirname "$0")/.git" ] && command -v git >/dev/null 2>&1; then
	describe=$(git -C "$(dirname "$0")" describe --tags --dirty 2>/dev/null)
	[ -n "$describe" ] && VERSION=$(echo "$describe" | sed -e s/^v//)
fi

show_usage()
{
	# shellcheck disable=SC2086
	cat <<EOF
	Uso:
		Modo ao vivo (automático):   $(basename $0) [options]
		Modo ao vivo (manual): $(basename $0) [options] <[--kernel <kimage>] [--config <kconfig>] [--map <mapfile>]> --live
		Modo offline:       $(basename $0) [options] <[--kernel <kimage>] [--config <kconfig>] [--map <mapfile>]>

	Modos:
		Dois modos estão disponíveis.

		O primeiro modo é o modo "ao vivo" (padrão); ele faz o possível para encontrar informações sobre o kernel atualmente em execução.
		Para executar neste modo, basta iniciar o script sem nenhuma opção (você também pode usar --live explicitamente)

		O segundo modo é o modo "offline", onde você pode inspecionar um kernel não executando.
		Este modo é ativado automaticamente quando você especifica o local dos arquivos kernel, config e System.map:

		--kernel kernel_file	especifique um arquivo de kernel Linux ou BSD (possivelmente compactado)
		--config kernel_config	especifique um arquivo de configuração do kernel (somente Linux)
		--map kernel_map_file	especifique um arquivo System.map do kernel (somente Linux)

		Se você quiser usar o modo ao vivo enquanto especifica o local do kernel, configuração ou arquivo de mapeamento,
		você pode adicionar --live às opções acima, para dizer ao script para executar no modo ao vivo, em vez do modo offline,
		que é ativado por padrão quando pelo menos um arquivo é especificado na linha de comando.

	Opções:
		--no-color		não use códigos de cores
		--verbose, -v		aumentar o nível de verbosidade, possivelmente várias vezes
		--explain		produzir uma explicação legível adicional de ações a serem tomadas para mitigar a vulnerabilidade
		--paranoid		exigir que o IBPB considere a variante 2 como atenuada
					também exigem SMT desativado  liberação L1D incondicional para considerar o Foreshadow-NG VMM como atenuado
					também exigem que o SMT desativado considere vulnerabilidades do MDS atenuadas

		--no-sysfs		não use a interface /sys mesmo se presente [Linux]
		--sysfs-only		use apenas a interface /sys, não execute nossas próprias verificações [Linux]
		--coreos		modo especial para CoreOS (use uma caixa de ferramentas efêmera para inspecionar o kernel) [Linux]

		--arch-prefix PREFIX	especifique um prefixo para a inspeção cruzada de um kernel de um arco diferente, por exemplo "aarch64-linux-gnu-",
					para que ferramentas invocadas sejam prefixadas com este (i.e. aarch64-linux-gnu-objdump)
		--batch text		produzir saída legível por máquina, esse é o padrão se --batch for especificado sozinho
		--batch short		produzir apenas uma linha com as vulnerabilidades separadas por espaços
		--batch json		produzir saída JSON formatada para Puppet, Ansible, Chef...
		--batch nrpe		produzir saída legível por máquina formatada para NRPE
		--batch prometheus		produzir saída para consumo por prometheus-node-exporter

		--variant VARIANT	especifique qual variante você gostaria de verificar, por padrão, todas as variantes são verificadas.
					pode ser usado várias vezes (por exemplo, --variant 3a --variant l1tf)
					para obter uma lista de parâmetros VARIANT suportados, use --variant help
		--cve CVE		especifique qual CVE você gostaria de verificar, por padrão, todos os CVEs suportados são verificados
					pode ser usado várias vezes (por exemplo, --cve CVE-2017-5753 --cve CVE-2020-0543)
		--hw-only		verifique apenas as informações da CPU, não verifique nenhuma variante
		--no-hw			pule as informações e verificações da CPU, se você estiver inspecionando um kernel para não ser executado neste host
		--vmm [auto,yes,no]	substituir a detecção da presença de um hypervisor, padrão: auto
		--no-intel-db		não use o banco de dados Intel integrado dos processadores afetados
		--allow-msr-write	permitir a sondagem de MSRs somente gravação, isso pode produzir logs do kernel ou ser bloqueado pelo seu sistema
		--cpu [#,all]		interagir com CPUID e MSR do número do núcleo da CPU #, ou todos (padrão: núcleo da CPU 0)
		--update-fwdb		atualize nossa cópia local do banco de dados de versões de microcódigos da CPU (usando o incrível
					Projeto MCExtractor e o repositório GitHub dos firmwares Intel)
		--update-builtin-fwdb	o mesmo que --update-fwdb, mas atualize o banco de dados interno dentro do próprio script
		--dump-mock-data	usado para imitar uma CPU em outro sistema, usado principalmente para ajudar na depuração desse script

	Códigos de retorno:
		0 (não vulnerável), 2 (vulnerável), 3 (desconhecido), 255 (erro)

	IMPORTANTE:
	Uma falsa sensação de segurança é pior do que nenhuma segurança.
	Por favor, use a opção --disclaimer para entender exatamente o que esse script faz.

EOF
}

show_disclaimer()
{
	cat <<EOF
Isenção de responsabilidade:

Esta ferramenta faz o possível para determinar se o seu sistema é imune (ou se possui mitigações adequadas) para o
vulnerabilidades coletivamente chamadas de "execução transitória" (também conhecidas como "execução especulativa") que começaram a aparecer
desde o início de 2018 com o famigerado Specter & Meltdown.

Esta ferramenta NÃO tenta executar qualquer tipo de exploração e não pode garantir 100% que seu sistema seja seguro,
mas ajuda a verificar se o seu sistema possui as mitigações corretas conhecidas.
No entanto, algumas mitigações também podem existir em seu kernel que este script não sabe (ainda) como detectar, ou pode
detecta falsamente mitigações que, no final, não funcionam como esperado (por exemplo, em kernels modificados ou com backport).

A afetabilidade do sistema a uma determinada vulnerabilidade depende do modelo da CPU e da versão do microcódigo da CPU, enquanto o
mitigações em vigor dependem de sua CPU (modelo e microcódigo), sua versão do kernel e a configuração de tempo de execução
de sua CPU (através de bits definidos pelos MSRs) e seu kernel. O script tenta explicar tudo para cada
vulnerabilidade, para que você saiba onde está o seu sistema. Para uma determinada vulnerabilidade, informações detalhadas às vezes são
disponível usando a opção \`--explain\`.

Observe também que, para as vulnerabilidades do tipo Spectre, todos os softwares podem ser explorados, caso em que
esta ferramenta apenas verifica se o kernel (que é o núcleo do sistema) que você está usando possui as proteções adequadas
no lugar. A verificação de todos os outros softwares está fora do escopo desta ferramenta, pois não pode ser feita de maneira simples.
Como medida geral, certifique-se de ter sempre as versões estáveis mais atualizadas de todos os softwares que você usa,
especialmente para aqueles que estão expostos ao mundo, como daemons de rede e navegadores.

Para obter mais informações e respostas a perguntas relacionadas, consulte o arquivo FAQ.md.

Esta ferramenta foi lançada na esperança de que seja útil, mas não a use para tirar conclusões precipitadas sobre sua segurança.

EOF
}

os=$(uname -s)

# parse options
opt_kernel=''
opt_config=''
opt_map=''
opt_live=-1
opt_no_color=0
opt_batch=0
opt_batch_format='text'
opt_verbose=1
opt_cve_list=''
opt_cve_all=1
opt_no_sysfs=0
opt_sysfs_only=0
opt_coreos=0
opt_arch_prefix=''
opt_hw_only=0
opt_no_hw=0
opt_vmm=-1
opt_allow_msr_write=0
opt_cpu=0
opt_explain=0
opt_paranoid=0
opt_mock=0
opt_intel_db=1

global_critical=0
global_unknown=0
nrpe_vuln=''

supported_cve_list='
CVE-2017-5753
CVE-2017-5715
CVE-2017-5754
CVE-2018-3640
CVE-2018-3639
CVE-2018-3615
CVE-2018-3620
CVE-2018-3646
CVE-2018-12126
CVE-2018-12130
CVE-2018-12127
CVE-2019-11091
CVE-2019-11135
CVE-2018-12207
CVE-2020-0543
CVE-2023-20593
CVE-2022-40982
CVE-2023-20569
CVE-2023-23583'

# find a sane command to print colored messages, we prefer `printf` over `echo`
# because `printf` behavior is more standard across Linux/BSD
# we'll try to avoid using shell builtins that might not take options
echo_cmd_type='echo'
# ignore SC2230 here because `which` ignores builtins while `command -v` doesn't, and
# we don't want builtins here. Even if `which` is not installed, we'll fallback to the
# `echo` builtin anyway, so this is safe.
# shellcheck disable=SC2230
if command -v printf >/dev/null 2>&1; then
	echo_cmd=$(command -v printf)
	echo_cmd_type='printf'
elif which echo >/dev/null 2>&1; then
	echo_cmd=$(which echo)
else
	# maybe the `which` command is broken?
	[ -x /bin/echo        ] && echo_cmd=/bin/echo
	# for Android
	[ -x /system/bin/echo ] && echo_cmd=/system/bin/echo
fi
# still empty? fallback to builtin
[ -z "$echo_cmd" ] && echo_cmd='echo'
__echo()
{
	opt="$1"
	shift
	_msg="$*"

	if [ "$opt_no_color" = 1 ] ; then
		# strip ANSI color codes
		# some sed versions (i.e. toybox) can't seem to handle
		# \033 aka \x1B correctly, so do it for them.
		if [ "$echo_cmd_type" = printf ]; then
			_interpret_chars=''
		else
			_interpret_chars='-e'
		fi
		_ctrlchar=$($echo_cmd $_interpret_chars "\033")
		_msg=$($echo_cmd $_interpret_chars "$_msg" | sed -r "s/$_ctrlchar\[([0-9][0-9]?(;[0-9][0-9]?)?)?m//g")
	fi
	if [ "$echo_cmd_type" = printf ]; then
		if [ "$opt" = "-n" ]; then
			$echo_cmd "$_msg"
		else
			$echo_cmd "$_msg\n"
		fi
	else
		# shellcheck disable=SC2086
		$echo_cmd $opt -e "$_msg"
	fi
}

_echo()
{
	if [ "$opt_verbose" -ge "$1" ]; then
		shift
		__echo '' "$*"
	fi
}

_echo_nol()
{
	if [ "$opt_verbose" -ge "$1" ]; then
		shift
		__echo -n "$*"
	fi
}

_warn()
{
	_echo 0 "\033[31m$*\033[0m" >&2
}

_info()
{
	_echo 1 "$*"
}

_info_nol()
{
	_echo_nol 1 "$*"
}

_verbose()
{
	_echo 2 "$*"
}

_verbose_nol()
{
	_echo_nol 2 "$*"
}

_debug()
{
	_echo 3 "\033[34m(debug) $*\033[0m"
}

explain()
{
	if [ "$opt_explain" = 1 ] ; then
		_info ''
		_info "> \033[41m\033[30mComo corrigir:\033[0m $*"
	fi
}

cve2name()
{
	case "$1" in
		CVE-2017-5753)	echo "Spectre Variante 1, desvio de verificação de limites";;
		CVE-2017-5715)	echo "Spectre Variante 2, injeção no alvo do ramo";;
		CVE-2017-5754)	echo "Variante 3, Meltdown, carregamento de cache de dados não autorizado";;
		CVE-2018-3640)	echo "Variante 3a, leitura de registro de sistema não autorizado";;
		CVE-2018-3639)	echo "Variante 4, derivação especulativa de armazenamento";;
		CVE-2018-3615)	echo "Foreshadow (SGX), falha no terminal L1";;
		CVE-2018-3620)	echo "Foreshadow-NG (OS), falha do terminal L1";;
		CVE-2018-3646)	echo "Foreshadow-NG (VMM), falha do terminal L1";;
		CVE-2018-12126) echo "Fallout, amostragem de dados de buffer de microarquitetura arquitetônica (MSBDS)";;
		CVE-2018-12130) echo "ZombieLoad, amostragem de dados de buffer de microarquitetura arquitetônica (MFBDS)";;
		CVE-2018-12127) echo "RIDL, amostragem de dados de portas de carga microarquiteturais (MLPDS)";;
		CVE-2019-11091) echo "RIDL, memória incachável de amostragem de dados da microarquitetura (MDSUM)";;
		CVE-2019-11135) echo "ZombieLoad V2, TSX Abortamento assíncrono (TAA)";;
		CVE-2018-12207) echo "Sem exceções de eXcuses, iTLB Multihit, verificação de máquina nas alterações de tamanho de página (MCEPSC)";;
		CVE-2020-0543) echo "Amostragem de dados de buffer de registro especial (SRBDS)";;
		CVE-2023-20593) echo "Zenbleed, vazamento de informações entre processos";;
		CVE-2022-40982) echo "Downfall, coleta de amostragem de dados (GDS)";;
		CVE-2023-20569) echo "Começo, segurança de endereço de retorno (RAS)";;
		CVE-2023-23583) echo "Reptar, problema de prefixo redundante";;
		*) echo "$0: erro: CVE inválido '$1' passado para cve2name()" >&2; exit 255;;
	esac
}

is_cpu_affected_cached=0
_is_cpu_affected_cached()
{
	# shellcheck disable=SC2086
	case "$1" in
		CVE-2017-5753) return $variant1;;
		CVE-2017-5715) return $variant2;;
		CVE-2017-5754) return $variant3;;
		CVE-2018-3640) return $variant3a;;
		CVE-2018-3639) return $variant4;;
		CVE-2018-3615) return $variantl1tf_sgx;;
		CVE-2018-3620) return $variantl1tf;;
		CVE-2018-3646) return $variantl1tf;;
		CVE-2018-12126) return $variant_msbds;;
		CVE-2018-12130) return $variant_mfbds;;
		CVE-2018-12127) return $variant_mlpds;;
		CVE-2019-11091) return $variant_mdsum;;
		CVE-2019-11135) return $variant_taa;;
		CVE-2018-12207) return $variant_itlbmh;;
		CVE-2020-0543) return $variant_srbds;;
		CVE-2023-20593) return $variant_zenbleed;;
		CVE-2022-40982) return $variant_downfall;;
		CVE-2023-20569) return $variant_inception;;
		CVE-2023-23583) return $variant_reptar;;
		*) echo "$0: erro: variante inválida '$1' passada para is_cpu_affected()" >&2; exit 255;;
	esac
}

is_cpu_affected()
{
	# param: one of the $supported_cve_list items
	# returns 0 if affected, 1 if not affected
	# (note that in shell, a return of 0 is success)
	# by default, everything is affected, we work in a "whitelist" logic here.
	# usage: is_cpu_affected CVE-xxxx-yyyy && do something if affected

	# if CPU is Intel and is in our dump of the Intel official affected CPUs page, use it:
	if is_intel; then
		cpuid_hex=$(printf "0x%08X" $(( cpu_cpuid )) )
		if [ "${intel_line:-}" = "no" ]; then
			_debug "is_cpu_affected:$cpuid_hex não está no banco de dados Intel (em cache)"
		elif [ -z "$intel_line" ]; then
			intel_line=$(read_inteldb | grep -F "$cpuid_hex," | head -n1)
			if [ -z "$intel_line" ]; then
				intel_line=no
				_debug "is_cpu_affected: $cpuid_hex não está no banco de dados Intel"
			fi
		fi
		if [ "$intel_line" != "no" ]; then
			_result=$(echo "$intel_line" | grep -Eo ,"$(echo "$1" | cut -c5-)"'=[^,]+' | cut -d= -f2)
			_debug "is_cpu_affected: inteldb para $1 diz '$_result'"

			# handle special case for Foreshadow SGX (CVE-2018-3615):
			# even if we are affected to L1TF (CVE-2018-3620/CVE-2018-3646), if there's no SGX on our CPU,
			# then we're not affected to the original Foreshadow.
			if [ "$1" = "CVE-2018-3615" ] && [ "$cpuid_sgx" = 0 ]; then
				# not affected
				return 1
			fi
			# /special case

			if [ "$_result" = "N" ]; then
				# not affected
				return 1
			elif [ -n "$_result" ]; then
				# non-empty string != N means affected
				return 0
			fi
		fi
	fi

	# Otherwise, do it ourselves

	if [ "$is_cpu_affected_cached" = 1 ]; then
		_is_cpu_affected_cached "$1"
		return $?
	fi

	variant1=''
	variant2=''
	variant3=''
	variant3a=''
	variant4=''
	variantl1tf=''
	variant_msbds=''
	variant_mfbds=''
	variant_mlpds=''
	variant_mdsum=''
	variant_taa=''
	variant_itlbmh=''
	variant_srbds=''
	# Zenbleed and Inception are both AMD specific, look for "is_amd" below:
	variant_zenbleed=immune
	variant_inception=immune
	# Downfall & Reptar are Intel specific, look for "is_intel" below:
	variant_downfall=immune
	variant_reptar=immune

	if is_cpu_mds_free; then
		[ -z "$variant_msbds" ] && variant_msbds=immune
		[ -z "$variant_mfbds" ] && variant_mfbds=immune
		[ -z "$variant_mlpds" ] && variant_mlpds=immune
		[ -z "$variant_mdsum" ] && variant_mdsum=immune
		_debug "is_cpu_affected: CPU não afetada pela Amostragem de Dados Microarquiteturais"
	fi

	if is_cpu_taa_free; then
		[ -z "$variant_taa" ] && variant_taa=immune
		_debug "is_cpu_affected: CPU não afetada pelo TSX Asynhronous Abort"
	fi

	if is_cpu_srbds_free; then
		[ -z "$variant_srbds" ] && variant_srbds=immune
		_debug "is_cpu_affected: cpu não afetado pela Amostragem de dados de buffer de registro especial"
	fi

	if is_cpu_specex_free; then
		variant1=immune
		variant2=immune
		variant3=immune
		variant3a=immune
		variant4=immune
		variantl1tf=immune
		variant_msbds=immune
		variant_mfbds=immune
		variant_mlpds=immune
		variant_mdsum=immune
		variant_taa=immune
		variant_srbds=immune
	elif is_intel; then
		# Intel
		# https://github.com/crozone/SpectrePoC/issues/1 ^F E5200 => spectre 2 not affected
		# https://github.com/paboldin/meltdown-exploit/issues/19 ^F E5200 => meltdown affected
		# model name : Pentium(R) Dual-Core  CPU      E5200  @ 2.50GHz
		if echo "$cpu_friendly_name" | grep -qE 'Pentium\(R\) Dual-Core[[:space:]]+CPU[[:space:]]+E[0-9]{4}K?'; then
			variant1=vuln
			[ -z "$variant2" ] && variant2=immune
			variant3=vuln
		fi
		if [ "$capabilities_rdcl_no" = 1 ]; then
			# capability bit for future Intel processor that will explicitly state
			# that they're not affected to Meltdown
			# this var is set in check_cpu()
			[ -z "$variant3" ]    && variant3=immune
			[ -z "$variantl1tf" ] && variantl1tf=immune
			_debug "is_cpu_affected: RDCL_NO está definido para que não seja vuln para meltdown nem l1tf"
		fi
		if [ "$capabilities_ssb_no" = 1 ]; then
			# capability bit for future Intel processor that will explicitly state
			# that they're not affected to Variant 4
			# this var is set in check_cpu()
			[ -z "$variant4" ] && variant4=immune
			_debug "is_cpu_affected: SSB_NO está definido para não ser vuln para variant4"
		fi
		if is_cpu_ssb_free; then
			[ -z "$variant4" ] && variant4=immune
			_debug "is_cpu_affected: CPU não afetada pelo desvio de armazenamento especulativo, portanto, não está relacionada à variante4"
		fi
		# variant 3a
		if [ "$cpu_family" = 6 ]; then
			if [ "$cpu_model" = "$INTEL_FAM6_XEON_PHI_KNL" ] || [ "$cpu_model" = "$INTEL_FAM6_XEON_PHI_KNM" ]; then
				_debug "is_cpu_affected: xeon phi imune à variante 3a"
				[ -z "$variant3a" ] && variant3a=immune
			elif [ "$cpu_model" = "$INTEL_FAM6_ATOM_SILVERMONT" ] || \
				[ "$cpu_model" = "$INTEL_FAM6_ATOM_SILVERMONT_MID" ] || \
				[ "$cpu_model" = "$INTEL_FAM6_ATOM_SILVERMONT_D" ]; then
					# https://www.intel.com/content/www/us/en/security-center/advisory/intel-sa-00115.html
					# https://github.com/speed47/spectre-meltdown-checker/issues/310
					# => silvermont CPUs (aka cherry lake for tablets and brawsell for mobile/desktop) don't seem to be affected
					# => goldmont ARE affected
					_debug "is_cpu_affected: silvermont imune à variante 3a"
					[ -z "$variant3a" ] && variant3a=immune
			fi
		fi
		# L1TF (RDCL_NO already checked above)
		if [ "$cpu_family" = 6 ]; then
			if [ "$cpu_model" = "$INTEL_FAM6_ATOM_SALTWELL"          ] || \
				[ "$cpu_model" = "$INTEL_FAM6_ATOM_SALTWELL_TABLET" ] || \
				[ "$cpu_model" = "$INTEL_FAM6_ATOM_SALTWELL_MID" ] || \
				[ "$cpu_model" = "$INTEL_FAM6_ATOM_BONNELL" ] || \
				[ "$cpu_model" = "$INTEL_FAM6_ATOM_BONNELL_MID" ] || \
				[ "$cpu_model" = "$INTEL_FAM6_ATOM_SILVERMONT" ] || \
				[ "$cpu_model" = "$INTEL_FAM6_ATOM_SILVERMONT_MID" ] || \
				[ "$cpu_model" = "$INTEL_FAM6_ATOM_SILVERMONT_D" ] || \
				[ "$cpu_model" = "$INTEL_FAM6_ATOM_AIRMONT" ] || \
				[ "$cpu_model" = "$INTEL_FAM6_ATOM_AIRMONT_MID" ] || \
				[ "$cpu_model" = "$INTEL_FAM6_ATOM_AIRMONT_NP" ] || \
				[ "$cpu_model" = "$INTEL_FAM6_ATOM_GOLDMONT" ] || \
				[ "$cpu_model" = "$INTEL_FAM6_ATOM_GOLDMONT_D" ] || \
				[ "$cpu_model" = "$INTEL_FAM6_ATOM_GOLDMONT_PLUS" ] || \
				[ "$cpu_model" = "$INTEL_FAM6_ATOM_TREMONT_D" ] || \
				[ "$cpu_model" = "$INTEL_FAM6_XEON_PHI_KNL"     ] || \
				[ "$cpu_model" = "$INTEL_FAM6_XEON_PHI_KNM" ]; then

				_debug "is_cpu_affected: família intel 6, mas modelo conhecido por ser imune a l1tf"
				[ -z "$variantl1tf" ] && variantl1tf=immune
			else
				_debug "is_cpu_affected: família intel 6 é vuln para l1tf"
				variantl1tf=vuln
			fi
		elif [ "$cpu_family" -lt 6 ]; then
			_debug "is_cpu_affected: família intel < 6 é imune a l1tf"
			[ -z "$variantl1tf" ] && variantl1tf=immune
		fi
		# Downfall
		if [ "$capabilities_gds_no" = 1 ]; then
			# capability bit for future Intel processors that will explicitly state
			# that they're unaffected by GDS. Also set by hypervisors on virtual CPUs
			# so that the guest kernel doesn't try to mitigate GDS when it's already mitigated on the host
			_debug "is_cpu_affected: downfall: não afetado (GDS_NO)"
		elif [ "$cpu_family" = 6 ]; then
			# list from https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=64094e7e3118aff4b0be8ff713c242303e139834
			set -u
			if [ "$cpu_model" = "$INTEL_FAM6_SKYLAKE_X" ] || \
				[ "$cpu_model" = "$INTEL_FAM6_KABYLAKE_L" ] || \
				[ "$cpu_model" = "$INTEL_FAM6_KABYLAKE" ] || \
				[ "$cpu_model" = "$INTEL_FAM6_ICELAKE_L" ] || \
				[ "$cpu_model" = "$INTEL_FAM6_ICELAKE_D" ] || \
				[ "$cpu_model" = "$INTEL_FAM6_ICELAKE_X" ] || \
				[ "$cpu_model" = "$INTEL_FAM6_COMETLAKE" ] || \
				[ "$cpu_model" = "$INTEL_FAM6_COMETLAKE_L" ] || \
				[ "$cpu_model" = "$INTEL_FAM6_TIGERLAKE_L" ] || \
				[ "$cpu_model" = "$INTEL_FAM6_TIGERLAKE" ] || \
				[ "$cpu_model" = "$INTEL_FAM6_ROCKETLAKE" ]; then
				_debug "is_cpu_affected: downfall: afetado"
				variant_downfall=vuln
			elif [ "$has_avx2" = 0 ] && [ "$has_avx512" = 0 ]; then
				_debug "is_cpu_affected: downfall: sem avx; imune"
			else
				# old Intel CPU (not in their DB), not listed as being affected by the Linux kernel,
				# but with AVX2 or AVX512: unclear for now
				_debug "is_cpu_affected: downfall: obscuro, padrão para não afetado por enquanto"
			fi
			set +u
		fi
		# Reptar
		# the only way to know whether a CPU is vuln, is to check whether there is a known ucode update for it,
		# as the mitigation is only ucode-based and there's no flag exposed by the kernel or by an updated ucode.
		# we have to hardcode the truthtable of affected CPUs vs updated ucodes...
		# https://www.intel.com/content/www/us/en/developer/articles/technical/software-security-guidance/advisory-guidance/redundant-prefix-issue.html
		# list taken from:
		# https://github.com/intel/Intel-Linux-Processor-Microcode-Data-Files/commit/ece0d294a29a1375397941a4e6f2f7217910bc89#diff-e6fad0f2abbac6c9603b2e8f88fe1d151a83de708aeca1c1d93d881c958ecba4R26
		# both pages have a lot of inconsistencies, I've tried to fix the errors the best I could, the logic being: if it's not in the
		# blog page, then the microcode update in the commit is not related to reptar, if microcode versions differ, then the one in github is correct,
		# if a stepping exists in the blog page but not in the commit, then the blog page is right
		reptar_ucode_list='
06-97-02/07,00000032
06-97-05/07,00000032
06-9a-03/80,00000430
06-9a-04/80,00000430
06-6c-01/10,01000268
06-6a-06/87,0d0003b9
06-7e-05/80,000000c2
06-ba-02/e0,0000411c
06-b7-01/32,0000011d
06-a7-01/02,0000005d
06-bf-05/07,00000032
06-bf-02/07,00000032
06-ba-03/e0,0000411c
06-8f-08/87,2b0004d0
06-8f-07/87,2b0004d0
06-8f-06/87,2b0004d0
06-8f-05/87,2b0004d0
06-8f-04/87,2b0004d0
06-8f-08/10,2c000290
06-8c-01/80,000000b4
06-8c-00/ff,000000b4
06-8d-01/c2,0000004e
06-8d-00/c2,0000004e
06-8c-02/c2,00000034
'
		for tuple in $reptar_ucode_list; do
			fixed_ucode_ver=$(( 0x$(echo "$tuple" | cut -d, -f2) ))
			affected_fmspi=$(echo "$tuple" | cut -d, -f1)
			affected_fms=$(echo "$affected_fmspi" | cut -d/ -f1)
			ucode_platformid_mask=0x$(echo "$affected_fmspi" | cut -d/ -f2)
			affected_cpuid=$(fms2cpuid \
				0x"$(echo "$affected_fms" | cut -d- -f1)" \
				0x"$(echo "$affected_fms" | cut -d- -f2)" \
				0x"$(echo "$affected_fms" | cut -d- -f3)" \
			)
			if [ "$cpu_cpuid" = "$affected_cpuid" ] && [ $((cpu_platformid & ucode_platformid_mask)) -gt 0 ]; then
				# this is not perfect as Intel never tells about their EOL CPUs, so more CPUs might be affected but there's no way to tell
				variant_reptar=vuln
				reptar_fixed_ucode_version=$fixed_ucode_ver
				break
			fi
		done


	elif is_amd || is_hygon; then
		# AMD revised their statement about variant2 => affected
		# https://www.amd.com/en/corporate/speculative-execution
		variant1=vuln
		variant2=vuln
		[ -z "$variant3"  ] && variant3=immune
		# https://www.amd.com/en/corporate/security-updates
		# "We have not identified any AMD x86 products susceptible to the Variant 3a vulnerability in our analysis to-date."
		[ -z "$variant3a" ] && variant3a=immune
		if is_cpu_ssb_free; then
			[ -z "$variant4" ] && variant4=immune
			_debug "is_cpu_affected: CPU não afetada pelo desvio de armazenamento especulativo, portanto, não está relacionada à variante4"
		fi
		variantl1tf=immune

		# Zenbleed
		amd_legacy_erratum "$(amd_model_range 0x17 0x30 0x0 0x4f 0xf)" && variant_zenbleed=vuln
		amd_legacy_erratum "$(amd_model_range 0x17 0x60 0x0 0x7f 0xf)" && variant_zenbleed=vuln
		amd_legacy_erratum "$(amd_model_range 0x17 0xa0 0x0 0xaf 0xf)" && variant_zenbleed=vuln

		# Inception (according to kernel, zen 1 to 4)
		if [ "$cpu_family" = $(( 0x17 )) ] || [ "$cpu_family" = $(( 0x19 )) ]; then
			variant_inception=vuln
		fi

	elif [ "$cpu_vendor" = CAVIUM ]; then
		variant3=immune
		variant3a=immune
		variantl1tf=immune
	elif [ "$cpu_vendor" = PHYTIUM ]; then
		variant3=immune
		variant3a=immune
		variantl1tf=immune
	elif [ "$cpu_vendor" = ARM ]; then
		# ARM
		# reference: https://developer.arm.com/support/security-update
		# some devices (phones or other) have several ARMs and as such different part numbers,
		# an example is "bigLITTLE". we shouldn't rely on the first CPU only, so we check the whole list
		i=0
		for cpupart in $cpu_part_list
		do
			i=$(( i + 1 ))
			# do NOT quote $cpu_arch_list below
			# shellcheck disable=SC2086
			cpuarch=$(echo $cpu_arch_list | awk '{ print $'$i' }')
			_debug "checando a cpu$i: <$cpupart> <$cpuarch>"
			# some kernels report AArch64 instead of 8
			[ "$cpuarch" = "AArch64" ] && cpuarch=8
			if [ -n "$cpupart" ] && [ -n "$cpuarch" ]; then
				# Cortex-R7 and Cortex-R8 are real-time and only used in medical devices or such
				# I can't find their CPU part number, but it's probably not that useful anyway
				# model R7 R8 A8  A9  A12 A15 A17 A57 A72 A73 A75 A76 A77 Neoverse-N1 Neoverse-V1 Neoverse-N1 Neoverse-V2 
				# part   ?  ? c08 c09 c0d c0f c0e d07 d08 d09 d0a d0b d0d d0c         d40	  d49	      d4f
				# arch  7? 7? 7   7   7   7   7   8   8   8   8   8   8   8           8		  8	      8
				#
				# Whitelist identified non-affected processors, use vulnerability information from 
				# https://developer.arm.com/support/arm-security-updates/speculative-processor-vulnerability
				# Partnumbers can be found here:
				# https://github.com/gcc-mirror/gcc/blob/master/gcc/config/arm/arm-cpus.in
				#
				# Maintain cumulative check of vulnerabilities -
				# if at least one of the cpu is affected, then the system is affected
				if [ "$cpuarch" = 7 ] && echo "$cpupart" | grep -q -w -e 0xc08 -e 0xc09 -e 0xc0d -e 0xc0e; then
					variant1=vuln
					variant2=vuln
					[ -z "$variant3" ] && variant3=immune
					[ -z "$variant3a" ] && variant3a=immune
					[ -z "$variant4" ] && variant4=immune
					_debug "checando a cpu$i: armv7 A8/A9/A12/A17 não afetado às variantes 3, 3a e 4"
				elif [ "$cpuarch" = 7 ] && echo "$cpupart" | grep -q -w -e 0xc0f; then
					variant1=vuln
					variant2=vuln
					[ -z "$variant3" ] && variant3=immune
					variant3a=vuln
					[ -z "$variant4" ] && variant4=immune
					_debug "checando a cpu$i: armv7 A15 não afetado às variantes 3 e 4"
				elif [ "$cpuarch" = 8 ] && echo "$cpupart" | grep -q -w -e 0xd07 -e 0xd08; then
					variant1=vuln
					variant2=vuln
					[ -z "$variant3" ] && variant3=immune
					variant3a=vuln
					variant4=vuln
					_debug "checando a cpu$i: armv8 A57/A72 não afetado a variantes 3"
				elif [ "$cpuarch" = 8 ] && echo "$cpupart" | grep -q -w -e 0xd09; then
					variant1=vuln
					variant2=vuln
					[ -z "$variant3" ] && variant3=immune
					[ -z "$variant3a" ] && variant3a=immune
					variant4=vuln
					_debug "checando a cpu$i: armv8 A73 não afetado às variantes 3 e 3a"
				elif [ "$cpuarch" = 8 ] && echo "$cpupart" | grep -q -w -e 0xd0a; then
					variant1=vuln
					variant2=vuln
					variant3=vuln
					[ -z "$variant3a" ] && variant3a=immune
					variant4=vuln
					_debug "checando a cpu$i: armv8 A75 não afetado à variante 3a"
				elif [ "$cpuarch" = 8 ] && echo "$cpupart" | grep -q -w -e 0xd0b -e 0xd0c -e 0xd0d; then
					variant1=vuln
					[ -z "$variant2" ] && variant2=immune
					[ -z "$variant3" ] && variant3=immune
					[ -z "$variant3a" ] && variant3a=immune
					variant4=vuln
					_debug "checando a cpu$i: armv8 A76/A77/NeoverseN1 não afetado às variantes 2, 3 e 3a"
				elif [ "$cpuarch" = 8 ] && echo "$cpupart" | grep -q -w -e 0xd40 -e 0xd49 -e 0xd4f; then
					variant1=vuln
					[ -z "$variant2" ] && variant2=immune
					[ -z "$variant3" ] && variant3=immune
					[ -z "$variant3a" ] && variant3a=immune
					[ -z "$variant4" ] && variant4=immune
					_debug "checando cpu$i: armv8 NeoverseN2/V1/V2 não afetado pela variante 2, 3, 3a e 4"
				elif [ "$cpuarch" -le 7 ] || { [ "$cpuarch" = 8 ] && [ $(( cpupart )) -lt $(( 0xd07 )) ]; } ; then
					[ -z "$variant1" ] && variant1=immune
					[ -z "$variant2" ] && variant2=immune
					[ -z "$variant3" ] && variant3=immune
					[ -z "$variant3a" ] && variant3a=immune
					[ -z "$variant4" ] && variant4=immune
					_debug "checando a cpu$i: arm arch$cpuarch, todos imunes (v7 ou v8 e modelo < 0xd07)"
				else
					variant1=vuln
					variant2=vuln
					variant3=vuln
					variant3a=vuln
					variant4=vuln
					_debug "checando a cpu$i: arm desconhecido arch$cpuarch part$cpupart, considerando vuln"
				fi
			fi
			_debug "is_cpu_affected: para cpu$i e até agora, temos <$variant1> <$variant2> <$variant3> <$variant3a> <$variant4>"
		done
		variantl1tf=immune
	fi

	# we handle iTLB Multihit here (not linked to is_specex_free)
	if is_intel; then
		# commit f9aa6b73a407b714c9aac44734eb4045c893c6f7
		if [ "$cpu_family" = 6 ]; then
			if [ "$cpu_model" = "$INTEL_FAM6_ATOM_SALTWELL" ] || \
				[ "$cpu_model" = "$INTEL_FAM6_ATOM_SALTWELL_TABLET" ] || \
				[ "$cpu_model" = "$INTEL_FAM6_ATOM_SALTWELL_MID" ] || \
				[ "$cpu_model" = "$INTEL_FAM6_ATOM_BONNELL" ] || \
				[ "$cpu_model" = "$INTEL_FAM6_ATOM_BONNELL_MID" ] || \
				[ "$cpu_model" = "$INTEL_FAM6_ATOM_SILVERMONT" ] || \
				[ "$cpu_model" = "$INTEL_FAM6_ATOM_SILVERMONT_D" ] || \
				[ "$cpu_model" = "$INTEL_FAM6_ATOM_SILVERMONT_MID" ] || \
				[ "$cpu_model" = "$INTEL_FAM6_ATOM_AIRMONT" ] || \
				[ "$cpu_model" = "$INTEL_FAM6_XEON_PHI_KNL" ] || \
				[ "$cpu_model" = "$INTEL_FAM6_XEON_PHI_KNM" ] || \
				[ "$cpu_model" = "$INTEL_FAM6_ATOM_AIRMONT_MID" ] || \
				[ "$cpu_model" = "$INTEL_FAM6_ATOM_GOLDMONT" ] || \
				[ "$cpu_model" = "$INTEL_FAM6_ATOM_GOLDMONT_D" ] || \
				[ "$cpu_model" = "$INTEL_FAM6_ATOM_GOLDMONT_PLUS" ]; then
				_debug "is_cpu_affected: família intel 6, mas modelo conhecido por ser imune a itlbmh"
				[ -z "$variant_itlbmh" ] && variant_itlbmh=immune
			else
				_debug "is_cpu_affected: família intel 6 é vulnerável a itlbmh"
				variant_itlbmh=vuln
			fi
		elif [ "$cpu_family" -lt 6 ]; then
			_debug "is_cpu_affected: família intel < 6 é imune a itlbmh"
			[ -z "$variant_itlbmh" ] && variant_itlbmh=immune
		fi
	else
		_debug "is_cpu_affected: não-intel não afetado para itlbmh"
		[ -z "$variant_itlbmh" ] && variant_itlbmh=immune
	fi

	_debug "is_cpu_affected: resultados temporários são <$variant1> <$variant2> <$variant3> <$variant3a> <$variant4> <$variantl1tf>"
	[ "$variant1"          = "immune" ] && variant1=1       || variant1=0
	[ "$variant2"          = "immune" ] && variant2=1       || variant2=0
	[ "$variant3"          = "immune" ] && variant3=1       || variant3=0
	[ "$variant3a"         = "immune" ] && variant3a=1      || variant3a=0
	[ "$variant4"          = "immune" ] && variant4=1       || variant4=0
	[ "$variantl1tf"       = "immune" ] && variantl1tf=1    || variantl1tf=0
	[ "$variant_msbds"     = "immune" ] && variant_msbds=1  || variant_msbds=0
	[ "$variant_mfbds"     = "immune" ] && variant_mfbds=1  || variant_mfbds=0
	[ "$variant_mlpds"     = "immune" ] && variant_mlpds=1  || variant_mlpds=0
	[ "$variant_mdsum"     = "immune" ] && variant_mdsum=1  || variant_mdsum=0
	[ "$variant_taa"       = "immune" ] && variant_taa=1    || variant_taa=0
	[ "$variant_itlbmh"    = "immune" ] && variant_itlbmh=1 || variant_itlbmh=0
	[ "$variant_srbds"     = "immune" ] && variant_srbds=1  || variant_srbds=0
	[ "$variant_zenbleed"  = "immune" ] && variant_zenbleed=1  || variant_zenbleed=0
	[ "$variant_downfall"  = "immune" ] && variant_downfall=1  || variant_downfall=0
	[ "$variant_inception" = "immune" ] && variant_inception=1 || variant_inception=0
	[ "$variant_reptar"    = "immune" ] && variant_reptar=1    || variant_reptar=0
	variantl1tf_sgx="$variantl1tf"
	# even if we are affected to L1TF, if there's no SGX, we're not affected to the original foreshadow
	[ "$cpuid_sgx" = 0 ] && variantl1tf_sgx=1
	_debug "is_cpu_affected: resultados finais são <$variant1> <$variant2> <$variant3> <$variant3a> <$variant4> <$variantl1tf> <$variantl1tf_sgx>"
	is_cpu_affected_cached=1
	_is_cpu_affected_cached "$1"
	return $?
}

is_cpu_specex_free()
{
	# return true (0) if the CPU doesn't do speculative execution, false (1) if it does.
	# if it's not in the list we know, return false (1).
	# source: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/x86/kernel/cpu/common.c#n882
	# { X86_VENDOR_INTEL,	6, INTEL_FAM6_ATOM_SALTWELL,	X86_FEATURE_ANY },
	# { X86_VENDOR_INTEL,	6, INTEL_FAM6_ATOM_SALTWELL_TABLET,	X86_FEATURE_ANY },
	# { X86_VENDOR_INTEL,	6, INTEL_FAM6_ATOM_BONNELL_MID,	X86_FEATURE_ANY },
	# { X86_VENDOR_INTEL,	6, INTEL_FAM6_ATOM_SALTWELL_MID,	X86_FEATURE_ANY },
	# { X86_VENDOR_INTEL,	6, INTEL_FAM6_ATOM_BONNELL,	X86_FEATURE_ANY },
	# { X86_VENDOR_CENTAUR,   5 },
	# { X86_VENDOR_INTEL,     5 },
	# { X86_VENDOR_NSC,       5 },
	# { X86_VENDOR_ANY,       4 },

	parse_cpu_details
	if is_intel; then
		if [ "$cpu_family" = 6 ]; then
			if [ "$cpu_model" = "$INTEL_FAM6_ATOM_SALTWELL"	] || \
				[ "$cpu_model" = "$INTEL_FAM6_ATOM_SALTWELL_TABLET"	] || \
				[ "$cpu_model" = "$INTEL_FAM6_ATOM_BONNELL_MID"		] || \
				[ "$cpu_model" = "$INTEL_FAM6_ATOM_SALTWELL_MID"	] || \
				[ "$cpu_model" = "$INTEL_FAM6_ATOM_BONNELL"	]; then
				return 0
			fi
		elif [ "$cpu_family" = 5 ]; then
			return 0
		fi
	fi
	[ "$cpu_family" = 4 ] && return 0
	return 1
}

is_cpu_mds_free()
{
	# return true (0) if the CPU isn't affected by microarchitectural data sampling, false (1) if it does.
	# if it's not in the list we know, return false (1).
	# source: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/x86/kernel/cpu/common.c
	#VULNWL_INTEL(ATOM_GOLDMONT,             NO_MDS | NO_L1TF),
	#VULNWL_INTEL(ATOM_GOLDMONT_X,           NO_MDS | NO_L1TF),
	#VULNWL_INTEL(ATOM_GOLDMONT_PLUS,        NO_MDS | NO_L1TF),

	#/* AMD Family 0xf - 0x12 */
	#VULNWL_AMD(0x0f,        NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS),
	#VULNWL_AMD(0x10,        NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS),
	#VULNWL_AMD(0x11,        NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS),
	#VULNWL_AMD(0x12,        NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS),

	#/* FAMILY_ANY must be last, otherwise 0x0f - 0x12 matches won't work */
	#VULNWL_AMD(X86_FAMILY_ANY,      NO_MELTDOWN | NO_L1TF | NO_MDS),
	#VULNWL_HYGON(X86_FAMILY_ANY,    NO_MELTDOWN | NO_L1TF | NO_MDS),
	parse_cpu_details
	if is_intel; then
		if [ "$cpu_family" = 6 ]; then
			if [ "$cpu_model" = "$INTEL_FAM6_ATOM_GOLDMONT" ] || \
				[ "$cpu_model" = "$INTEL_FAM6_ATOM_GOLDMONT_D" ] || \
				[ "$cpu_model" = "$INTEL_FAM6_ATOM_GOLDMONT_PLUS" ]; then
				return 0
			fi
		fi
		[ "$capabilities_mds_no" = 1 ] && return 0
	fi

	# official statement from AMD says none of their CPUs are affected
	# https://www.amd.com/en/corporate/product-security
	# https://www.amd.com/system/files/documents/security-whitepaper.pdf
	if is_amd; then
		return 0
	elif is_hygon; then
		return 0
	elif [ "$cpu_vendor" = CAVIUM ]; then
		return 0
	elif [ "$cpu_vendor" = PHYTIUM ]; then
		return 0
	elif [ "$cpu_vendor" = ARM ]; then
		return 0
	fi

	return 1
}


is_cpu_taa_free()
{
	# return true (0) if the CPU isn't affected by tsx asynchronous aborts, false (1) if it does.
	# There are three types of processors that do not require additional mitigations.
	# 1. CPUs that do not support Intel TSX are not affected.
	# 2. CPUs that enumerate IA32_ARCH_CAPABILITIES[TAA_NO] (bit 8)=1 are not affected.
	# 3. CPUs that support Intel TSX and do not enumerate IA32_ARCH_CAPABILITIES[MDS_NO] (bit 5)=1
	# do not need additional mitigations beyond what is already required to mitigate MDS.

	if ! is_intel; then
		return 0
	# is intel
	elif [ "$capabilities_taa_no" = 1 ] || [ "$cpuid_rtm" = 0 ]; then
		return 0
	fi

	return 1
}

is_cpu_srbds_free()
{
	# return zero (0) if the CPU isn't affected by special register buffer data sampling, one (1) if it is.
	# If it's not in the list we know, return one (1).
	# source: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/x86/kernel/cpu/common.c
	#
	# A processor is affected by SRBDS if its Family_Model and stepping is in the
	# following list, with the exception of the listed processors
	# exporting MDS_NO while Intel TSX is available yet not enabled. The
	# latter class of processors are only affected when Intel TSX is enabled
	# by software using TSX_CTRL_MSR otherwise they are not affected.
	#
	# =============  ============  ========
	# common name    Family_Model  Stepping
	# =============  ============  ========
	# IvyBridge      06_3AH        All              (INTEL_FAM6_IVYBRIDGE)
	#
	# Haswell        06_3CH        All              (INTEL_FAM6_HASWELL)
	# Haswell_L      06_45H        All              (INTEL_FAM6_HASWELL_L)
	# Haswell_G      06_46H        All              (INTEL_FAM6_HASWELL_G)
	#
	# Broadwell_G    06_47H        All              (INTEL_FAM6_BROADWELL_G)
	# Broadwell      06_3DH        All              (INTEL_FAM6_BROADWELL)
	#
	# Skylake_L      06_4EH        All              (INTEL_FAM6_SKYLAKE_L)
	# Skylake        06_5EH        All              (INTEL_FAM6_SKYLAKE)
	#
	# Kabylake_L     06_8EH        <=0xC (MDS_NO)   (INTEL_FAM6_KABYLAKE_L)
	#
	# Kabylake       06_9EH        <=0xD (MDS_NO)   (INTEL_FAM6_KABYLAKE)
	# =============  ============  ========
	parse_cpu_details
	if is_intel; then
		if [ "$cpu_family" = 6 ]; then
			if [ "$cpu_model" = "$INTEL_FAM6_IVYBRIDGE" ] || \
				[ "$cpu_model" = "$INTEL_FAM6_HASWELL" ] || \
				[ "$cpu_model" = "$INTEL_FAM6_HASWELL_L" ] || \
				[ "$cpu_model" = "$INTEL_FAM6_HASWELL_G" ] || \
				[ "$cpu_model" = "$INTEL_FAM6_BROADWELL_G" ] || \
				[ "$cpu_model" = "$INTEL_FAM6_BROADWELL" ] || \
				[ "$cpu_model" = "$INTEL_FAM6_SKYLAKE_L" ] || \
				[ "$cpu_model" = "$INTEL_FAM6_SKYLAKE" ]; then
				return 1
			elif [ "$cpu_model" = "$INTEL_FAM6_KABYLAKE_L" ] && [ "$cpu_stepping" -le 12 ] || \
				[ "$cpu_model" = "$INTEL_FAM6_KABYLAKE" ] && [ "$cpu_stepping" -le 13 ]; then
				if [ "$capabilities_mds_no" -eq 1 ] && { [ "$cpuid_rtm" -eq 0 ] || [ "$tsx_ctrl_msr_rtm_disable" -eq 1 ] ;} ; then
					return 0
				else
					return 1
				fi
			fi
		fi
	fi

	return 0

}

is_cpu_ssb_free()
{
	# return true (0) if the CPU isn't affected by speculative store bypass, false (1) if it does.
	# if it's not in the list we know, return false (1).
	# source1: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/x86/kernel/cpu/common.c#n945
	# source2: https://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git/tree/arch/x86/kernel/cpu/common.c
	# Only list CPUs that speculate but are immune, to avoid duplication of cpus listed in is_cpu_specex_free()
	#{ X86_VENDOR_INTEL,	6,	INTEL_FAM6_ATOM_SILVERMONT	},
	#{ X86_VENDOR_INTEL,	6,	INTEL_FAM6_ATOM_AIRMONT		},
	#{ X86_VENDOR_INTEL,	6,	INTEL_FAM6_ATOM_SILVERMONT_X	},
	#{ X86_VENDOR_INTEL,	6,	INTEL_FAM6_ATOM_SILVERMONT_MID	},
	#{ X86_VENDOR_INTEL,	6,	INTEL_FAM6_CORE_YONAH		},
	#{ X86_VENDOR_INTEL,	6,	INTEL_FAM6_XEON_PHI_KNL		},
	#{ X86_VENDOR_INTEL,	6,	INTEL_FAM6_XEON_PHI_KNM		},
	#{ X86_VENDOR_AMD,	0x12,					},
	#{ X86_VENDOR_AMD,	0x11,					},
	#{ X86_VENDOR_AMD,	0x10,					},
	#{ X86_VENDOR_AMD,	0xf,					},
	parse_cpu_details
	if is_intel; then
		if [ "$cpu_family" = 6 ]; then
			if [ "$cpu_model" = "$INTEL_FAM6_ATOM_AIRMONT"          ] || \
				[ "$cpu_model" = "$INTEL_FAM6_ATOM_SILVERMONT" ] || \
				[ "$cpu_model" = "$INTEL_FAM6_ATOM_SILVERMONT_D" ] || \
				[ "$cpu_model" = "$INTEL_FAM6_ATOM_SILVERMONT_MID"  ]; then
				return 0
			elif [ "$cpu_model" = "$INTEL_FAM6_CORE_YONAH"          ] || \
				[ "$cpu_model" = "$INTEL_FAM6_XEON_PHI_KNL"     ] || \
				[ "$cpu_model" = "$INTEL_FAM6_XEON_PHI_KNM"     ]; then
				return 0
			fi
		fi
	fi
	if is_amd; then
		if [ "$cpu_family" = "18" ] || \
			[ "$cpu_family" = "17" ] || \
			[ "$cpu_family" = "16" ] || \
			[ "$cpu_family" = "15" ]; then 
			return 0
		fi
	fi
	if is_hygon; then
		return 1
	fi
	[ "$cpu_family" = 4 ] && return 0
	return 1
}

show_header()
{
	_info "Ferramenta de detecção de mitigação Spectre e Meltdown v$VERSION"
	_info
}

# Family-Model-Stepping to CPUID
# prints CPUID in base-10 to stdout
fms2cpuid()
{
	_family="$1"
	_model="$2"
	_stepping="$3"

	if [ "$(( _family ))" -le 15 ]; then
		_extfamily=0
		_lowfamily=$(( _family ))
	else
		# when we have a family > 0xF, then lowfamily is stuck at 0xF
		# and extfamily is ADDED to it (as in "+"), to ensure old software
		# never sees a lowfamily < 0xF for newer families
		_lowfamily=15
		_extfamily=$(( (_family) - 15 ))
	fi
	_extmodel=$((  (_model  & 0xF0 ) >> 4 ))
	_lowmodel=$((  (_model  & 0x0F ) >> 0 ))
	echo $(( (_stepping & 0x0F) | (_lowmodel << 4) | (_lowfamily << 8) | (_extmodel << 16) | (_extfamily << 20) ))
}

download_file()
{
	_url="$1"
	_file="$2"
	if command -v wget >/dev/null 2>&1; then
		wget -q "$_url" -O "$_file"; ret=$?
	elif command -v curl >/dev/null 2>&1; then
		curl -sL "$_url" -o "$_file"; ret=$?
	elif command -v fetch >/dev/null 2>&1; then
		fetch -q "$_url" -o "$_file"; ret=$?
	else
		echo ERROR "instale um dos programas \`wget\`, \`curl\` de \`fetch\`"
		unset _file _url
		return 1
	fi
	unset _file _url
	if [ "$ret" != 0 ]; then
		echo ERROR "erro $ret"
		return $ret
	fi
	echo DONE
}

[ -z "$HOME" ] && HOME="$(getent passwd "$(whoami)" | cut -d: -f6)"
mcedb_cache="$HOME/.mcedb"
update_fwdb()
{
	show_header

	set -e

	if [ -r "$mcedb_cache" ]; then
		previous_dbversion=$(awk '/^# %%% MCEDB / { print $4 }' "$mcedb_cache")
	fi

	# first, download the MCE.db from the excellent platomav's MCExtractor project
	mcedb_tmp="$(mktemp -t smc-mcedb-XXXXXX)"
	mcedb_url='https://github.com/platomav/MCExtractor/raw/master/MCE.db'
	_info_nol "Obtendo MCE.db do projeto MCExtractor... "
	download_file "$mcedb_url" "$mcedb_tmp" || return $?

	# second, get the Intel firmwares from GitHub
	intel_tmp="$(mktemp -d -t smc-intelfw-XXXXXX)"
	intel_url="https://github.com/intel/Intel-Linux-Processor-Microcode-Data-Files/archive/main.zip"
	_info_nol "Buscando firmwares Intel... "
	## https://github.com/intel/Intel-Linux-Processor-Microcode-Data-Files.git
	download_file "$intel_url" "$intel_tmp/fw.zip" || return $?

	# now extract MCEdb contents using sqlite
	_info_nol "Extraindo dados MCEdb... "
	if ! command -v sqlite3 >/dev/null 2>&1; then
		echo ERROR "instale o programa \`sqlite3\`"
		return 1
	fi
	mcedb_revision=$(sqlite3 "$mcedb_tmp" "SELECT \"revision\" from \"MCE\"")
	if [ -z "$mcedb_revision" ]; then
		echo ERROR "arquivo baixado parece inválido"
		return 1
	fi
	sqlite3 "$mcedb_tmp" "ALTER TABLE \"Intel\" ADD COLUMN \"origin\" TEXT"
	sqlite3 "$mcedb_tmp" "ALTER TABLE \"Intel\" ADD COLUMN \"pfmask\" TEXT"
	sqlite3 "$mcedb_tmp" "ALTER TABLE \"AMD\" ADD COLUMN \"origin\" TEXT"
	sqlite3 "$mcedb_tmp" "ALTER TABLE \"AMD\" ADD COLUMN \"pfmask\" TEXT"
	sqlite3 "$mcedb_tmp" "UPDATE \"Intel\" SET \"origin\"='mce'"
	sqlite3 "$mcedb_tmp" "UPDATE \"Intel\" SET \"pfmask\"='FF'"
	sqlite3 "$mcedb_tmp" "UPDATE \"AMD\" SET \"origin\"='mce'"
	sqlite3 "$mcedb_tmp" "UPDATE \"AMD\" SET \"pfmask\"='FF'"

	echo OK "Revisão do banco de dados MCExtractor $mcedb_revision"

	# parse Intel firmwares to get their versions
	_info_nol "Integrando dados de firmwares da Intel ao db... "
	if ! command -v unzip >/dev/null 2>&1; then
		echo ERROR "por favor, instale o programa \`unzip\`"
		return 1
	fi
	( cd "$intel_tmp" && unzip fw.zip >/dev/null; )
	if ! [ -d "$intel_tmp/Intel-Linux-Processor-Microcode-Data-Files-main/intel-ucode" ]; then
		echo ERROR "esperava a pasta 'intel-ucode' no arquivo zip baixado"
		return 1
	fi

	if ! command -v iucode_tool >/dev/null 2>&1; then
		if ! command -v iucode-tool >/dev/null 2>&1; then
			echo ERROR "por favor, instale o programa \`iucode-tool\`"
			return 1
		else
			iucode_tool="iucode-tool"
		fi
	else
		iucode_tool="iucode_tool"
	fi
	#  079/001: sig 0x000106c2, pf_mask 0x01, 2009-04-10, rev 0x0217, size 5120
	#  078/004: sig 0x000106ca, pf_mask 0x10, 2009-08-25, rev 0x0107, size 5120
	$iucode_tool -l "$intel_tmp/Intel-Linux-Processor-Microcode-Data-Files-main/intel-ucode" | grep -wF sig | while read -r _line
	do
		_cpuid=$(echo "$_line" | grep -Eio 'sig 0x[0-9a-f]+' | awk '{print $2}')
		_cpuid=$(( _cpuid ))
		_cpuid=$(printf "%08X" "$_cpuid")
		_pfmask=$(echo "$_line" | grep -Eio 'pf_mask 0x[0-9a-f]+' | awk '{print $2}')
		_pfmask=$(( _pfmask ))
		_pfmask=$(printf "%02X" $_pfmask)
		_date=$(echo "$_line" | grep -Eo '(19|20)[0-9][0-9]-[01][0-9]-[0-3][0-9]' | tr -d '-')
		_version=$(echo "$_line" | grep -Eio 'rev 0x[0-9a-f]+' | awk '{print $2}')
		_version=$(( _version ))
		_version=$(printf "%08X" "$_version")
		# ensure the official Intel DB always has precedence over mcedb, even if mcedb has seen a more recent fw
		sqlite3 "$mcedb_tmp" "DELETE FROM \"Intel\" WHERE \"origin\" != 'intel' AND \"cpuid\" = '$_cpuid';"
		# then insert our version
		sqlite3 "$mcedb_tmp" "INSERT INTO \"Intel\" (\"origin\",\"cpuid\",\"pfmask\",\"version\",\"yyyymmdd\") VALUES ('intel','$_cpuid','$_pfmask','$_version','$_date');"
	done
	_intel_timestamp=$(stat -c %Y "$intel_tmp/Intel-Linux-Processor-Microcode-Data-Files-main/license" 2>/dev/null)
	if [ -n "$_intel_timestamp" ]; then
		# use this date, it matches the last commit date
		_intel_latest_date=$(date +%Y%m%d -d @"$_intel_timestamp")
	else
		echo "Voltando para a última data do microcódigo"
		_intel_latest_date=$(sqlite3 "$mcedb_tmp" "SELECT \"yyyymmdd\" FROM \"Intel\" WHERE \"origin\"='intel' ORDER BY \"yyyymmdd\" DESC LIMIT 1;")
	fi
	echo DONE "(version $_intel_latest_date)"

	# now parse the most recent linux-firmware amd-ucode README file
	_info_nol "Buscando o último README amd-ucode do projeto linux-firmware... "
	linuxfw_url="https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git/plain/amd-ucode/README"
	linuxfw_tmp=$(mktemp -t smc-linuxfw-XXXXXX)
	download_file "$linuxfw_url" "$linuxfw_tmp" || return $?

	_info_nol "Analisando o README... "
	nbfound=0
	for line in $(grep -E 'Family=0x[0-9a-f]+ Model=0x[0-9a-f]+ Stepping=0x[0-9a-f]+: Patch=0x[0-9a-f]+' "$linuxfw_tmp" | tr " " ","); do
		_debug "Analisando a linha $line"
		_family=$(  echo "$line" | grep -Eoi 'Family=0x[0-9a-f]+'   | cut -d= -f2)
		_model=$(   echo "$line" | grep -Eoi 'Model=0x[0-9a-f]+'    | cut -d= -f2)
		_stepping=$(echo "$line" | grep -Eoi 'Stepping=0x[0-9a-f]+' | cut -d= -f2)
		_version=$( echo "$line" | grep -Eoi 'Patch=0x[0-9a-f]+'    | cut -d= -f2)
		_version=$(printf "%08X" "$(( _version ))")
		_cpuid=$(fms2cpuid "$_family" "$_model" "$_stepping")
		_cpuid=$(printf "%08X" "$_cpuid")
		_sqlstm="INSERT INTO \"AMD\" (\"origin\",\"cpuid\",\"pfmask\",\"version\",\"yyyymmdd\") VALUES ('linux-firmware','$_cpuid','FF','$_version','20000101')"
		_debug "família $_family modelo $_model stepping $_stepping cpuid $_cpuid"
		_debug "$_sqlstm"
		sqlite3 "$mcedb_tmp" "$_sqlstm"
		nbfound=$((nbfound + 1))
		unset _family _model _stepping _version _cpuid _date _sqlstm
	done
	echo "encontrados microcódigos $nbfound"
	unset nbfound

	dbversion="$mcedb_revision+i$_intel_latest_date"
	linuxfw_hash=$(md5sum "$linuxfw_tmp" 2>/dev/null | cut -c1-4)
	if [ -n "$linuxfw_hash" ]; then
		dbversion="$dbversion+$linuxfw_hash"
	fi

	if [ "$1" != builtin ] && [ -n "$previous_dbversion" ] && [ "$previous_dbversion" = "v$dbversion" ]; then
		echo "Já temos esta versão localmente, nenhuma atualização necessária"
		return 0
	fi

	_info_nol "Criando banco de dados local... "
	{
		echo "# Spectre e Meltdown Checker";
		echo "# %%% MCEDB v$dbversion";
		# we'll use the more recent fw for Intel and AMD
		sqlite3 "$mcedb_tmp" "SELECT '# I,0x'||\"t1\".\"cpuid\"||',0x'||\"t1\".\"pfmask\"||',0x'||MAX(\"t1\".\"version\")||','||\"t1\".\"yyyymmdd\" FROM \"Intel\" AS \"t1\" LEFT OUTER JOIN \"Intel\" AS \"t2\" ON \"t2\".\"cpuid\"=\"t1\".\"cpuid\" AND \"t2\".\"pfmask\"=\"t1\".\"pfmask\" AND \"t2\".\"yyyymmdd\" > \"t1\".\"yyyymmdd\" WHERE \"t2\".\"yyyymmdd\" IS NULL GROUP BY \"t1\".\"cpuid\",\"t1\".\"pfmask\" ORDER BY \"t1\".\"cpuid\",\"t1\".\"pfmask\" ASC;" | grep -v '^# .,0x00000000,';
		sqlite3 "$mcedb_tmp" "SELECT '# A,0x'||\"t1\".\"cpuid\"||',0x'||\"t1\".\"pfmask\"||',0x'||MAX(\"t1\".\"version\")||','||\"t1\".\"yyyymmdd\" FROM \"AMD\"   AS \"t1\" LEFT OUTER JOIN \"AMD\"   AS \"t2\" ON \"t2\".\"cpuid\"=\"t1\".\"cpuid\" AND \"t2\".\"pfmask\"=\"t1\".\"pfmask\" AND \"t2\".\"yyyymmdd\" > \"t1\".\"yyyymmdd\" WHERE \"t2\".\"yyyymmdd\" IS NULL GROUP BY \"t1\".\"cpuid\",\"t1\".\"pfmask\" ORDER BY \"t1\".\"cpuid\",\"t1\".\"pfmask\" ASC;" | grep -v '^# .,0x00000000,';
	} > "$mcedb_cache"
	echo DONE "(versão $dbversion)"

	if [ "$1" = builtin ]; then
		newfile=$(mktemp -t smc-builtin-XXXXXX)
		awk '/^# %%% MCEDB / { exit }; { print }' "$0" > "$newfile"
		awk '{ if (NR>1) { print } }' "$mcedb_cache" >> "$newfile"
		cat "$newfile" > "$0"
		rm -f "$newfile"
	fi
}

parse_opt_file()
{
	# parse_opt_file option_name option_value
	option_name="$1"
	option_value="$2"
	if [ -z "$option_value" ]; then
		show_header
		show_usage
		echo "$0: erro: --$option_name espera um parâmetro (um arquivo)" >&2
		exit 1
	elif [ ! -e "$option_value" ]; then
		show_header
		echo "$0: erro: não foi possível encontrar o arquivo $option_value" >&2
		exit 1
	elif [ ! -f "$option_value" ]; then
		show_header
		echo "$0: erro: $option_value não é um arquivo" >&2
		exit 1
	elif [ ! -r "$option_value" ]; then
		show_header
		echo "$0: erro: não foi possível ler $option_value (você é root?)" >&2
		exit 1
	fi
	echo "$option_value"
	exit 0
}

while [ -n "${1:-}" ]; do
	if [ "$1" = "--kernel" ]; then
		opt_kernel=$(parse_opt_file kernel "$2"); ret=$?
		[ $ret -ne 0 ] && exit 255
		shift 2
	elif [ "$1" = "--config" ]; then
		opt_config=$(parse_opt_file config "$2"); ret=$?
		[ $ret -ne 0 ] && exit 255
		shift 2
	elif [ "$1" = "--map" ]; then
		opt_map=$(parse_opt_file map "$2"); ret=$?
		[ $ret -ne 0 ] && exit 255
		shift 2
	elif [ "$1" = "--arch-prefix" ]; then
		opt_arch_prefix="$2"
		shift 2
	elif [ "$1" = "--live" ]; then
		opt_live=1
		shift
	elif [ "$1" = "--no-color" ]; then
		opt_no_color=1
		shift
	elif [ "$1" = "--no-sysfs" ]; then
		opt_no_sysfs=1
		shift
	elif [ "$1" = "--sysfs-only" ]; then
		opt_sysfs_only=1
		shift
	elif [ "$1" = "--coreos" ]; then
		opt_coreos=1
		shift
	elif [ "$1" = "--coreos-within-toolbox" ]; then
		# don't use directly: used internally by --coreos
		opt_coreos=0
		shift
	elif [ "$1" = "--paranoid" ]; then
		opt_paranoid=1
		shift
	elif [ "$1" = "--hw-only" ]; then
		opt_hw_only=1
		shift
	elif [ "$1" = "--no-hw" ]; then
		opt_no_hw=1
		shift
	elif [ "$1" = "--allow-msr-write" ]; then
		opt_allow_msr_write=1
		shift
	elif [ "$1" = "--no-intel-db" ]; then
		opt_intel_db=0
		shift
	elif [ "$1" = "--cpu" ]; then
		opt_cpu=$2
		if [ "$opt_cpu" != all ]; then
			if echo "$opt_cpu" | grep -Eq '^[0-9]+'; then
				opt_cpu=$(( opt_cpu ))
			else
				echo "$0: erro: --cpu deve ser um número inteiro ou 'todos', obteve '$opt_cpu'" >&2
				exit 255
			fi
		fi
		shift 2
	elif [ "$1" = "--no-explain" ]; then
		# deprecated, kept for compatibility
		opt_explain=0
		shift
	elif [ "$1" = "--update-fwdb" ] || [ "$1" = "--update-mcedb" ]; then
		update_fwdb
		exit $?
	elif [ "$1" = "--update-builtin-fwdb" ] || [ "$1" = "--update-builtin-mcedb" ]; then
		update_fwdb builtin
		exit $?
	elif [ "$1" = "--dump-mock-data" ]; then
		opt_mock=1
		shift
	elif [ "$1" = "--explain" ]; then
		opt_explain=1
		shift
	elif [ "$1" = "--batch" ]; then
		opt_batch=1
		opt_verbose=0
		opt_no_color=1
		shift
		case "$1" in
			text|short|nrpe|json|prometheus) opt_batch_format="$1"; shift;;
			--*) ;;    # allow subsequent flags
			'') ;;     # allow nothing at all
			*)
				echo "$0: erro: formato de lote desconhecido '$1'" >&2
				echo "$0: erro: --batch espera um formato de: text, nrpe, json" >&2
				exit 255
				;;
		esac
	elif [ "$1" = "-v" ] || [ "$1" = "--verbose" ]; then
		opt_verbose=$(( opt_verbose + 1 ))
		[ "$opt_verbose" -ge 2 ] && opt_mock=1
		shift
	elif [ "$1" = "--cve" ]; then
		if [ -z "$2" ]; then
			echo "$0: erro: option --cve espera um parâmetro, CVEs suportados são: $supported_cve_list" >&2
			exit 255
		fi
		selected_cve=$(echo "$supported_cve_list" | grep -iwo "$2")
		if [ -n "$selected_cve" ]; then
			opt_cve_list="$opt_cve_list $selected_cve"
			opt_cve_all=0
		else
			echo "$0: erro: CVE não suportado especificado ('$2'), os CVEs suportados são: $supported_cve_list" >&2
			exit 255
		fi
		shift 2
	elif [ "$1" = "--vmm" ]; then
		if [ -z "$2" ]; then
			echo "$0: erro: opção --vmm (auto, yes, no)" >&2
			exit 255
		fi
		case "$2" in
			auto) opt_vmm=-1;;
			yes)  opt_vmm=1;;
			no)   opt_vmm=0;;
			*)    echo "$0: erro: esperado um de (auto, yes, no) para a opção --vmm em vez de '$2'" >&2; exit 255;;
		esac
		shift 2
	elif [ "$1" = "--variant" ]; then
		if [ -z "$2" ]; then
			echo "$0: erro: a opção --variant espera um parâmetro (consulte a ajuda de --variant)" >&2
			exit 255
		fi
		case "$2" in
			help)	echo "Os seguintes parâmetros são compatíveis com --variant (podem ser usados várias vezes):";
					echo "1, 2, 3, 3a, 4, msbds, mfbds, mlpds, mdsum, l1tf, taa, mcepsc, srbds, zenbleed, downfall, inception";
					exit 0;;
			1)			opt_cve_list="$opt_cve_list CVE-2017-5753"; opt_cve_all=0;;
			2)			opt_cve_list="$opt_cve_list CVE-2017-5715"; opt_cve_all=0;;
			3)			opt_cve_list="$opt_cve_list CVE-2017-5754"; opt_cve_all=0;;
			3a)			opt_cve_list="$opt_cve_list CVE-2018-3640"; opt_cve_all=0;;
			4)			opt_cve_list="$opt_cve_list CVE-2018-3639"; opt_cve_all=0;;
			msbds)		opt_cve_list="$opt_cve_list CVE-2018-12126"; opt_cve_all=0;;
			mfbds)		opt_cve_list="$opt_cve_list CVE-2018-12130"; opt_cve_all=0;;
			mlpds)		opt_cve_list="$opt_cve_list CVE-2018-12127"; opt_cve_all=0;;
			mdsum)		opt_cve_list="$opt_cve_list CVE-2019-11091"; opt_cve_all=0;;
			l1tf)		opt_cve_list="$opt_cve_list CVE-2018-3615 CVE-2018-3620 CVE-2018-3646"; opt_cve_all=0;;
			taa)		opt_cve_list="$opt_cve_list CVE-2019-11135"; opt_cve_all=0;;
			mcepsc)		opt_cve_list="$opt_cve_list CVE-2018-12207"; opt_cve_all=0;;
			srbds)		opt_cve_list="$opt_cve_list CVE-2020-0543"; opt_cve_all=0;;
			zenbleed)	opt_cve_list="$opt_cve_list CVE-2023-20593"; opt_cve_all=0;;
			downfall)   opt_cve_list="$opt_cve_list CVE-2022-40982"; opt_cve_all=0;;
			inception)  opt_cve_list="$opt_cve_list CVE-2023-20569"; opt_cve_all=0;;
			reptar)     opt_cve_list="$opt_cve_list CVE-2023-23583"; opt_cve_all=0;;
			*)
				echo "$0: erro: parâmetro inválido '$2' para --variant, consulte a ajuda de --variant para obter uma lista" >&2;
				exit 255
				;;
		esac
		shift 2
	elif [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
		show_header
		show_usage
		exit 0
	elif [ "$1" = "--version" ]; then
		opt_no_color=1
		show_header
		exit 0
	elif [ "$1" = "--disclaimer" ]; then
		show_header
		show_disclaimer
		exit 0
	else
		show_header
		show_usage
		echo "$0: erro: opção desconhecida '$1'"
		exit 255
	fi
done

show_header

if [ "$opt_no_sysfs" = 1 ] && [ "$opt_sysfs_only" = 1 ]; then
	_warn "Opções incompatíveis especificadas (--no-sysfs e --sysfs-only), cancelando"
	exit 255
fi

if [ "$opt_no_hw" = 1 ] && [ "$opt_hw_only" = 1 ]; then
	_warn "Opções incompatíveis especificadas (--no-hw e --hw-only), cancelando"
	exit 255
fi

if [ "$opt_live" = -1 ]; then
	if [ -n "$opt_kernel" ] || [ -n "$opt_config" ] || [ -n "$opt_map" ]; then
		# no --live specified and we have a least one of the kernel/config/map files on the cmdline: offline mode
		opt_live=0
	else
		opt_live=1
	fi
fi

# print status function
# param1: color
# param2: message to print
# param3(optional): supplement message to print between ()
pstatus()
{
	if [ "$opt_no_color" = 1 ]; then
		_info_nol "$2"
	else
		case "$1" in
			red)    _col="\033[41m\033[30m";;
			green)  _col="\033[42m\033[30m";;
			yellow) _col="\033[43m\033[30m";;
			blue)   _col="\033[44m\033[30m";;
			*)      _col="";;
		esac
		_info_nol "$_col $2 \033[0m"
	fi
	[ -n "${3:-}" ] && _info_nol " ($3)"
	_info
	unset _col
}

# Print the final status of a vulnerability (incl. batch mode)
# Arguments are: CVE UNK/OK/VULN description
pvulnstatus()
{
	pvulnstatus_last_cve="$1"
	if [ "$opt_batch" = 1 ]; then
		case "$1" in
			CVE-2017-5753) aka="SPECTRE VARIANTE 1";;
			CVE-2017-5715) aka="SPECTRE VARIANTE 2";;
			CVE-2017-5754) aka="MELTDOWN";;
			CVE-2018-3640) aka="VARIANTE 3A";;
			CVE-2018-3639) aka="VARIANTE 4";;
			CVE-2018-3615) aka="L1TF SGX";;
			CVE-2018-3620) aka="L1TF OS";;
			CVE-2018-3646) aka="L1TF VMM";;
			CVE-2018-12126) aka="MSBDS";;
			CVE-2018-12130) aka="MFBDS";;
			CVE-2018-12127) aka="MLPDS";;
			CVE-2019-11091) aka="MDSUM";;
			CVE-2019-11135) aka="TAA";;
			CVE-2018-12207) aka="ITLBMH";;
			CVE-2020-0543) aka="SRBDS";;
			CVE-2023-20593) aka="ZENBLEED";;
			CVE-2022-40982) aka="DOWNFALL";;
			CVE-2023-20569) aka="INCEPTION";;
			CVE-2023-23583) aka="REPTAR";;
			*) echo "$0: erro: CVE inválido '$1' passado para pvulnstatus()" >&2; exit 255;;
		esac

		case "$opt_batch_format" in
			text) _echo 0 "$1: $2 ($3)";;
			short) short_output="${short_output}$1 ";;
			json)
				case "$2" in
					DES)  is_vuln="null";;
					VULN) is_vuln="true";;
					OK)   is_vuln="false";;
					*)    echo "$0: erro: status desconhecido '$2' passado para pvulnstatus()" >&2; exit 255;;
				esac
				[ -z "$json_output" ] && json_output='['
				json_output="${json_output}{\"NOME\":\"$aka\",\"CVE\":\"$1\",\"VULNERÁVEL\":$is_vuln,\"INFOS\":\"$3\"},"
				;;

			nrpe)	[ "$2" = VULN ] && nrpe_vuln="$nrpe_vuln $1";;
			prometheus)
				prometheus_output="${prometheus_output:+$prometheus_output\n}specex_vuln_status{name=\"$aka\",cve=\"$1\",status=\"$2\",info=\"$3\"} 1"
				;;
			*) echo "$0: erro: formato de lote inválido '$opt_batch_format' especificado" >&2; exit 255;;
		esac
	fi

	# always fill global_* vars because we use that do decide the program exit code
	case "$2" in
		DES)  global_unknown="1";;
		VULN) global_critical="1";;
		OK)   ;;
		*)    echo "$0: erro: status desconhecido '$2' passado para pvulnstatus()" >&2; exit 255;;
	esac

	# display info if we're not in quiet/batch mode
	vulnstatus="$2"
	shift 2
	_info_nol "> \033[46m\033[30mESTADO:\033[0m "
	: "${final_summary:=}"
	case "$vulnstatus" in
		DES)  pstatus yellow 'DESCONHECIDO'        "$@"; final_summary="$final_summary \033[43m\033[30m$pvulnstatus_last_cve:??\033[0m";;
		VULN) pstatus red    'VULNERÁVEL'     "$@"; final_summary="$final_summary \033[41m\033[30m$pvulnstatus_last_cve:KO\033[0m";;
		OK)   pstatus green  'NÃO VULNERÁVEL' "$@"; final_summary="$final_summary \033[42m\033[30m$pvulnstatus_last_cve:OK\033[0m";;
		*)    echo "$0: erro: status desconhecido '$vulnstatus' passado para pvulnstatus()" >&2; exit 255;;
	esac
}


# The 3 below functions are taken from the extract-linux script, available here:
# https://github.com/torvalds/linux/blob/master/scripts/extract-vmlinux
# The functions have been modified for better integration to this script
# The original header of the file has been retained below

# ----------------------------------------------------------------------
# extract-vmlinux - Extract uncompressed vmlinux from a kernel image
#
# Inspired from extract-ikconfig
# (c) 2009,2010 Dick Streefland <dick@streefland.net>
#
# (c) 2011      Corentin Chary <corentin.chary@gmail.com>
#
# Licensed under the GNU General Public License, version 2 (GPLv2).
# ----------------------------------------------------------------------

kernel=''
kernel_err=''
check_kernel()
{
	_file="$1"
	_mode="${2:-normal}"
	# checking the return code of readelf -h is not enough, we could get
	# a damaged ELF file and validate it, check for stderr warnings too

	# the warning "readelf: Warning: [16]: Link field (0) should index a symtab section./" can appear on valid kernels, ignore it
	_readelf_warnings=$("${opt_arch_prefix}readelf" -S "$_file" 2>&1 >/dev/null | grep -v 'should index a symtab section' | tr "\n" "/"); ret=$?
	_readelf_sections=$("${opt_arch_prefix}readelf" -S "$_file" 2>/dev/null | grep -c -e data -e text -e init)
	_kernel_size=$(stat -c %s "$_file" 2>/dev/null || stat -f %z "$_file" 2>/dev/null || echo 10000)
	_debug "check_kernel: ret=$? size=$_kernel_size sections=$_readelf_sections warnings=$_readelf_warnings"
	if [ "$_mode" = desperate ]; then
		if "${opt_arch_prefix}strings" "$_file" | grep -Eq '^Linux version '; then
			_debug "check_kernel (desesperado): ... coincide!"
			if [ "$_readelf_sections" = 0 ] && grep -qF -e armv6 -e armv7 "$_file"; then
				_debug "check_kernel (desesperado): binário raw arm encontrado, ajustando opções objdump"
				objdump_options="-D -b binary -marm"
			else
				objdump_options="-d"
			fi
			return 0
		else
			_debug "check_kernel (desesperado): ... invalido"
		fi
	else
		if [ $ret -eq 0 ] && [ -z "$_readelf_warnings" ] && [ "$_readelf_sections" -gt 0 ]; then
			if [ "$_kernel_size" -ge 100000 ]; then
				_debug "check_kernel: ... arquivo é válido"
				objdump_options="-d"
				return 0
			else
				_debug "check_kernel: ... o arquivo parece válido, mas é muito pequeno, ignorando"
			fi
		else
			_debug "check_kernel: ... arquivo é inválido"
		fi
	fi
	return 1
}

try_decompress()
{
	# The obscure use of the "tr" filter is to work around older versions of
	# "grep" that report the byte offset of the line instead of the pattern.

	# Try to find the header ($1) and decompress from here
	_debug "try_decompress: procurando $3 mágicos em $6"
	for     pos in $(tr "$1\n$2" "\n$2=" < "$6" | grep -abo "^$2")
	do
		_debug "try_decompress: mágica por US $3 encontrada no deslocamento $pos"
		if ! command -v "$3" >/dev/null 2>&1; then
			if [ "$8" = 1 ]; then
				# pass1: if the tool is not installed, just bail out silently
				# and hope that the next decompression tool will be, and that
				# it'll happen to be the proper one for this kernel
				_debug "try_decompress: a ferramenta '$3' não está instalada (passe 1), tente o próximo algo"
			else
				# pass2: if the tool is not installed, populate kernel_err this time
				kernel_err="faltando a ferramenta '$3', instale-a, geralmente está no pacote '$5'"
				_debug "try_decompress: $kernel_err"
			fi
			return 1
		fi
		pos=${pos%%:*}
		# shellcheck disable=SC2086
		tail -c+$pos "$6" 2>/dev/null | $3 $4 > "$kerneltmp" 2>/dev/null; ret=$?
		if [ ! -s "$kerneltmp" ]; then
			# don't rely on $ret, sometimes it's != 0 but worked
			# (e.g. gunzip ret=2 just means there was trailing garbage)
			_debug "try_decompress: descompressão com $3 falhou (err=$ret)"
		elif check_kernel "$kerneltmp" "$7"; then
			kernel="$kerneltmp"
			_debug "try_decompress: descompactado com $3 com sucesso!"
			return 0
		elif [ "$3" != "cat" ]; then
			_debug "try_decompress: descompressão com $3 funcionou, mas o resultado não é um kernel, tentando com um deslocamento"
			[ -z "$kerneltmp2" ] && kerneltmp2=$(mktemp -t smc-kernel-XXXXXX)
			cat "$kerneltmp" > "$kerneltmp2"
			try_decompress '\177ELF' xxy 'cat' '' cat "$kerneltmp2" && return 0
		else
			_debug "try_decompress: descompressão com $3 funcionou, mas o resultado não é um kernel"
		fi
	done
	return 1
}

extract_kernel()
{
	[ -n "${1:-}" ] || return 1
	# Prepare temp files:
	kerneltmp="$(mktemp -t smc-kernel-XXXXXX)"

	# Initial attempt for uncompressed images or objects:
	if check_kernel "$1"; then
		_debug "extract_kernel: kernel encontrado é válido, nenhuma descompressão necessária"
		cat "$1" > "$kerneltmp"
		kernel=$kerneltmp
		return 0
	fi

	# That didn't work, so retry after decompression.
	for pass in 1 2; do
		for mode in normal desperate; do
			_debug "extract_kernel: pass $pass $mode mode"
			try_decompress '\037\213\010'     xy    gunzip  ''      gunzip      "$1" "$mode" "$pass" && return 0
			try_decompress '\002\041\114\030' xyy   'lz4'   '-d -l' liblz4-tool "$1" "$mode" "$pass" && return 0
			try_decompress '\3757zXZ\000'     abcde unxz    ''      xz-utils    "$1" "$mode" "$pass" && return 0
			try_decompress 'BZh'              xy    bunzip2 ''      bzip2       "$1" "$mode" "$pass" && return 0
			try_decompress '\135\0\0\0'       xxx   unlzma  ''      xz-utils    "$1" "$mode" "$pass" && return 0
			try_decompress '\211\114\132'     xy    'lzop'  '-d'    lzop        "$1" "$mode" "$pass" && return 0
			try_decompress '\177ELF'          xxy   'cat'   ''      cat         "$1" "$mode" "$pass" && return 0
			try_decompress '(\265/\375'       xxy   unzstd  ''      zstd        "$1" "$mode" "$pass" && return 0
		done
	done
	# kernel_err might already have been populated by try_decompress() if we're missing one of the tools
	if [ -z "$kernel_err" ]; then
		kernel_err="o formato de compressão do kernel é desconhecido ou a imagem é inválida"
	fi
	_verbose "Não foi possível extrair a imagem do kernel ($kernel_err), a precisão pode ser reduzida"
	return 1
}

# end of extract-vmlinux functions

mount_debugfs()
{
	if [ ! -e /sys/kernel/debug/sched_features ]; then
		# try to mount the debugfs hierarchy ourselves and remember it to umount afterwards
		mount -t debugfs debugfs /sys/kernel/debug 2>/dev/null && mounted_debugfs=1
	fi
}

load_msr()
{
	# only attempt to do it once even if called multiple times
	[ "${load_msr_once:-}" = 1 ] && return
	load_msr_once=1

	if [ "$os" = Linux ]; then
		if ! grep -qw msr "$procfs/modules" 2>/dev/null; then
			modprobe msr 2>/dev/null && insmod_msr=1
			_debug "tentou carregar o módulo msr, insmod_msr=$insmod_msr"
		else
			_debug "módulo msr já carregado"
		fi	
	else
		if ! kldstat -q -m cpuctl; then
			kldload cpuctl 2>/dev/null && kldload_cpuctl=1
			_debug "tentou carregar o módulo cpuctl, kldload_cpuctl=$kldload_cpuctl"
		else
			_debug "módulo cpuctl já carregado"
		fi
	fi
}

load_cpuid()
{
	# only attempt to do it once even if called multiple times
	[ "${load_cpuid_once:-}" = 1 ] && return
	load_cpuid_once=1

	if [ "$os" = Linux ]; then
		if ! grep -qw cpuid "$procfs/modules" 2>/dev/null; then
			modprobe cpuid 2>/dev/null && insmod_cpuid=1
			_debug "tentou carregar o módulo cpuid, insmod_cpuid=$insmod_cpuid"
		else
			_debug "módulo cpuid já carregado"
		fi	
	else
		if ! kldstat -q -m cpuctl; then
			kldload cpuctl 2>/dev/null && kldload_cpuctl=1
			_debug "tentou carregar o módulo cpuctl, kldload_cpuctl=$kldload_cpuctl"
		else
			_debug "módulo cpuctl já carregado"
		fi
	fi
}

# shellcheck disable=SC2034
EAX=1; EBX=2; ECX=3; EDX=4;
READ_CPUID_RET_OK=0
READ_CPUID_RET_KO=1
READ_CPUID_RET_ERR=2
read_cpuid()
{
	if [ "$opt_cpu" != all ]; then
		# we only have one core to read, do it and return the result
		read_cpuid_one_core $opt_cpu "$@"
		return $?
	fi

	# otherwise we must read all cores
	for _core in $(seq 0 "$max_core_id"); do
		read_cpuid_one_core "$_core" "$@"; ret=$?
		if [ "$_core" = 0 ]; then
			# save the result of the first core, for comparison with the others
			_first_core_ret=$ret
			_first_core_value=$read_cpuid_value
		else
			# compare first core with the other ones
			if [ $_first_core_ret != $ret ] || [ "$_first_core_value" != "$read_cpuid_value" ]; then
				read_cpuid_msg="resultado não é homogêneo entre todos os núcleos, pelo menos núcleo 0 e $_core diferem!"
				return $READ_CPUID_RET_ERR
			fi
		fi
	done
	# if we're here, all cores agree, return the result
	return $ret
}

read_cpuid_one_core()
{
	# on which core to send the CPUID instruction
	_core="$1"
	# leaf is the value of the eax register when calling the cpuid instruction:
	_leaf="$2"
	# subleaf is the value of the ecx register when calling the cpuid instruction:
	_subleaf="$3"
	# eax=1 ebx=2 ecx=3 edx=4:
	_register="$4"
	# number of bits to shift the register right to, 0-31:
	_shift="$5"
	# mask to apply as an AND operand to the shifted register value
	_mask="$6"
	# wanted value (optional), if present we return 0(true) if the obtained value is equal, 1 otherwise:
	_wanted="${7:-}"
	# in any case, the read value is globally available in $read_cpuid_value
	read_cpuid_value=''
	read_cpuid_msg='erro desconhecido'

	if [ $# -lt 6 ]; then
		read_cpuid_msg="read_cpuid: argumentos ausentes, obteve apenas $#, esperava pelo menos 6: $*"
		return $READ_CPUID_RET_ERR
	fi
	if [ "$_register" -gt 4 ]; then
		read_cpuid_msg="read_cpuid: register deve ser 0-4, tem $_register"
		return $READ_CPUID_RET_ERR
	fi
	if [ "$_shift" -gt 32 ]; then
		read_cpuid_msg="read_cpuid: turno deve ser 0-31, tem $_shift"
		return $READ_CPUID_RET_ERR
	fi

	if [ ! -e /dev/cpu/0/cpuid ] && [ ! -e /dev/cpuctl0 ]; then
		# try to load the module ourselves (and remember it so we can rmmod it afterwards)
		load_cpuid
	fi

	if [ -e /dev/cpu/0/cpuid ]; then
		# Linux
		if [ ! -r /dev/cpu/0/cpuid ]; then
			read_cpuid_msg="Não foi possível carregar o módulo cpuid"
			return $READ_CPUID_RET_ERR
		fi
		# on some kernel versions, /dev/cpu/0/cpuid doesn't imply that the cpuid module is loaded, in that case dd returns an error,
		# we use that fact to load the module if dd returns an error
		if ! dd if=/dev/cpu/0/cpuid bs=16 count=1 >/dev/null 2>&1; then
			load_cpuid
		fi
		# we need _leaf to be converted to decimal for dd
		_leaf=$(( _leaf ))
		_subleaf=$(( _subleaf ))
		_position=$(( _leaf + (_subleaf << 32) ))
		# to avoid using iflag=skip_bytes, which doesn't exist on old versions of dd, seek to the closer multiple-of-16
		_ddskip=$(( _position / 16 ))
		_odskip=$(( _position - _ddskip * 16 ))
		# now read the value
		_cpuid=$(dd if="/dev/cpu/$_core/cpuid" bs=16 skip=$_ddskip count=$((_odskip + 1)) 2>/dev/null | od -j $((_odskip * 16)) -A n -t u4)
	elif [ -e /dev/cpuctl0 ]; then
		# BSD
		if [ ! -r /dev/cpuctl0 ]; then
			read_cpuid_msg="Não foi possível ler as informações do cpuid do cpuctl"
			return $READ_CPUID_RET_ERR
		fi
		_cpuid=$(cpucontrol -i "$_leaf","$_subleaf" "/dev/cpuctl$_core" 2>/dev/null | cut -d: -f2-)
		# cpuid level 0x4, level_type 0x2: 0x1c004143 0x01c0003f 0x000001ff 0x00000000
	else
		read_cpuid_msg="Não encontrou nenhuma maneira de ler as informações do cpuid"
		return $READ_CPUID_RET_ERR
	fi

	_debug "cpuid: leaf$_leaf subleaf$_subleaf on cpu$_core, eax-ebx-ecx-edx: $_cpuid"
	_mockvarname="SMC_MOCK_CPUID_${_leaf}_${_subleaf}"
	# shellcheck disable=SC1083
	if [ -n "$(eval echo \${$_mockvarname:-})" ]; then
		_cpuid="$(eval echo \$$_mockvarname)"
		_debug "read_cpuid: MOCKING ativado para a folha $_leaf subfolha $_subleaf, retornará $_cpuid"
		mocked=1
	else
		mockme=$(printf "%b\n%b" "$mockme" "SMC_MOCK_CPUID_${_leaf}_${_subleaf}='$_cpuid'")
	fi
	if [ -z "$_cpuid" ]; then
		read_cpuid_msg="Falha ao obter dados cpuid"
		return $READ_CPUID_RET_ERR
	fi

	# get the value of the register we want
	_reg=$(echo "$_cpuid" | awk '{print $'"$_register"'}')
	# Linux returns it as decimal, BSD as hex, normalize to decimal
	_reg=$(( _reg ))
	# shellcheck disable=SC2046
	_debug "cpuid: registro desejado ($_register) tem valor $_reg também conhecido como "$(printf "%08x" "$_reg")
	_reg_shifted=$(( _reg >> _shift ))
	# shellcheck disable=SC2046
	_debug "cpuid: valor deslocado por $_shift é $_reg_shifted também conhecido como "$(printf "%x" "$_reg_shifted")
	read_cpuid_value=$(( _reg_shifted & _mask ))
	# shellcheck disable=SC2046
	_debug "cpuid: depois de AND $_mask, o valor final é $read_cpuid_value, também conhecido como "$(printf "%x" "$read_cpuid_value")
	if [ -n "$_wanted" ]; then
		_debug "cpuid: queria $_queria e recebi $read_cpuid_value"
		if [ "$read_cpuid_value" = "$_wanted" ]; then
			return $READ_CPUID_RET_OK
		else
			return $READ_CPUID_RET_KO
		fi
	fi

	return $READ_CPUID_RET_OK
}

dmesg_grep()
{
	# grep for something in dmesg, ensuring that the dmesg buffer
	# has not been truncated
	dmesg_grepped=''
	if ! dmesg | grep -qE -e '(^|\] )Linux version [0-9]' -e '^FreeBSD is a registered' ; then
		# dmesg truncated
		return 2
	fi
	dmesg_grepped=$(dmesg | grep -E "$1" | head -1)
	# not found:
	[ -z "$dmesg_grepped" ] && return 1
	# found, output is in $dmesg_grepped
	return 0
}

is_coreos()
{
	command -v coreos-install >/dev/null 2>&1 && command -v toolbox >/dev/null 2>&1 && return 0
	return 1
}

# write_msr
# param1 (mandatory): MSR, can be in hex or decimal.
# param2 (optional): value to write, can be in hex or decimal.
# param3 (optional): CPU index, starting from 0. Default 0.
WRITE_MSR_RET_OK=0
WRITE_MSR_RET_KO=1
WRITE_MSR_RET_ERR=2
WRITE_MSR_RET_LOCKDOWN=3
write_msr()
{
	if [ "$opt_cpu" != all ]; then
		# we only have one core to write to, do it and return the result
		write_msr_one_core $opt_cpu "$@"
		return $?
	fi

	# otherwise we must write on all cores
	for _core in $(seq 0 "$max_core_id"); do
		write_msr_one_core "$_core" "$@"; ret=$?
		if [ "$_core" = 0 ]; then
			# save the result of the first core, for comparison with the others
			_first_core_ret=$ret
		else
			# compare first core with the other ones
			if [ $_first_core_ret != $ret ]; then
				write_msr_msg="resultado não é homogêneo entre todos os núcleos, pelo menos o núcleo 0 e $_core diferem!"
				return $WRITE_MSR_RET_ERR
			fi
		fi
	done
	# if we're here, all cores agree, return the result
	return $ret
}

write_msr_one_core()
{
	_core="$1"
	_msr_dec=$(( $2 ))
	_msr=$(printf "0x%x" "$_msr_dec")
	_value_dec=$(( $3 ))
	_value=$(printf "0x%x" "$_value_dec")

	write_msr_msg='erro desconhecido'
	: "${msr_locked_down:=0}"

	_mockvarname="SMC_MOCK_WRMSR_${_msr}_RET"
	# shellcheck disable=SC2086,SC1083
	if [ -n "$(eval echo \${$_mockvarname:-})" ]; then
		_debug "write_msr: MOCKING ativado para retornos de msr $_msr func $(eval echo \$$_mockvarname)"
		mocked=1
		[ "$(eval echo \$$_mockvarname)" = $WRITE_MSR_RET_LOCKDOWN ] && msr_locked_down=1
		return "$(eval echo \$$_mockvarname)"
	fi

	if [ ! -e /dev/cpu/0/msr ] && [ ! -e /dev/cpuctl0 ]; then
		# try to load the module ourselves (and remember it so we can rmmod it afterwards)
		load_msr
	fi
	if [ ! -e /dev/cpu/0/msr ] && [ ! -e /dev/cpuctl0 ]; then
		read_msr_msg="o módulo do kernel msr está disponível?"
		return $WRITE_MSR_RET_ERR
	fi

	_write_denied=0
	if [ "$os" != Linux ]; then
		cpucontrol -m "$_msr=$_value" "/dev/cpuctl$_core" >/dev/null 2>&1; ret=$?
	else
		# for Linux
		# convert to decimal
		if [ ! -w /dev/cpu/"$_core"/msr ]; then
			write_msr_msg="Sem permissão de gravação em /dev/cpu/$_core/msr"
			return $WRITE_MSR_RET_ERR
		# if wrmsr is available, use it
		elif command -v wrmsr >/dev/null 2>&1 && [ "${SMC_NO_WRMSR:-}" != 1 ]; then
			_debug "write_msr: usando wrmsr"
			wrmsr $_msr_dec $_value_dec 2>/dev/null; ret=$?
			# ret=4: msr doesn't exist, ret=127: msr.allow_writes=off
			[ "$ret" = 127 ] && _write_denied=1
		# or fallback to dd if it supports seek_bytes, we prefer it over perl because we can tell the difference between EPERM and EIO
		elif dd if=/dev/null of=/dev/null bs=8 count=1 seek="$_msr_dec" oflag=seek_bytes 2>/dev/null && [ "${SMC_NO_DD:-}" != 1 ]; then
			_debug "write_msr: usando dd"
			awk "BEGIN{printf \"%c\", $_value_dec}" | dd of=/dev/cpu/"$_core"/msr bs=8 count=1 seek="$_msr_dec" oflag=seek_bytes 2>/dev/null; ret=$?
			# if it failed, inspect stderrto look for EPERM
			if [ "$ret" != 0 ]; then
				if awk "BEGIN{printf \"%c\", $_value_dec}" | dd of=/dev/cpu/"$_core"/msr bs=8 count=1 seek="$_msr_dec" oflag=seek_bytes 2>&1 | grep -qF 'Operation not permitted'; then
					_write_denied=1
				fi
			fi
		# or if we have perl, use it, any 5.x version will work
		elif command -v perl >/dev/null 2>&1 && [ "${SMC_NO_PERL:-}" != 1 ]; then
			_debug "write_msr: usando perl"
			ret=1
			perl -e "open(M,'>','/dev/cpu/$_core/msr') and seek(M,$_msr_dec,0) and exit(syswrite(M,pack(v4,$_value_dec)))"; [ $? -eq 8 ] && ret=0
		else
			_debug "write_msr: não tenho wrmsr, perl ou dd recente o suficiente!"
			mockme=$(printf "%b\n%b" "$mockme" "SMC_MOCK_WRMSR_${_msr}_RET=$WRITE_MSR_RET_ERR")
			write_msr_msg="ferramenta ausente, instale msr-tools ou perl"
			return $WRITE_MSR_RET_ERR
		fi
		if [ "$ret" != 0 ]; then
			# * Fedora (and probably Red Hat) have a "kernel lock down" feature that prevents us to write to MSRs
			# when this mode is enabled and EFI secure boot is enabled (see issue #303)
			# https://src.fedoraproject.org/rpms/kernel/blob/master/f/efi-lockdown.patch
			# when this happens, any write will fail and dmesg will have a msg printed "msr: Direct access to MSR"
			# * A version of this patch also made it to vanilla in 5.4+, in that case the message is: 'raw MSR access is restricted'
			# * we don't use dmesg_grep() because we don't care if dmesg is truncated here, as the message has just been printed
			# yet more recent versions of the msr module can be set to msr.allow_writes=off, in which case no dmesg message is printed,
			# but the write fails
			if [ "$_write_denied" = 1 ]; then
				_debug "write_msr: escrita para msr foi negado"
				mockme=$(printf "%b\n%b" "$mockme" "SMC_MOCK_WRMSR_${_msr}_RET=$WRITE_MSR_RET_LOCKDOWN")
				msr_locked_down=1
				write_msr_msg="seu kernel está configurado para negar gravações em MSRs do espaço do usuário"
				return $WRITE_MSR_RET_LOCKDOWN
			elif dmesg | grep -qF "msr: Direct access to MSR"; then
				_debug "write_msr: kernel bloqueado detectado (Red Hat/Fedora)"
				mockme=$(printf "%b\n%b" "$mockme" "SMC_MOCK_WRMSR_${_msr}_RET=$WRITE_MSR_RET_LOCKDOWN")
				msr_locked_down=1
				write_msr_msg="seu kernel está bloqueado (Fedora/Red Hat), reinicie sem inicialização segura e tente novamente"
				return $WRITE_MSR_RET_LOCKDOWN
			elif dmesg | grep -qF "raw MSR access is restricted"; then
				_debug "write_msr: kernel bloqueado detectado (vanilla)"
				mockme=$(printf "%b\n%b" "$mockme" "SMC_MOCK_WRMSR_${_msr}_RET=$WRITE_MSR_RET_LOCKDOWN")
				msr_locked_down=1
				write_msr_msg="seu kernel está bloqueado, reinicie com lockdown=none no cmdline do kernel e tente novamente"
				return $WRITE_MSR_RET_LOCKDOWN
			fi
			unset _write_denied
		fi
	fi

	# normalize ret
	if [ "$ret" = 0 ]; then
		ret=$WRITE_MSR_RET_OK
	else
		ret=$WRITE_MSR_RET_KO
	fi
	_debug "write_msr: para cpu $_core no msr $_msr, value=$_value, ret=$ret"
	mockme=$(printf "%b\n%b" "$mockme" "SMC_MOCK_WRMSR_${_msr}_RET=$ret")
	return $ret
}

# read_msr
# param1 (mandatory): MSR, can be in hex or decimal.
# param2 (optional): CPU index, starting from 0. Default 0.
# returned data is available in $read_msr_value
READ_MSR_RET_OK=0
READ_MSR_RET_KO=1
READ_MSR_RET_ERR=2
read_msr()
{
	if [ "$opt_cpu" != all ]; then
		# we only have one core to read, do it and return the result
		read_msr_one_core $opt_cpu "$@"
		return $?
	fi

	# otherwise we must read all cores
	for _core in $(seq 0 "$max_core_id"); do
		read_msr_one_core "$_core" "$@"; ret=$?
		if [ "$_core" = 0 ]; then
			# save the result of the first core, for comparison with the others
			_first_core_ret=$ret
			_first_core_value=$read_msr_value
		else
			# compare first core with the other ones
			if [ $_first_core_ret != $ret ] || [ "$_first_core_value" != "$read_msr_value" ]; then
				read_msr_msg="resultado não é homogêneo entre todos os núcleos, pelo menos o núcleo 0 e $_core diferem!"
				return $READ_MSR_RET_ERR
			fi
		fi
	done
	# if we're here, all cores agree, return the result
	return $ret
}

read_msr_one_core()
{
	_core="$1"
	_msr_dec=$(( $2 ))
	_msr=$(printf "0x%x" "$_msr_dec")

	read_msr_value=''
	read_msr_msg='erro desconhecido'

	_mockvarname="SMC_MOCK_RDMSR_${_msr}"
	# shellcheck disable=SC2086,SC1083
	if [ -n "$(eval echo \${$_mockvarname:-})" ]; then
		read_msr_value="$(eval echo \$$_mockvarname)"
		_debug "read_msr: MOCKING ativado para msr $_msr, retornando $read_msr_value"
		mocked=1
		return $READ_MSR_RET_OK
	fi

	_mockvarname="SMC_MOCK_RDMSR_${_msr}_RET"
	# shellcheck disable=SC2086,SC1083
	if [ -n "$(eval echo \${$_mockvarname:-})" ] && [ "$(eval echo \$$_mockvarname)" -ne 0 ]; then
		_debug "read_msr: MOCKING ativado para retornos de msr $_msr func $(eval echo \$$_mockvarname)"
		mocked=1
		return "$(eval echo \$$_mockvarname)"
	fi

	if [ ! -e /dev/cpu/0/msr ] && [ ! -e /dev/cpuctl0 ]; then
		# try to load the module ourselves (and remember it so we can rmmod it afterwards)
		load_msr
	fi
	if [ ! -e /dev/cpu/0/msr ] && [ ! -e /dev/cpuctl0 ]; then
		read_msr_msg="o módulo do kernel msr está disponível?"
		return $READ_MSR_RET_ERR
	fi

	if [ "$os" != Linux ]; then
		# for BSD
		_msr=$(cpucontrol -m "$_msr" "/dev/cpuctl$_core" 2>/dev/null); ret=$?
		if [ $ret -ne 0 ]; then
			mockme=$(printf "%b\n%b" "$mockme" "SMC_MOCK_RDMSR_${_msr}_RET=$READ_MSR_RET_KO")
			return $READ_MSR_RET_KO
		fi
		# MSR 0x10: 0x000003e1 0xb106dded
		_msr_h=$(echo "$_msr" | awk '{print $3}');
		_msr_l=$(echo "$_msr" | awk '{print $4}');
		read_msr_value=$(( _msr_h << 32 | _msr_l ))
	else
		# for Linux
		if [ ! -r /dev/cpu/"$_core"/msr ]; then
			mockme=$(printf "%b\n%b" "$mockme" "SMC_MOCK_RDMSR_${_msr}_RET=$READ_MSR_RET_ERR")
			read_msr_msg="Sem permissão de leitura para /dev/cpu/$_core/msr"
			return $READ_MSR_RET_ERR
		# if rdmsr is available, use it
		elif command -v rdmsr >/dev/null 2>&1 && [ "${SMC_NO_RDMSR:-}" != 1 ]; then
			_debug "read_msr: usando rdmsr em $_msr"
			read_msr_value=$(rdmsr -r $_msr_dec 2>/dev/null | od -t u8 -A n)
		# or if we have perl, use it, any 5.x version will work
		elif command -v perl >/dev/null 2>&1 && [ "${SMC_NO_PERL:-}" != 1 ]; then
			_debug "read_msr: usando perl em $_msr"
			read_msr_value=$(perl -e "open(M,'<','/dev/cpu/$_core/msr') and seek(M,$_msr_dec,0) and read(M,\$_,8) and print" | od -t u8 -A n)
		# fallback to dd if it supports skip_bytes
		elif dd if=/dev/null of=/dev/null bs=8 count=1 skip="$_msr_dec" iflag=skip_bytes 2>/dev/null; then
			_debug "read_msr: usando dd em $_msr"
			read_msr_value=$(dd if=/dev/cpu/"$_core"/msr bs=8 count=1 skip="$_msr_dec" iflag=skip_bytes 2>/dev/null | od -t u8 -A n)
		else
			_debug "read_msr: não tenho rdmsr, perl ou dd recente o suficiente!"
			mockme=$(printf "%b\n%b" "$mockme" "SMC_MOCK_RDMSR_${_msr}_RET=$READ_MSR_RET_ERR")
			read_msr_msg='ferramenta ausente, instale msr-tools ou perl'
			return $READ_MSR_RET_ERR
		fi
		if [ -z "$read_msr_value" ]; then
			# MSR doesn't exist, don't check for $? because some versions of dd still return 0!
			mockme=$(printf "%b\n%b" "$mockme" "SMC_MOCK_RDMSR_${_msr}_RET=$READ_MSR_RET_KO")
			return $READ_MSR_RET_KO
		fi
		# remove sparse spaces od might give us
		read_msr_value=$(( read_msr_value ))
	fi
	mockme=$(printf "%b\n%b" "$mockme" "SMC_MOCK_RDMSR_${_msr}='$read_msr_value'")
	_debug "read_msr: MSR=$_msr o valor é $read_msr_value"
	return $READ_MSR_RET_OK
}


parse_cpu_details()
{
	[ "${parse_cpu_details_done:-}" = 1 ] && return 0

	if command -v nproc >/dev/null; then
		number_of_cores=$(nproc)
	elif echo "$os" | grep -q BSD; then
		number_of_cores=$(sysctl -n hw.ncpu 2>/dev/null || echo 1)
	elif [ -e "$procfs/cpuinfo" ]; then
		number_of_cores=$(grep -c ^processor "$procfs/cpuinfo" 2>/dev/null || echo 1)
	else
		# if we don't know, default to 1 CPU
		number_of_cores=1
	fi
	max_core_id=$(( number_of_cores - 1 ))

	has_avx2=0
	has_avx512=0
	if [ -e "$procfs/cpuinfo" ]; then
		if grep -qw avx2 "$procfs/cpuinfo" 2>/dev/null; then has_avx2=1; fi
		if grep -qw avx512 "$procfs/cpuinfo" 2>/dev/null; then has_avx512=1; fi
		cpu_vendor=$(  grep '^vendor_id'  "$procfs/cpuinfo" | awk '{print $3}' | head -1)
		cpu_friendly_name=$(grep '^model name' "$procfs/cpuinfo" | cut -d: -f2- | head -1 | sed -e 's/^ *//')
		# special case for ARM follows
		if grep -qi 'CPU implementer[[:space:]]*:[[:space:]]*0x41' "$procfs/cpuinfo"; then
			cpu_vendor='ARM'
			# some devices (phones or other) have several ARMs and as such different part numbers,
			# an example is "bigLITTLE", so we need to store the whole list, this is needed for is_cpu_affected
			cpu_part_list=$(awk '/CPU part/         {print $4}' "$procfs/cpuinfo")
			cpu_arch_list=$(awk '/CPU architecture/ {print $3}' "$procfs/cpuinfo")
			# take the first one to fill the friendly name, do NOT quote the vars below
			# shellcheck disable=SC2086
			cpu_arch=$(echo $cpu_arch_list | awk '{ print $1 }')
			# shellcheck disable=SC2086
			cpu_part=$(echo $cpu_part_list | awk '{ print $1 }')
			[ "$cpu_arch" = "AArch64" ] && cpu_arch=8
			cpu_friendly_name="ARM"
			[ -n "$cpu_arch" ] && cpu_friendly_name="$cpu_friendly_name v$cpu_arch"
			[ -n "$cpu_part" ] && cpu_friendly_name="$cpu_friendly_name model $cpu_part"

		elif grep -qi 'CPU implementer[[:space:]]*:[[:space:]]*0x43' "$procfs/cpuinfo"; then
			cpu_vendor='CAVIUM'
		elif grep -qi 'CPU implementer[[:space:]]*:[[:space:]]*0x70' "$procfs/cpuinfo"; then
			cpu_vendor='PHYTIUM'
		fi

		cpu_family=$(  grep '^cpu family' "$procfs/cpuinfo" | awk '{print $4}' | grep -E '^[0-9]+$' | head -1)
		cpu_model=$(   grep '^model'      "$procfs/cpuinfo" | awk '{print $3}' | grep -E '^[0-9]+$' | head -1)
		cpu_stepping=$(grep '^stepping'   "$procfs/cpuinfo" | awk '{print $3}' | grep -E '^[0-9]+$' | head -1)
		cpu_ucode=$(   grep '^microcode'  "$procfs/cpuinfo" | awk '{print $3}' | head -1)
	else
		cpu_vendor=$( dmesg | grep -i -m1 'Origin=' | cut -f2 -w | cut -f2 -d= | cut -f2 -d\" )
		cpu_family=$( dmesg | grep -i -m1 'Family=' | cut -f4 -w | cut -f2 -d= )
		cpu_family=$(( cpu_family ))
		cpu_model=$( dmesg | grep -i -m1 'Model=' | cut -f5 -w | cut -f2 -d= )
		cpu_model=$(( cpu_model ))
		cpu_stepping=$( dmesg | grep -i -m1 'Stepping=' | cut -f6 -w | cut -f2 -d= )
		cpu_friendly_name=$(sysctl -n hw.model 2>/dev/null)
	fi

	# Intel processors have a 3bit Platform ID field in MSR(17H) that specifies the platform type for up to 8 types
	# see https://elixir.bootlin.com/linux/v6.0/source/arch/x86/kernel/cpu/microcode/intel.c#L694
	# Set it to 8 (impossible value as it is 3 bit long) by default
	cpu_platformid=8
	if [ "$cpu_vendor" = GenuineIntel ] && [ "$cpu_model" -ge 5 ]; then
		read_msr 0x17; ret=$?
		if [ $ret = $READ_MSR_RET_OK ]; then
			cpu_platformid=$(( 1 << ( (read_msr_value >> 18) & 7) ))
		fi
	fi

	if [ -n "${SMC_MOCK_CPU_FRIENDLY_NAME:-}" ]; then
		cpu_friendly_name="$SMC_MOCK_CPU_FRIENDLY_NAME"
		_debug "parse_cpu_details: MOCKING nome amigável da cpu para $ cpu_friendly_name"
		mocked=1
	else
		mockme=$(printf "%b\n%b" "$mockme" "SMC_MOCK_CPU_FRIENDLY_NAME='$cpu_friendly_name'")
	fi
	if [ -n "${SMC_MOCK_CPU_VENDOR:-}" ]; then
		cpu_vendor="$SMC_MOCK_CPU_VENDOR"
		_debug "parse_cpu_details: MOCKING fornecedor de cpu para $cpu_vendor"
		mocked=1
	else
		mockme=$(printf "%b\n%b" "$mockme" "SMC_MOCK_CPU_VENDOR='$cpu_vendor'")
	fi
	if [ -n "${SMC_MOCK_CPU_FAMILY:-}" ]; then
		cpu_family="$SMC_MOCK_CPU_FAMILY"
		_debug "parse_cpu_details: MOCKING família de cpu para $cpu_family"
		mocked=1
	else
		mockme=$(printf "%b\n%b" "$mockme" "SMC_MOCK_CPU_FAMILY='$cpu_family'")
	fi
	if [ -n "${SMC_MOCK_CPU_MODEL:-}" ]; then
		cpu_model="$SMC_MOCK_CPU_MODEL"
		_debug "parse_cpu_details: MOCKING modelo de CPU para $cpu_model"
		mocked=1
	else
		mockme=$(printf "%b\n%b" "$mockme" "SMC_MOCK_CPU_MODEL='$cpu_model'")
	fi
	if [ -n "${SMC_MOCK_CPU_STEPPING:-}" ]; then
		cpu_stepping="$SMC_MOCK_CPU_STEPPING"
		_debug "parse_cpu_details: MOCKING cpu passo a passo para $cpu_stepping"
		mocked=1
	else
		mockme=$(printf "%b\n%b" "$mockme" "SMC_MOCK_CPU_STEPPING='$cpu_stepping'")
	fi
	if [ -n "${SMC_MOCK_CPU_PLATFORMID:-}" ]; then
		cpu_platformid="$SMC_MOCK_CPU_PLATFORMID"
		_debug "parse_cpu_details: MOCKING cpu platformid name to $cpu_platformid"
		mocked=1
	else
		mockme=$(printf "%b\n%b" "$mockme" "SMC_MOCK_CPU_PLATFORMID='$cpu_platformid'")
	fi

	# get raw cpuid, it's always useful (referenced in the Intel doc for firmware updates for example)
	if [ "$mocked" != 1 ] && read_cpuid 0x1 0x0 $EAX 0 0xFFFFFFFF; then
		cpu_cpuid="$read_cpuid_value"
	else
		# try to build it by ourselves
		_debug "parse_cpu_details: construa o CPUID por conta própria"
		cpu_cpuid=$(fms2cpuid "$cpu_family" "$cpu_model" "$cpu_stepping")
	fi

	# under BSD, linprocfs often doesn't export ucode information, so fetch it ourselves the good old way
	if [ -z "$cpu_ucode" ] && [ "$os" != Linux ]; then
		load_cpuid
		if [ -e /dev/cpuctl0 ]; then
			# init MSR with NULLs
			cpucontrol -m 0x8b=0 /dev/cpuctl0
			# call CPUID
			cpucontrol -i 1 /dev/cpuctl0 >/dev/null
			# read MSR
			cpu_ucode=$(cpucontrol -m 0x8b /dev/cpuctl0 | awk '{print $3}')
			# convert to decimal
			cpu_ucode=$(( cpu_ucode ))
			# convert back to hex
			cpu_ucode=$(printf "0x%x" "$cpu_ucode")
		fi
	fi

	# if we got no cpu_ucode (e.g. we're in a vm), fall back to 0x0
	: "${cpu_ucode:=0x0}"

	if [ -n "${SMC_MOCK_CPU_UCODE:-}" ]; then
		cpu_ucode="$SMC_MOCK_CPU_UCODE"
		_debug "parse_cpu_details: MOCKING cpu ucode para $cpu_ucode"
		mocked=1
	else
		mockme=$(printf "%b\n%b" "$mockme" "SMC_MOCK_CPU_UCODE='$cpu_ucode'")
	fi

	echo "$cpu_ucode" | grep -q ^0x && cpu_ucode=$(( cpu_ucode ))
	ucode_found=$(printf "familia 0x%x modelo 0x%x stepping 0x%x ucode 0x%x cpuid 0x%x pfid 0x%x" \
		"$cpu_family" "$cpu_model" "$cpu_stepping" "$cpu_ucode" "$cpu_cpuid" "$cpu_platformid")

	# also define those that we will need in other funcs
	# taken from https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/x86/include/asm/intel-family.h
	# curl -s 'https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/plain/arch/x86/include/asm/intel-family.h' | awk '/#define INTEL_FAM6/ {print $2"=$(( "$3" )) # "$4,$5,$6,$7,$8,$9}' | sed -re 's/ +$//'
	# shellcheck disable=SC2034
	{
	INTEL_FAM6_CORE_YONAH=$(( 0x0E )) #
	INTEL_FAM6_CORE2_MEROM=$(( 0x0F )) #
	INTEL_FAM6_CORE2_MEROM_L=$(( 0x16 )) #
	INTEL_FAM6_CORE2_PENRYN=$(( 0x17 )) #
	INTEL_FAM6_CORE2_DUNNINGTON=$(( 0x1D )) #
	INTEL_FAM6_NEHALEM=$(( 0x1E )) #
	INTEL_FAM6_NEHALEM_G=$(( 0x1F )) # /* Auburndale / Havendale */
	INTEL_FAM6_NEHALEM_EP=$(( 0x1A )) #
	INTEL_FAM6_NEHALEM_EX=$(( 0x2E )) #
	INTEL_FAM6_WESTMERE=$(( 0x25 )) #
	INTEL_FAM6_WESTMERE_EP=$(( 0x2C )) #
	INTEL_FAM6_WESTMERE_EX=$(( 0x2F )) #
	INTEL_FAM6_SANDYBRIDGE=$(( 0x2A )) #
	INTEL_FAM6_SANDYBRIDGE_X=$(( 0x2D )) #
	INTEL_FAM6_IVYBRIDGE=$(( 0x3A )) #
	INTEL_FAM6_IVYBRIDGE_X=$(( 0x3E )) #
	INTEL_FAM6_HASWELL=$(( 0x3C )) #
	INTEL_FAM6_HASWELL_X=$(( 0x3F )) #
	INTEL_FAM6_HASWELL_L=$(( 0x45 )) #
	INTEL_FAM6_HASWELL_G=$(( 0x46 )) #
	INTEL_FAM6_BROADWELL=$(( 0x3D )) #
	INTEL_FAM6_BROADWELL_G=$(( 0x47 )) #
	INTEL_FAM6_BROADWELL_X=$(( 0x4F )) #
	INTEL_FAM6_BROADWELL_D=$(( 0x56 )) #
	INTEL_FAM6_SKYLAKE_L=$(( 0x4E )) # /* Sky Lake */
	INTEL_FAM6_SKYLAKE=$(( 0x5E )) # /* Sky Lake */
	INTEL_FAM6_SKYLAKE_X=$(( 0x55 )) # /* Sky Lake */
	INTEL_FAM6_KABYLAKE_L=$(( 0x8E )) # /* Sky Lake */
	INTEL_FAM6_KABYLAKE=$(( 0x9E )) # /* Sky Lake */
	INTEL_FAM6_COMETLAKE=$(( 0xA5 )) # /* Sky Lake */
	INTEL_FAM6_COMETLAKE_L=$(( 0xA6 )) # /* Sky Lake */
	INTEL_FAM6_CANNONLAKE_L=$(( 0x66 )) # /* Palm Cove */
	INTEL_FAM6_ICELAKE_X=$(( 0x6A )) # /* Sunny Cove */
	INTEL_FAM6_ICELAKE_D=$(( 0x6C )) # /* Sunny Cove */
	INTEL_FAM6_ICELAKE=$(( 0x7D )) # /* Sunny Cove */
	INTEL_FAM6_ICELAKE_L=$(( 0x7E )) # /* Sunny Cove */
	INTEL_FAM6_ICELAKE_NNPI=$(( 0x9D )) # /* Sunny Cove */
	INTEL_FAM6_LAKEFIELD=$(( 0x8A )) # /* Sunny Cove / Tremont */
	INTEL_FAM6_ROCKETLAKE=$(( 0xA7 )) # /* Cypress Cove */
	INTEL_FAM6_TIGERLAKE_L=$(( 0x8C )) # /* Willow Cove */
	INTEL_FAM6_TIGERLAKE=$(( 0x8D )) # /* Willow Cove */
	INTEL_FAM6_SAPPHIRERAPIDS_X=$(( 0x8F )) # /* Golden Cove */
	INTEL_FAM6_ALDERLAKE=$(( 0x97 )) # /* Golden Cove / Gracemont */
	INTEL_FAM6_ALDERLAKE_L=$(( 0x9A )) # /* Golden Cove / Gracemont */
	INTEL_FAM6_RAPTORLAKE=$(( 0xB7 )) #
	INTEL_FAM6_ATOM_BONNELL=$(( 0x1C )) # /* Diamondville, Pineview */
	INTEL_FAM6_ATOM_BONNELL_MID=$(( 0x26 )) # /* Silverthorne, Lincroft */
	INTEL_FAM6_ATOM_SALTWELL=$(( 0x36 )) # /* Cedarview */
	INTEL_FAM6_ATOM_SALTWELL_MID=$(( 0x27 )) # /* Penwell */
	INTEL_FAM6_ATOM_SALTWELL_TABLET=$(( 0x35 )) # /* Cloverview */
	INTEL_FAM6_ATOM_SILVERMONT=$(( 0x37 )) # /* Bay Trail, Valleyview */
	INTEL_FAM6_ATOM_SILVERMONT_D=$(( 0x4D )) # /* Avaton, Rangely */
	INTEL_FAM6_ATOM_SILVERMONT_MID=$(( 0x4A )) # /* Merriefield */
	INTEL_FAM6_ATOM_AIRMONT=$(( 0x4C )) # /* Cherry Trail, Braswell */
	INTEL_FAM6_ATOM_AIRMONT_MID=$(( 0x5A )) # /* Moorefield */
	INTEL_FAM6_ATOM_AIRMONT_NP=$(( 0x75 )) # /* Lightning Mountain */
	INTEL_FAM6_ATOM_GOLDMONT=$(( 0x5C )) # /* Apollo Lake */
	INTEL_FAM6_ATOM_GOLDMONT_D=$(( 0x5F )) # /* Denverton */
	INTEL_FAM6_ATOM_GOLDMONT_PLUS=$(( 0x7A )) # /* Gemini Lake */
	INTEL_FAM6_ATOM_TREMONT_D=$(( 0x86 )) # /* Jacobsville */
	INTEL_FAM6_ATOM_TREMONT=$(( 0x96 )) # /* Elkhart Lake */
	INTEL_FAM6_ATOM_TREMONT_L=$(( 0x9C )) # /* Jasper Lake */
	INTEL_FAM6_XEON_PHI_KNL=$(( 0x57 )) # /* Knights Landing */
	INTEL_FAM6_XEON_PHI_KNM=$(( 0x85 )) # /* Knights Mill */
	}
	parse_cpu_details_done=1
}
is_hygon()
{
	parse_cpu_details
	[ "$cpu_vendor" = HygonGenuine ] && return 0
	return 1
}

is_amd()
{
	parse_cpu_details
	[ "$cpu_vendor" = AuthenticAMD ] && return 0
	return 1
}

is_intel()
{
	parse_cpu_details
	[ "$cpu_vendor" = GenuineIntel ] && return 0
	return 1
}

is_cpu_smt_enabled()
{
	# SMT / HyperThreading is enabled if siblings != cpucores
	if [ -e "$procfs/cpuinfo" ]; then
		_siblings=$(awk '/^siblings/  {print $3;exit}' "$procfs/cpuinfo")
		_cpucores=$(awk '/^cpu cores/ {print $4;exit}' "$procfs/cpuinfo")
		if [ -n "$_siblings" ] && [ -n "$_cpucores" ]; then
			if [ "$_siblings" = "$_cpucores" ]; then
				return 1
			else
				return 0
			fi
		fi
	fi
	# we can't tell
	return 2
}

is_ucode_blacklisted()
{
	parse_cpu_details
	# if it's not an Intel, don't bother: it's not blacklisted
	is_intel || return 1
	# it also needs to be family=6
	[ "$cpu_family" = 6 ] || return 1
	# now, check each known bad microcode
	# source: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/x86/kernel/cpu/intel.c#n105
	# 2018-02-08 update: https://newsroom.intel.com/wp-content/uploads/sites/11/2018/02/microcode-update-guidance.pdf
	# model,stepping,microcode
	for tuple in \
		$INTEL_FAM6_KABYLAKE,0x0B,0x80 \
		$INTEL_FAM6_KABYLAKE,0x0A,0x80 \
		$INTEL_FAM6_KABYLAKE,0x09,0x80 \
		$INTEL_FAM6_KABYLAKE_L,0x0A,0x80  \
		$INTEL_FAM6_KABYLAKE_L,0x09,0x80  \
		$INTEL_FAM6_SKYLAKE_X,0x03,0x0100013e  \
		$INTEL_FAM6_SKYLAKE_X,0x04,0x02000036  \
		$INTEL_FAM6_SKYLAKE_X,0x04,0x0200003a  \
		$INTEL_FAM6_SKYLAKE_X,0x04,0x0200003c  \
		$INTEL_FAM6_BROADWELL,0x04,0x28   \
		$INTEL_FAM6_BROADWELL_G,0x01,0x1b   \
		$INTEL_FAM6_BROADWELL_D,0x02,0x14 \
		$INTEL_FAM6_BROADWELL_D,0x03,0x07000011 \
		$INTEL_FAM6_BROADWELL_X,0x01,0x0b000025 \
		$INTEL_FAM6_HASWELL_L,0x01,0x21        \
		$INTEL_FAM6_HASWELL_G,0x01,0x18     \
		$INTEL_FAM6_HASWELL,0x03,0x23     \
		$INTEL_FAM6_HASWELL_X,0x02,0x3b        \
		$INTEL_FAM6_HASWELL_X,0x04,0x10        \
		$INTEL_FAM6_IVYBRIDGE_X,0x04,0x42a     \
		$INTEL_FAM6_SANDYBRIDGE_X,0x06,0x61b   \
		$INTEL_FAM6_SANDYBRIDGE_X,0x07,0x712
	do
		model=$(echo "$tuple" | cut -d, -f1)
		stepping=$(( $(echo "$tuple" | cut -d, -f2) ))
		if [ "$cpu_model" = "$model" ] && [ "$cpu_stepping" = "$stepping" ]; then
			ucode=$(( $(echo "$tuple" | cut -d, -f3) ))
			if [ "$cpu_ucode" = "$ucode" ]; then
				_debug "is_ucode_blacklisted: temos uma partida! ($cpu_model/$cpu_stepping/$cpu_ucode)"
				return 0
			fi
		fi
	done

	# 2024-01-09 update: https://github.com/speed47/spectre-meltdown-checker/issues/475
	# this time the tuple is cpuid,microcode
	for tuple in \
		0xB0671,0x119  \
		0xB06A2,0x4119 \
		0xB06A3,0x4119
	do
		cpuid=$(( $(echo "$tuple" | cut -d, -f1) ))
		ucode=$(( $(echo "$tuple" | cut -d, -f2) ))
		if [ "$cpu_cpuid" = "$cpuid" ] && [ "$cpu_ucode" = "$ucode" ]; then
			_debug "is_ucode_blacklisted: temos uma partida! ($cpuid/$ucode)"
			return 0
		fi
	done

	_debug "is_ucode_blacklisted: não ($cpu_model/$cpu_stepping/$cpu_ucode)"
	return 1
}

is_skylake_cpu()
{
	# is this a skylake cpu?
	# return 0 if yes, 1 otherwise
	#if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL &&
	#		boot_cpu_data.x86 == 6) {
	#		switch (boot_cpu_data.x86_model) {
	#		case INTEL_FAM6_SKYLAKE_MOBILE:
	#		case INTEL_FAM6_SKYLAKE_DESKTOP:
	#		case INTEL_FAM6_SKYLAKE_X:
	#		case INTEL_FAM6_KABYLAKE_MOBILE:
	#		case INTEL_FAM6_KABYLAKE_DESKTOP:
	#			return true;
	parse_cpu_details
	is_intel || return 1
	[ "$cpu_family" = 6 ] || return 1
	if [ "$cpu_model" = $INTEL_FAM6_SKYLAKE_L       ] || \
		[ "$cpu_model" = $INTEL_FAM6_SKYLAKE    ] || \
		[ "$cpu_model" = $INTEL_FAM6_SKYLAKE_X  ] || \
		[ "$cpu_model" = $INTEL_FAM6_KABYLAKE_L ] || \
		[ "$cpu_model" = $INTEL_FAM6_KABYLAKE   ]; then
		return 0
	fi
	return 1
}

is_vulnerable_to_empty_rsb()
{
	if is_intel && [ -z "$capabilities_rsba" ]; then
		_warn "is_vulnerable_to_empty_rsb() chamado antes de ARCH CAPABILITIES MSR ser lido"
	fi
	if is_skylake_cpu || [ "$capabilities_rsba" = 1 ]; then
		return 0
	fi
	return 1
}

is_zen_cpu()
{
	# is this CPU from the AMD ZEN family ? (ryzen, epyc, ...)
	parse_cpu_details
	is_amd || return 1
	[ "$cpu_family" = 23 ] && return 0
	return 1
}

is_moksha_cpu()
{
	parse_cpu_details
	is_hygon || return 1
	[ "$cpu_family" = 24 ] && return 0
	return 1
}

# mimick the Linux macro
##define AMD_MODEL_RANGE(f, m_start, s_start, m_end, s_end) \
#	((f << 24) | (m_start << 16) | (s_start << 12) | (m_end << 4) | (s_end))
amd_model_range()
{
	echo $(( ($1 << 24) | ($2 << 16) | ($3 << 12) | ($4 << 4) | ($5) ))
}

# mimick the Linux func, usage:
# amd_legacy_erratum $(amd_model_range 0x17 0x30 0x0 0x4f 0xf)
# return true (0) if the current CPU is affected by this erratum, 1 otherwise
amd_legacy_erratum()
{
	_range="$1"
	_ms=$((cpu_model << 4 | cpu_stepping))
	if [ "$cpu_family" = $(( ( (_range) >> 24) & 0xff )) ] && \
		[ $_ms -ge $(( ( (_range) >> 12) & 0xfff )) ] && \
		[ $_ms -le $(( (_range) & 0xfff )) ]; then
		return 0
	fi
	return 1
}

# returns 0 (true) if yes, 1 otherwise
# returns 2 if not applicable
has_zenbleed_fixed_firmware()
{
	# return cached data
	[ -n "$zenbleed_fw" ] && return "$zenbleed_fw"
	# or compute it:
	zenbleed_fw=2 # unknown
	# only amd
	if ! is_amd; then
		zenbleed_fw=1
		return $zenbleed_fw
	fi
	# list of known fixed firmwares, from commit 522b1d69219d8f083173819fde04f994aa051a98
	_tuples="
		0x30,0x3f,0x0830107a
		0x60,0x67,0x0860010b
		0x68,0x6f,0x08608105
		0x70,0x7f,0x08701032
		0xa0,0xaf,0x08a00008
	"
	for tuple in $_tuples; do
		_model_low=$( echo "$tuple" | cut -d, -f1)
		_model_high=$(echo "$tuple" | cut -d, -f2)
		_fwver=$(     echo "$tuple" | cut -d, -f3)
		if [ $((cpu_model)) -ge $((_model_low)) ] && [ $((cpu_model)) -le $((_model_high)) ]; then
			if [ $((cpu_ucode)) -ge $((_fwver)) ]; then
				zenbleed_fw=0 # true
				break
			else
				zenbleed_fw=1 # false
				zenbleed_fw_required=$_fwver
			fi
		fi
	done
	unset _tuples
	return $zenbleed_fw
}

# Test if the current host is a Xen PV Dom0 / DomU
is_xen() {
	if [ ! -d "$procfs/xen" ]; then
		return 1
	fi

	# XXX do we have a better way that relying on dmesg?
	dmesg_grep 'Inicializando o kernel paravirtualizado no Xen$'; ret=$?
	if [ $ret -eq 2 ]; then
		_warn "dmesg truncado, a detecção do Xen não será confiável. Reinicie e reinicie este script"
		return 1
	elif [ $ret -eq 0 ]; then
		return 0
	else
		return 1
	fi
}

is_xen_dom0()
{
	if ! is_xen; then
		return 1
	fi

	if [ -e "$procfs/xen/capabilities" ] && grep -q "control_d" "$procfs/xen/capabilities"; then
		return 0
	else
		return 1
	fi
}

is_xen_domU()
{
	if ! is_xen; then
		return 1
	fi

	# PVHVM guests also print 'Booting paravirtualized kernel', so we need this check.
	dmesg_grep 'O vetor de retorno de chamada Xen HVM para entrega de eventos está ativado$'; ret=$?
	if [ $ret -eq 0 ]; then
		return 1
	fi

	if ! is_xen_dom0; then
		return 0
	else
		return 1
	fi
}

builtin_dbversion=$(awk '/^# %%% MCEDB / { print $4 }' "$0")
if [ -r "$mcedb_cache" ]; then
	# we have a local cache file, but it might be older than the builtin version we have
	local_dbversion=$(  awk '/^# %%% MCEDB / { print $4 }' "$mcedb_cache")
	# sort -V sorts by version number
	older_dbversion=$(printf "%b\n%b" "$local_dbversion" "$builtin_dbversion" | sort -V | head -n1)
	if [ "$older_dbversion" = "$builtin_dbversion" ]; then
		mcedb_source="$mcedb_cache"
		mcedb_info="BD de firmwares locais $local_dbversion"
	fi
fi
# if mcedb_source is not set, either we don't have a local cached db, or it is older than the builtin db
if [ -z "${mcedb_source:-}" ]; then
	mcedb_source="$0"
	mcedb_info="firmwares embutidos DB $builtin_dbversion"
fi
read_mcedb()
{
	awk '{ if (DELIM==1) { print $2 } } /^# %%% MCEDB / { DELIM=1 }' "$mcedb_source"
}

read_inteldb()
{
	if [ "$opt_intel_db" = 1 ]; then
		awk '/^# %%% ENDOFINTELDB/ { exit } { if (DELIM==1) { print $2 } } /^# %%% INTELDB/ { DELIM=1 }' "$0"
	fi
	# otherwise don't output nothing, it'll be as if the database is empty
}

is_latest_known_ucode()
{
	# 0: yes, 1: no, 2: unknown
	parse_cpu_details
	if [ "$cpu_cpuid" = 0 ]; then
		ucode_latest="não consegui seu cpuid"
		return 2
	fi
	ucode_latest="A versão mais recente do microcódigo para o seu modelo de CPU é desconhecida"
	if is_intel; then
		cpu_brand_prefix=I
	elif is_amd; then
		cpu_brand_prefix=A
	else
		return 2
	fi
	for tuple in $(read_mcedb | grep "$(printf "^$cpu_brand_prefix,0x%08X," "$cpu_cpuid")")
	do
		# skip if the pfmask doesn't match our platformid
		pfmask=$(echo "$tuple" | cut -d, -f3)
		if is_intel && [ $((cpu_platformid & pfmask)) -eq 0 ]; then
			continue
		fi
		ucode=$((  $(echo "$tuple" | cut -d, -f4) ))
		ucode_date=$(echo "$tuple" | cut -d, -f5 | sed -r 's=(....)(..)(..)=\1/\2/\3=')
		_debug "is_latest_known_ucode: com cpuid $cpu_cpuid possui ucode $cpu_ucode, o último conhecido é $ucode de $ucode_date"
		ucode_latest=$(printf "versão mais recente é 0x%x data $ucode_date de acordo com $mcedb_info" "$ucode")
		if [ "$cpu_ucode" -ge "$ucode" ]; then
			return 0
		else
			return 1
		fi
	done
	_debug "is_latest_known_ucode: este cpuid não é referenciado ($cpu_cpuid)"
	return 2
}

get_cmdline()
{
	if [ -n "${kernel_cmdline:-}" ]; then
		return
	fi

	if [ -n "${SMC_MOCK_CMDLINE:-}" ]; then
		mocked=1
		_debug "get_cmdline: usando cmdline zombado '$SMC_MOCK_CMDLINE'"
		kernel_cmdline="$SMC_MOCK_CMDLINE"
		return
	else
		kernel_cmdline=$(cat "$procfs/cmdline")
		mockme=$(printf "%b\n%b" "$mockme" "SMC_MOCK_CMDLINE='$kernel_cmdline'")
	fi
}

# ENTRYPOINT

# we can't do anything useful under WSL
if uname -a | grep -qE -- '-Microsoft #[0-9]+-Microsoft '; then
	_warn "Este script não funciona no Windows Subsystem for Linux"
	_warn "Você deve usar a ferramenta oficial da Microsoft."
	_warn "Pode ser encontrado em https://aka.ms/SpeculationControlPS"
	exit 1
fi

# or other UNIX-ish OSes non-Linux non-supported-BSDs
if [ "$os" = Darwin ] || [ "$os" = VMkernel ]; then
	_warn "Você está executando no SO $os, mas este script"
	_warn "só funciona no Linux e alguns sistemas BSD, desculpe."
	_warn "Por favor, leia o README e FAQ para mais informações."
	exit 1
fi

# check for mode selection inconsistency
if [ "$opt_hw_only" = 1 ]; then
	if [ "$opt_cve_all" = 0 ]; then
		show_usage
		echo "$0: erro: modos incompatíveis especificados, --hw-only vs --variant" >&2
		exit 255
	else
		opt_cve_all=0
		opt_cve_list=''
	fi
fi

# coreos mode
if [ "$opt_coreos" = 1 ]; then
	if ! is_coreos; then
		_warn "Perguntou o modo CoreOS, mas não estamos sob o CoreOS!"
		exit 255
	fi
	_warn "Modo CoreOS, iniciando uma caixa de ferramentas efêmera para iniciar o script"
	load_msr
	load_cpuid
	mount_debugfs
	toolbox --ephemeral --bind-ro /dev/cpu:/dev/cpu -- sh -c "dnf install -y binutils which && /media/root$PWD/$0 $* --coreos-within-toolbox"
	exitcode=$?
	exit $exitcode
else
	if is_coreos; then
		_warn "Você parece estar executando o CoreOS, talvez queira usar a opção --coreos para obter melhores resultados"
		_warn
	fi
fi

# if we're under a BSD, try to mount linprocfs for "$procfs/cpuinfo"
procfs=/proc
if echo "$os" | grep -q BSD; then
	_debug "Estamos sob BSD, verifique se temos procfs"
	procfs=$(mount | awk '/^linprocfs/ { print $3; exit; }')
	if [ -z "$procfs" ]; then
		_debug "nós não, tente montar"
		procfs=/proc
		[ -d /compat/linux/proc ] && procfs=/compat/linux/proc
		test -d $procfs || mkdir $procfs
		if mount -t linprocfs linprocfs $procfs 2>/dev/null; then
			mounted_procfs=1
			_debug "procfs apenas montado em $procfs"
		else
			procfs=''
		fi
	else
		_debug "Nós fazemos: $procfs"
	fi
fi

# define a few vars we might reference later without these being inited
mockme=''
mocked=0
specex_knob_dir=/dev/no_valid_path

# if /tmp doesn't exist and TMPDIR is not set, try to set it to a sane default for Android
if [ -z "${TMPDIR:-}" ] && ! [ -d "/tmp" ] && [ -d "/data/local/tmp" ]; then
	TMPDIR=/data/local/tmp
	export TMPDIR
fi

parse_cpu_details
get_cmdline

if [ "$opt_cpu" != all ] && [ "$opt_cpu" -gt "$max_core_id" ]; then
	echo "$0: erro: --cpu não pode ser maior que $max_core_id, tem $opt_cpu" >&2
	exit 255
fi

if [ "$opt_live" = 1 ]; then
	_info "Verificando vulnerabilidades no sistema atual"
	_info "Kernel é \033[35m$os $(uname -r) $(uname -v) $(uname -m)\033[0m"
	_info "CPU é \033[35m$cpu_friendly_name\033[0m"

	# try to find the image of the current running kernel
	if [ -n "$opt_kernel" ]; then
		# specified by user on cmdline, with --live, don't override
		:
	# first, look for the BOOT_IMAGE hint in the kernel cmdline
	elif echo "$kernel_cmdline" | grep -q 'BOOT_IMAGE='; then
		opt_kernel=$(echo "$kernel_cmdline" | grep -Eo 'BOOT_IMAGE=[^ ]+' | cut -d= -f2)
		_debug "encontrado opt_kernel=$opt_kernel em $procfs/cmdline"
		# if the boot partition is within a btrfs subvolume, strip the subvolume name
		# if /boot is a separate subvolume, the remainder of the code in this section should handle it
		if echo "$opt_kernel" | grep -q "^/@"; then opt_kernel=$(echo "$opt_kernel" | sed "s:/@[^/]*::"); fi
		# if we have a dedicated /boot partition, our bootloader might have just called it /
		# so try to prepend /boot and see if we find anything
		[ -e "/boot/$opt_kernel" ] && opt_kernel="/boot/$opt_kernel"
		# special case for CoreOS if we're inside the toolbox
		[ -e "/media/root/boot/$opt_kernel" ] && opt_kernel="/media/root/boot/$opt_kernel"
		_debug "opt_kernel é agora $opt_kernel"
		# else, the full path is already there (most probably /boot/something)
	fi
	# if we didn't find a kernel, default to guessing
	if [ ! -e "$opt_kernel" ]; then
		# Fedora:
		[ -e "/lib/modules/$(uname -r)/vmlinuz" ] && opt_kernel="/lib/modules/$(uname -r)/vmlinuz"
		# Slackware:
		[ -e "/boot/vmlinuz"             ] && opt_kernel="/boot/vmlinuz"
		# Arch aarch64:
		[ -e "/boot/Image"               ] && opt_kernel="/boot/Image"
		# Arch armv5/armv7:
		[ -e "/boot/zImage"              ] && opt_kernel="/boot/zImage"
		# Arch arm7:
		[ -e "/boot/kernel7.img"         ] && opt_kernel="/boot/kernel7.img"
		# Linux-Libre:
		[ -e "/boot/vmlinuz-linux-libre" ] && opt_kernel="/boot/vmlinuz-linux-libre"
		# pine64
		[ -e "/boot/pine64/Image"        ] && opt_kernel="/boot/pine64/Image"
		# generic:
		[ -e "/boot/vmlinuz-$(uname -r)" ] && opt_kernel="/boot/vmlinuz-$(uname -r)"
		[ -e "/boot/kernel-$( uname -r)" ] && opt_kernel="/boot/kernel-$( uname -r)"
		[ -e "/boot/bzImage-$(uname -r)" ] && opt_kernel="/boot/bzImage-$(uname -r)"
		# Gentoo:
		[ -e "/boot/kernel-genkernel-$(uname -m)-$(uname -r)" ] && opt_kernel="/boot/kernel-genkernel-$(uname -m)-$(uname -r)"
		# NixOS:
		[ -e "/run/booted-system/kernel" ] && opt_kernel="/run/booted-system/kernel"
		# Guix System:
		[ -e "/run/booted-system/kernel/bzImage" ] && opt_kernel="/run/booted-system/kernel/bzImage"
		# systemd kernel-install:
		[ -e "/etc/machine-id" ] && [ -e "/boot/$(cat /etc/machine-id)/$(uname -r)/linux" ] && opt_kernel="/boot/$(cat /etc/machine-id)/$(uname -r)/linux"
		# Clear Linux:
		str_uname=$(uname -r)
		clear_linux_kernel="/lib/kernel/org.clearlinux.${str_uname##*.}.${str_uname%.*}"
		[ -e "$clear_linux_kernel" ] && opt_kernel=$clear_linux_kernel
		# Custom Arch seems to have the kernel path in its cmdline in the form "\directory\kernelimage",
		# with actual \'s instead of /'s:
		custom_arch_kernel=$(echo "$kernel_cmdline" | grep -Eo "(^|\s)\\\\[\\\\a-zA-Z0-9_.-]+" | tr "\\\\" "/" | tr -d '[:space:]')
		if [ -n "$custom_arch_kernel" ] && [ -e "$custom_arch_kernel" ]; then
			opt_kernel="$custom_arch_kernel"
		fi
		# FreeBSD:
		[ -e "/boot/kernel/kernel" ] && opt_kernel="/boot/kernel/kernel"
	fi

	# system.map
	if [ -n "$opt_map" ]; then
		# specified by user on cmdline, with --live, don't override
		:
	elif [ -e "$procfs/kallsyms" ] ; then
		opt_map="$procfs/kallsyms"
	elif [ -e "/lib/modules/$(uname -r)/System.map" ] ; then
		opt_map="/lib/modules/$(uname -r)/System.map"
	elif [ -e "/boot/System.map-$(uname -r)" ] ; then
		opt_map="/boot/System.map-$(uname -r)"
	elif [ -e "/lib/kernel/System.map-$(uname -r)" ]; then
		opt_map="/lib/kernel/System.map-$(uname -r)"
	fi

	# config
	if [ -n "$opt_config" ]; then
		# specified by user on cmdline, with --live, don't override
		:
	elif [ -e "$procfs/config.gz" ] ; then
		dumped_config="$(mktemp -t smc-config-XXXXXX)"
		gunzip -c "$procfs/config.gz" > "$dumped_config"
		# dumped_config will be deleted at the end of the script
		opt_config="$dumped_config"
	elif [ -e "/lib/modules/$(uname -r)/config" ]; then
		opt_config="/lib/modules/$(uname -r)/config"
	elif [ -e "/boot/config-$(uname -r)" ]; then
		opt_config="/boot/config-$(uname -r)"
	elif [ -e "/etc/kernels/kernel-config-$(uname -m)-$(uname -r)" ]; then
		opt_config="/etc/kernels/kernel-config-$(uname -m)-$(uname -r)"
	elif [ -e "/lib/kernel/config-$(uname -r)" ]; then
		opt_config="/lib/kernel/config-$(uname -r)"
	fi
else
	_info "Verificando vulnerabilidades em relação ao kernel especificado"
	_info "CPU é \033[35m$cpu_friendly_name\033[0m"
fi

if [ -n "$opt_kernel" ]; then
	_verbose "Usará imagem do kernel \033[35m$opt_kernel\033[0m"
else
	_verbose "Não usará imagem do kernel (a precisão pode ser reduzida)"
	bad_accuracy=1
fi

if [ "$os" = Linux ]; then
	if [ -n "$opt_config" ] && ! grep -q '^CONFIG_' "$opt_config"; then
		# given file is invalid!
		_warn "O arquivo de configuração do kernel parece inválido, esperava um arquivo de texto sem formatação, ignorando-o!"
		opt_config=''
	fi

	if [ -n "${dumped_config:-}" ] && [ -n "$opt_config" ]; then
		_verbose "Usará o kconfig \033[35m$procfs/config.gz (descomprimido)\033[0m"
	elif [ -n "$opt_config" ]; then
		_verbose "Usará o kconfig \033[35m$opt_config\033[0m"
	else
		_verbose "Não usará o kconfig (a precisão pode ser reduzida)"
		bad_accuracy=1
	fi

	if [ -n "$opt_map" ]; then
		_verbose "Usará o arquivo System.map \033[35m$opt_map\033[0m"
	else
		_verbose "Não usará nenhum arquivo System.map (a precisão pode ser reduzida)"
		bad_accuracy=1
	fi

	if [ "${bad_accuracy:=0}" = 1 ]; then
		_warn "Faltam algumas informações do kernel (consulte -v), a precisão pode ser reduzida"
	fi
fi

if [ -e "$opt_kernel" ]; then
	if ! command -v "${opt_arch_prefix}readelf" >/dev/null 2>&1; then
		_debug "readelf não encontrado"
		kernel_err="faltando a ferramenta '${opt_arch_prefix}readelf', instale-a, geralmente está no pacote 'binutils'"
	elif [ "$opt_sysfs_only" = 1 ] || [ "$opt_hw_only" = 1 ]; then
		kernel_err='descompressão de imagem do kernel ignorada'
	else
		extract_kernel "$opt_kernel"
	fi
else
	_debug "nenhum opt_kernel definido"
	kernel_err="não foi possível encontrar sua imagem do kernel em /boot, se você usou o netboot, isso é normal"
fi
if [ -z "$kernel" ] || [ ! -r "$kernel" ]; then
	[ -z "$kernel_err" ] && kernel_err="não foi possível extrair seu kernel de $opt_kernel"
else
	# vanilla kernels have with ^Linux version
	# also try harder with some kernels (such as Red Hat) that don't have ^Linux version before their version string
	# and check for FreeBSD
	kernel_version=$("${opt_arch_prefix}strings" "$kernel" 2>/dev/null | grep -E \
		-e '^Linux version ' \
		-e '^[[:alnum:]][^[:space:]]+ \([^[:space:]]+\) #[0-9]+ .+ (19|20)[0-9][0-9]$' \
		-e '^FreeBSD [0-9]' | grep -v 'ABI compat' | head -1)
	if [ -z "$kernel_version" ]; then
		# try even harder with some kernels (such as ARM) that split the release (uname -r) and version (uname -v) in 2 adjacent strings
		kernel_version=$("${opt_arch_prefix}strings" "$kernel" 2>/dev/null | grep -E -B1 '^#[0-9]+ .+ (19|20)[0-9][0-9]$' | tr "\n" " ")
	fi
	if [ -n "$kernel_version" ]; then
		# in live mode, check if the img we found is the correct one
		if [ "$opt_live" = 1 ]; then
			_verbose "A imagem do kernel é \033[35m$kernel_version"
			if ! echo "$kernel_version" | grep -qF "$(uname -r)"; then
				_warn "Possível discrepância entre o kernel em execução '$(uname -r)' e a imagem '$kernel_version' que encontramos ($opt_kernel), os resultados podem estar incorretos"
			fi
		else
			_info "A imagem do kernel é \033[35m$kernel_version"
		fi
	else
		_verbose "A versão da imagem do kernel é desconhecida"
	fi
fi

_info

# end of header stuff

# now we define some util functions and the check_*() funcs, as
# the user can choose to execute only some of those

sys_interface_check()
{
	file="$1"
	regex="${2:-}"
	mode="${3:-}"
	msg=''
	fullmsg=''

	if [ "$opt_live" = 1 ] && [ "$opt_no_sysfs" = 0 ] && [ -r "$file" ]; then
		:
	else
		mockme=$(printf "%b\n%b" "$mockme" "SMC_MOCK_SYSFS_$(basename "$file")_RET=1")
		return 1
	fi

	_mockvarname="SMC_MOCK_SYSFS_$(basename "$file")_RET"
	# shellcheck disable=SC2086,SC1083
	if [ -n "$(eval echo \${$_mockvarname:-})" ]; then
		_debug "sysfs: MOCKING ativado para $file func retorna $(eval echo \$$_mockvarname)"
		mocked=1
		return "$(eval echo \$$_mockvarname)"
	fi

	[ -n "$regex" ] || regex='.*'
	_mockvarname="SMC_MOCK_SYSFS_$(basename "$file")"
	# shellcheck disable=SC2086,SC1083
	if [ -n "$(eval echo \${$_mockvarname:-})" ]; then
		fullmsg="$(eval echo \$$_mockvarname)"
		msg=$(echo "$fullmsg" | grep -Eo "$regex")
		_debug "sysfs: MOCKING ativado para $file, retornará $fullmsg"
		mocked=1
	else
		fullmsg=$(cat "$file")
		msg=$(grep -Eo "$regex" "$file")
		mockme=$(printf "%b\n%b" "$mockme" "SMC_MOCK_SYSFS_$(basename "$file")='$fullmsg'")
	fi
	if [ "$mode" = silent ]; then
		return 0
	elif [ "$mode" = quiet ]; then
		_info "* Informações da interface /sys: $fullmsg"
		return 0
	fi
	_info_nol "* Mitigado de acordo com a interface /sys: "
	if echo "$msg" | grep -qi '^not affected'; then
		# Not affected
		status=OK
		pstatus green SIM "$fullmsg"
	elif echo "$msg" | grep -qEi '^(kvm: )?mitigation'; then
		# Mitigation: PTI
		status=OK
		pstatus green SIM "$fullmsg"
	elif echo "$msg" | grep -qi '^vulnerable'; then
		# Vulnerable
		status=VULN
		pstatus yellow NÃO "$fullmsg"
	else
		status=DESCONHECIDO
		pstatus yellow DESCONHECIDO "$fullmsg"
	fi
	_debug "sys_interface_check: $file=$msg (re=$regex)"
	return 0
}

check_cpu()
{
	_info "\033[1;34mVerificação de hardware\033[0m"

	if ! uname -m | grep -qwE 'x86_64|i[3-6]86|amd64'; then
		return
	fi

	_info     "* Suporte de hardware (microcódigo da CPU) para técnicas de mitigação"
	_info     "  * Especulação Restrita à Filial Indireta (IBRS)"
	_info_nol "    * SPEC_CTRL MSR está disponível: "
	# the new MSR 'SPEC_CTRL' is at offset 0x48
	read_msr 0x48; ret=$?
	if [ $ret = $READ_MSR_RET_OK ]; then
		spec_ctrl_msr=1
		pstatus green SIM
	elif [ $ret = $READ_MSR_RET_KO ]; then
		spec_ctrl_msr=0
		pstatus yellow NÃO
	else
		spec_ctrl_msr=-1
		pstatus yellow DESCONHECIDO "$read_msr_msg"
	fi

	_info_nol "    * CPU indica capacidade do IBRS: "
	# from kernel src: { X86_FEATURE_SPEC_CTRL,        CPUID_EDX,26, 0x00000007, 0 },
	# amd: https://developer.amd.com/wp-content/resources/Architecture_Guidelines_Update_Indirect_Branch_Control.pdf
	# amd: 8000_0008 EBX[14]=1
	cpuid_ibrs=''
	if is_intel; then
		read_cpuid 0x7 0x0 $EDX 26 1 1; ret=$?
		if [ $ret = $READ_CPUID_RET_OK ]; then
			pstatus green SIM "Bit de recurso SPEC_CTRL"
			cpuid_spec_ctrl=1
			cpuid_ibrs='SPEC_CTRL'
		fi
	elif is_amd || is_hygon; then
		read_cpuid 0x80000008 0x0 $EBX 14 1 1; ret=$?
		if [ $ret = $READ_CPUID_RET_OK ]; then
			pstatus green SIM "Bit de recurso IBRS_SUPPORT"
			cpuid_ibrs='IBRS_SUPPORT'
		fi
	else
		ret=invalid
		pstatus yellow NÃO "CPU desconhecida"
	fi
	if [ $ret = $READ_CPUID_RET_KO ]; then
		pstatus yellow NÃO
	elif [ $ret = $READ_CPUID_RET_ERR ]; then
		pstatus yellow DESCONHECIDO "$read_cpuid_msg"
		cpuid_spec_ctrl=-1
	fi

	if is_amd || is_hygon; then
		_info_nol "    * CPU indica que prefere o IBRS sempre ativo: "
		# amd or hygon
		read_cpuid 0x80000008 0x0 $EBX 16 1 1; ret=$?
		if [ $ret = $READ_CPUID_RET_OK ]; then
			pstatus green SIM
		elif [ $ret = $READ_CPUID_RET_KO ]; then
			pstatus yellow NÃO
		else
			pstatus yellow DESCONHECIDO "$read_cpuid_msg"
		fi

		_info_nol "    * CPU indica a preferência do IBRS sobre o retpoline: "
		# amd or hygon
		read_cpuid 0x80000008 0x0 $EBX 18 1 1; ret=$?
		if [ $ret = $READ_CPUID_RET_OK ]; then
			pstatus green SIM
		elif [ $ret = $READ_CPUID_RET_KO ]; then
			pstatus yellow NÃO
		else
			pstatus yellow DESCONHECIDO "$read_cpuid_msg"
		fi
	fi

	# IBPB
	_info     "  * Barreira de Previsão de Filial Indireta (IBPB)"

	if [ "$opt_allow_msr_write" = 1 ]; then
		_info_nol "    * PRED_CMD MSR está disponível: "
		# the new MSR 'PRED_CTRL' is at offset 0x49, write-only
		write_msr 0x49; ret=$?
		if [ $ret = $WRITE_MSR_RET_OK ]; then
			pstatus green SIM
		elif [ $ret = $WRITE_MSR_RET_KO ]; then
			pstatus yellow NÃO
		else
			pstatus yellow DESCONHECIDO "$write_msr_msg"
		fi
	fi

	_info_nol "    * CPU indica capacidade IBPB: "
	# CPUID EAX=0x80000008, ECX=0x00 return EBX[12] indicates support for just IBPB.
	if [ "$cpuid_spec_ctrl" = 1 ]; then
		# spec_ctrl implies ibpb
		cpuid_ibpb='SPEC_CTRL'
		pstatus green SIM "Bit de recurso SPEC_CTRL"
	elif is_intel; then
		if [ "$cpuid_spec_ctrl" = -1 ]; then
			pstatus yellow DESCONHECIDO "o módulo do kernel cpuid está disponível?"
		else
			pstatus yellow NÃO
		fi
	elif is_amd || is_hygon; then
		read_cpuid 0x80000008 0x0 $EBX 12 1 1; ret=$?
		if [ $ret = $READ_CPUID_RET_OK ]; then
			cpuid_ibpb='IBPB_SUPPORT'
			pstatus green SIM "Bit de recurso IBPB_SUPPORT"
		elif [ $ret = $READ_CPUID_RET_KO ]; then
			pstatus yellow NÃO
		else
			pstatus yellow DESCONHECIDO "$read_cpuid_msg"
		fi
	fi

	# STIBP
	_info     "  * Preditores de ramo indireto de segmento único (STIBP)"
	_info_nol "    * SPEC_CTRL MSR está disponível: "
	if [ "$spec_ctrl_msr" = 1 ]; then
		pstatus green SIM
	elif [ "$spec_ctrl_msr" = 0 ]; then
		pstatus yellow NÃO
	else
		pstatus yellow DESCONHECIDO "o módulo do kernel msr está disponível?"
	fi

	_info_nol "    * CPU indica capacidade STIBP: "
	# intel: A processor supports STIBP if it enumerates CPUID (EAX=7H,ECX=0):EDX[27] as 1
	# amd: 8000_0008 EBX[15]=1
	if is_intel; then
		read_cpuid 0x7 0x0 $EDX 27 1 1; ret=$?
		if [ $ret = $READ_CPUID_RET_OK ]; then
			pstatus green SIM "Bit de recurso Intel STIBP"
			#cpuid_stibp='Intel STIBP'
		fi
	elif is_amd; then
		read_cpuid 0x80000008 0x0 $EBX 15 1 1; ret=$?
		if [ $ret = $READ_CPUID_RET_OK ]; then
			pstatus green SIM "Bit de recurso AMD STIBP"
			#cpuid_stibp='AMD STIBP'
		fi
	elif is_hygon; then
		read_cpuid 0x80000008 0x0 $EBX 15 1 1; ret=$?
		if [ $ret = $READ_CPUID_RET_OK ]; then
			pstatus green SIM "Bit de recurso HYGON STIBP"
			#cpuid_stibp='HYGON STIBP'
		fi
	else
		ret=invalid
		pstatus yellow DESCONHECIDO "CPU desconhecida"
	fi
	if [ $ret = $READ_CPUID_RET_KO ]; then
		pstatus yellow NÃO
	elif [ $ret = $READ_CPUID_RET_ERR ]; then
		pstatus yellow DESCONHECIDO "$read_cpuid_msg"
	fi


	if is_amd || is_hygon; then
		_info_nol "    * CPU indica a preferência de STIBP sempre ativo: "
		read_cpuid 0x80000008 0x0 $EBX 17 1 1; ret=$?
		if [ $ret = $READ_CPUID_RET_OK ]; then
			pstatus green SIM
		elif [ $ret = $READ_CPUID_RET_KO ]; then
			pstatus yellow NÃO
		else
			pstatus yellow DESCONHECIDO "$read_cpuid_msg"
		fi
	fi

	# variant 4
	if is_intel; then
		_info     "  * Desvio de desvio de armazenamento especulativo (SSBD)"
		_info_nol "    * CPU indica capacidade SSBD: "
		read_cpuid 0x7 0x0 $EDX 31 1 1; ret24=$?; ret25=$ret24
		if [ $ret24 = $READ_CPUID_RET_OK ]; then
			cpuid_ssbd='Intel SSBD'
		fi
	elif is_amd; then
		_info     "  * Desvio de desvio de armazenamento especulativo (SSBD)"
		_info_nol "    * CPU indica capacidade SSBD: "
		read_cpuid 0x80000008 0x0 $EBX 24 1 1; ret24=$?
		read_cpuid 0x80000008 0x0 $EBX 25 1 1; ret25=$?
		if [ $ret24 = $READ_CPUID_RET_OK ]; then
			cpuid_ssbd='AMD SSBD em SPEC_CTRL'
			#cpuid_ssbd_spec_ctrl=1
		elif [ $ret25 = $READ_CPUID_RET_OK ]; then
			cpuid_ssbd='AMD SSBD em VIRT_SPEC_CTRL'
			#cpuid_ssbd_virt_spec_ctrl=1
		elif [ "$cpu_family" -ge 21 ] && [ "$cpu_family" -le 23 ]; then
			cpuid_ssbd='AMD non-architectural MSR'
		fi
	elif is_hygon; then
		_info     "  * Desvio de desvio de armazenamento especulativo (SSBD)"
		_info_nol "    * CPU indica capacidade SSBD: "
		read_cpuid 0x80000008 0x0 $EBX 24 1 1; ret24=$?
		read_cpuid 0x80000008 0x0 $EBX 25 1 1; ret25=$?

		if [ $ret24 = $READ_CPUID_RET_OK ]; then
			cpuid_ssbd='HYGON SSBD em SPEC_CTRL'
			#hygon cpuid_ssbd_spec_ctrl=1
		elif [ $ret25 = $READ_CPUID_RET_OK ]; then
			cpuid_ssbd='HYGON SSBD em VIRT_SPEC_CTRL'
			#hygon cpuid_ssbd_virt_spec_ctrl=1
		elif [ "$cpu_family" -ge 24 ]; then
			cpuid_ssbd='HYGON non-architectural MSR'
		fi
	fi

	if [ -n "${cpuid_ssbd:=}" ]; then
		pstatus green SIM "$cpuid_ssbd"
	elif [ "$ret24" = $READ_CPUID_RET_ERR ] && [ "$ret25" = $READ_CPUID_RET_ERR ]; then
		pstatus yellow DESCONHECIDO "$read_cpuid_msg"
	else
		pstatus yellow NÃO
	fi

	amd_ssb_no=0
	hygon_ssb_no=0
	if is_amd; then
		# similar to SSB_NO for intel
		read_cpuid 0x80000008 0x0 $EBX 26 1 1; ret=$?
		if [ $ret = $READ_CPUID_RET_OK ]; then
			amd_ssb_no=1
		elif [ $ret = $READ_CPUID_RET_ERR ]; then
			amd_ssb_no=-1
		fi
	elif is_hygon; then
		# indicate when speculative store bypass disable is no longer needed to prevent speculative loads bypassing older stores
		read_cpuid 0x80000008 0x0 $EBX 26 1 1; ret=$?
		if [ $ret = $READ_CPUID_RET_OK ]; then
			hygon_ssb_no=1
		elif [ $ret = $READ_CPUID_RET_ERR ]; then
			hygon_ssb_no=-1
		fi
	fi

	_info "  * Invalidação de cache de dados L1"

	if [ "$opt_allow_msr_write" = 1 ]; then
		_info_nol "    * FLUSH_CMD MSR está disponível: "
		# the new MSR 'FLUSH_CMD' is at offset 0x10b, write-only
		write_msr 0x10b; ret=$?
		if [ $ret = $WRITE_MSR_RET_OK ]; then
			pstatus green SIM
			cpu_flush_cmd=1
		elif [ $ret = $WRITE_MSR_RET_KO ]; then
			pstatus yellow NÃO
			cpu_flush_cmd=0
		else
			pstatus yellow DESCONHECIDO "$write_msr_msg"
			cpu_flush_cmd=-1
		fi
	fi

	# CPUID of L1D
	_info_nol "    * CPU indica capacidade de descarga L1D: "
	read_cpuid 0x7 0x0 $EDX 28 1 1; ret=$?
	if [ $ret = $READ_CPUID_RET_OK ]; then
		pstatus green SIM "Bit de recurso de descarga L1D"
		cpuid_l1df=1
	elif [ $ret = $READ_CPUID_RET_KO ]; then
		pstatus yellow NÃO
		cpuid_l1df=0
	else
		pstatus yellow DESCONHECIDO "$read_cpuid_msg"
		cpuid_l1df=-1
	fi

	# if we weren't allowed to probe the write-only MSR but the CPUID
	# bit says that it shoul be there, make the assumption that it is
	if [ "$opt_allow_msr_write" != 1 ]; then
		cpu_flush_cmd=$cpuid_l1df
	fi

	if is_intel; then
		_info     "  * Amostragem de dados microarquitetônicos"
		_info_nol "    * A instrução VERW está disponível: "
		read_cpuid 0x7 0x0 $EDX 10 1 1; ret=$?
		if [ $ret = $READ_CPUID_RET_OK ]; then
			cpuid_md_clear=1
			pstatus green SIM "Bit de recurso MD_CLEAR"
		elif [ $ret = $READ_CPUID_RET_KO ]; then
			cpuid_md_clear=0
			pstatus yellow NÃO
		else
			cpuid_md_clear=-1
			pstatus yellow DESCONHECIDO "$read_cpuid_msg"
		fi
	fi

	if is_intel; then
		_info     "  * Controles de previsão de ramificação indireta"
		_info_nol "    * O recurso Desativar Preditor Indireto está disponível: "
		read_cpuid 0x7 0x2 $EDX 1 1 1; ret=$?
		if [ $ret = $READ_CPUID_RET_OK ]; then
			cpuid_ipred=1
			pstatus green SIM "Bit de recurso IPRED_CTRL"
		elif [ $ret = $READ_CPUID_RET_KO ]; then
			cpuid_ipred=0
			pstatus yellow NÃO
		else
			cpuid_ipred=-1
			pstatus yellow DESCONHECIDO "$read_cpuid_msg"
		fi

		_info_nol "    * O recurso Desativar RSB sem fundo está disponível: "
		read_cpuid 0x7 0x2 $EDX 2 1 1; ret=$?
		if [ $ret = $READ_CPUID_RET_OK ]; then
			cpuid_rrsba=1
			pstatus green SIM "Bit de recurso RRSBA_CTRL"
		elif [ $ret = $READ_CPUID_RET_KO ]; then
			cpuid_rrsba=0
			pstatus yellow NÃO
		else
			cpuid_rrsba=-1
			pstatus yellow DESCONHECIDO "$read_cpuid_msg"
		fi

		_info_nol "    * O recurso de desativação do preditor indireto focado em BHB está disponível: "
		read_cpuid 0x7 0x2 $EDX 2 1 1; ret=$?
		if [ $ret = $READ_CPUID_RET_OK ]; then
			cpuid_bhi=1
			pstatus green SIM "Bit de recurso BHI_CTRL"
		elif [ $ret = $READ_CPUID_RET_KO ]; then
			cpuid_bhi=0
			pstatus yellow NÃO
		else
			cpuid_bhi=-1
			pstatus yellow DESCONHECIDO "$read_cpuid_msg"
		fi

		# make shellcheck happy while we're not yet using these new cpuid values in our checks
		export cpuid_ipred cpuid_rrsba cpuid_bhi
	fi

	if is_intel; then
		_info     "  * IBRS Aprimorado (IBRS_ALL)"
		_info_nol "    * CPU indica disponibilidade de ARCH_CAPABILITIES MSR: "
		cpuid_arch_capabilities=-1
		# A processor supports the ARCH_CAPABILITIES MSR if it enumerates CPUID (EAX=7H,ECX=0):EDX[29] as 1
		read_cpuid 0x7 0x0 $EDX 29 1 1; ret=$?
		if [ $ret = $READ_CPUID_RET_OK ]; then
			pstatus green SIM
			cpuid_arch_capabilities=1
		elif [ $ret = $READ_CPUID_RET_KO ]; then
			pstatus yellow NÃO
			cpuid_arch_capabilities=0
		else
			pstatus yellow DESCONHECIDO "$read_cpuid_msg"
		fi

		_info_nol "    * ARCH_CAPABILITIES MSR anuncia o recurso IBRS_ALL: "
		capabilities_taa_no=-1
		capabilities_mds_no=-1
		capabilities_rdcl_no=-1
		capabilities_ibrs_all=-1
		capabilities_rsba=-1
		capabilities_l1dflush_no=-1
		capabilities_ssb_no=-1
		capabilities_pschange_msc_no=-1
		capabilities_tsx_ctrl_msr=-1
		capabilities_gds_ctrl=-1
		capabilities_gds_no=-1
		if [ "$cpuid_arch_capabilities" = -1 ]; then
			pstatus yellow DESCONHECIDO
		elif [ "$cpuid_arch_capabilities" != 1 ]; then
			capabilities_rdcl_no=0
			capabilities_taa_no=0
			capabilities_mds_no=0
			capabilities_ibrs_all=0
			capabilities_rsba=0
			capabilities_l1dflush_no=0
			capabilities_ssb_no=0
			capabilities_pschange_msc_no=0
			capabilities_tsx_ctrl_msr=0
			capabilities_gds_ctrl=0
			capabilities_gds_no=0
			pstatus yellow NÃO
		else
			# the new MSR 'ARCH_CAPABILITIES' is at offset 0x10a
			read_msr 0x10a; ret=$?
			capabilities_rdcl_no=0
			capabilities_taa_no=0
			capabilities_mds_no=0
			capabilities_ibrs_all=0
			capabilities_rsba=0
			capabilities_l1dflush_no=0
			capabilities_ssb_no=0
			capabilities_pschange_msc_no=0
			capabilities_tsx_ctrl_msr=0
			capabilities_gds_ctrl=0
			capabilities_gds_no=0
			if [ $ret = $READ_MSR_RET_OK ]; then
				capabilities=$read_msr_value
				# https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/arch/x86/include/asm/msr-index.h#n82
				_debug "capacidades MSR é $capabilities (decimal)"
				[ $(( capabilities >>  0 & 1 )) -eq 1 ] && capabilities_rdcl_no=1
				[ $(( capabilities >>  1 & 1 )) -eq 1 ] && capabilities_ibrs_all=1
				[ $(( capabilities >>  2 & 1 )) -eq 1 ] && capabilities_rsba=1
				[ $(( capabilities >>  3 & 1 )) -eq 1 ] && capabilities_l1dflush_no=1
				[ $(( capabilities >>  4 & 1 )) -eq 1 ] && capabilities_ssb_no=1
				[ $(( capabilities >>  5 & 1 )) -eq 1 ] && capabilities_mds_no=1
				[ $(( capabilities >>  6 & 1 )) -eq 1 ] && capabilities_pschange_msc_no=1
				[ $(( capabilities >>  7 & 1 )) -eq 1 ] && capabilities_tsx_ctrl_msr=1
				[ $(( capabilities >>  8 & 1 )) -eq 1 ] && capabilities_taa_no=1
				[ $(( capabilities >> 25 & 1 )) -eq 1 ] && capabilities_gds_ctrl=1
				[ $(( capabilities >> 26 & 1 )) -eq 1 ] && capabilities_gds_no=1
				_debug "capacidades diz rdcl_no=$capabilities_rdcl_no ibrs_all=$capabilities_ibrs_all rsba=$capabilities_rsba l1dflush_no=$capabilities_l1dflush_no ssb_no=$capabilities_ssb_no mds_no=$capabilities_mds_no taa_no=$capabilities_taa_no pschange_msc_no=$capabilities_pschange_msc_no"
				if [ "$capabilities_ibrs_all" = 1 ]; then
					pstatus green SIM
				else
					pstatus yellow NÃO
				fi
			elif [ $ret = $READ_MSR_RET_KO ]; then
				pstatus yellow NÃO
			else
				pstatus yellow DESCONHECIDO "$read_msr_msg"
			fi
		fi

		_info_nol "  * A CPU indica explicitamente que não está sendo afetada por Meltdown/L1TF (RDCL_NO): "
		if [ "$capabilities_rdcl_no" = -1 ]; then
			pstatus yellow DESCONHECIDO
		elif [ "$capabilities_rdcl_no" = 1 ]; then
			pstatus green SIM
		else
			pstatus yellow NÃO
		fi

		_info_nol "  * A CPU indica explicitamente que não está sendo afetada pela Variante 4 (SSB_NO): "
		if [ "$capabilities_ssb_no" = -1 ]; then
			pstatus yellow DESCONHECIDO
		elif [ "$capabilities_ssb_no" = 1 ] || [ "$amd_ssb_no" = 1 ] || [ "$hygon_ssb_no" = 1 ]; then
			pstatus green SIM
		else
			pstatus yellow NÃO
		fi

		_info_nol "  * CPU/Hypervisor indica que a descarga L1D não é necessária neste sistema: "
		if [ "$capabilities_l1dflush_no" = -1 ]; then
			pstatus yellow DESCONHECIDO
		elif [ "$capabilities_l1dflush_no" = 1 ]; then
			pstatus green SIM
		else
			pstatus yellow NÃO
		fi

		_info_nol "  * O hipervisor indica que a CPU do host pode ser afetada pelo subfluxo de RSB (RSBA): "
		if [ "$capabilities_rsba" = -1 ]; then
			pstatus yellow DESCONHECIDO
		elif [ "$capabilities_rsba" = 1 ]; then
			pstatus yellow SIM
		else
			pstatus blue NÃO
		fi

		_info_nol "  * A CPU indica explicitamente que não está sendo afetada pelo Amostragem de dados microarquiteturais (MDS_NO): "
		if [ "$capabilities_mds_no" = -1 ]; then
			pstatus yellow DESCONHECIDO
		elif [ "$capabilities_mds_no" = 1 ]; then
			pstatus green SIM
		else
			pstatus yellow NÃO
		fi

		_info_nol "  * A CPU indica explicitamente que não está sendo afetada pelo TSX Asynchronous Abort (TAA_NO): "
		if [ "$capabilities_taa_no" = -1 ]; then
			pstatus yellow DESCONHECIDO
		elif [ "$capabilities_taa_no" = 1 ]; then
			pstatus green SIM
		else
			pstatus yellow NÃO
		fi

		_info_nol "  * A CPU indica explicitamente que não está sendo afetada pelo iTLB Multihit (PSCHANGE_MSC_NO): "
		if [ "$capabilities_pschange_msc_no" = -1 ]; then
			pstatus yellow DESCONHECIDO
		elif [ "$capabilities_pschange_msc_no" = 1 ]; then
			pstatus green SIM
		else
			pstatus yellow NÃO
		fi

		_info_nol "  * CPU indica explicitamente ter MSR para controle TSX (TSX_CTRL_MSR): "
		if [ "$capabilities_tsx_ctrl_msr" = -1 ]; then
			pstatus yellow DESCONHECIDO
		elif [ "$capabilities_tsx_ctrl_msr" = 1 ]; then
			pstatus green SIM
		else
			pstatus yellow NÃO
		fi

		if [ "$capabilities_tsx_ctrl_msr" = 1 ]; then
			read_msr 0x122; ret=$?
			if [ "$ret" = $READ_MSR_RET_OK ]; then
				tsx_ctrl_msr=$read_msr_value
				tsx_ctrl_msr_rtm_disable=$(( tsx_ctrl_msr >> 0 & 1 ))
				tsx_ctrl_msr_cpuid_clear=$(( tsx_ctrl_msr >> 1 & 1 ))
			fi

			_info_nol "    * TSX_CTRL MSR indica que TSX RTM está desabilitado: "
			if [ "$tsx_ctrl_msr_rtm_disable" = 1 ]; then
				pstatus blue SIM
			elif [ "$tsx_ctrl_msr_rtm_disable" = 0 ]; then
				pstatus blue NÃO
			else
				pstatus yellow DESCONHECIDO "não consegui ler MSR"
			fi

			_info_nol "    * TSX_CTRL MSR indica que o bit TSX CPUID está limpo: "
			if [ "$tsx_ctrl_msr_cpuid_clear" = 1 ]; then
				pstatus blue SIM
			elif [ "$tsx_ctrl_msr_cpuid_clear" = 0 ]; then
				pstatus blue NÃO
			else
				pstatus yellow DESCONHECIDO "não consegui ler MSR"
			fi
		fi

		_info_nol "  * A CPU indica explicitamente ser afetada pelo GDS e ter controle de mitigação (GDS_CTRL): "
		if [ "$capabilities_gds_ctrl" = -1 ]; then
			pstatus yellow DESCONHECIDO "não consegui ler MSR"
		elif [ "$capabilities_gds_ctrl" = 1 ]; then
			pstatus green SIM
		else
			pstatus blue NÃO
		fi

		mcu_opt_ctrl_gds_mitg_dis=-1
		mcu_opt_ctrl_gds_mitg_lock=-1
		if [ "$capabilities_gds_ctrl" = 1 ]; then
			# read the IA32_MCU_OPT_CTRL MSR
			read_msr 0x123; ret=$?
			if [ "$ret" = $READ_MSR_RET_OK ]; then
				mcu_opt_ctrl=$read_msr_value
				mcu_opt_ctrl_gds_mitg_dis=$((  mcu_opt_ctrl >> 4 & 1 ))
				mcu_opt_ctrl_gds_mitg_lock=$(( mcu_opt_ctrl >> 5 & 1 ))
			fi

			_info_nol "    * A mitigação do microcódigo GDS está desativada (GDS_MITG_DIS): "
			if [ "$mcu_opt_ctrl_gds_mitg_dis" = -1 ]; then
				pstatus yellow DESCONHECIDO "não consegui ler MSR"
			elif [ "$mcu_opt_ctrl_gds_mitg_dis" = 1 ]; then
				pstatus yellow SIM
			else
				pstatus green NÃO
			fi

			_info_nol "    * A mitigação do microcódigo GDS está bloqueada no estado habilitado (GDS_MITG_LOCK): "
			if [ "$mcu_opt_ctrl_gds_mitg_lock" = -1 ]; then
				pstatus yellow DESCONHECIDO "não consegui ler MSR"
			elif [ "$mcu_opt_ctrl_gds_mitg_lock" = 1 ]; then
				pstatus blue SIM
			else
				pstatus blue NÃO
			fi
		fi

		_info_nol "  * A CPU indica explicitamente que não está sendo afetada pelo GDS (GDS_NO): "
		if [ "$capabilities_gds_no" = -1 ]; then
			pstatus yellow DESCONHECIDO "não consegui ler MSR"
		elif [ "$capabilities_gds_no" = 1 ]; then
			pstatus green SIM
		else
			pstatus yellow NÃO
		fi

	fi

	if is_amd || is_hygon; then
		_info "  * Barreira Preditora de Ramo Seletivo (SBPB)"
		_info_nol "    * PRED_CMD MSR suporta gravação de bits SBPB: "

		if [ "$opt_allow_msr_write" = 1 ]; then
			# the MSR PRED_SBPB is at offset 0x49, BIT(7), write-only
			write_msr 0x49 128; ret=$?
			if [ $ret = $WRITE_MSR_RET_OK ]; then
				pstatus green SIM
				cpuid_sbpb=1
			elif [ $ret = $WRITE_MSR_RET_KO ]; then
				pstatus yellow NÃO
				cpuid_sbpb=2
			else
				pstatus yellow DESCONHECIDO "$write_msr_msg"
				cpuid_sbpb=3
			fi
		else
			pstatus yellow DESCONHECIDO "não é permitido escrever msr"
			cpuid_sbpb=3
		fi
	fi

	_info_nol "  * A CPU suporta extensões de sincronização transacional (TSX): "
	ret=$READ_CPUID_RET_KO
	cpuid_rtm=0
	if is_intel; then
		read_cpuid 0x7 0x0 $EBX 11 1 1; ret=$?
	fi
	if [ $ret = $READ_CPUID_RET_OK ]; then
		cpuid_rtm=1
		pstatus green SIM "Bit de recurso RTM"
	elif [ $ret = $READ_CPUID_RET_KO ]; then
		pstatus yellow NÃO
	else
		cpuid_rtm=-1
		pstatus yellow DESCONHECIDO "$read_cpuid_msg"
	fi

	_info_nol "  * CPU suporta Extensões de proteção de software (SGX): "
	ret=$READ_CPUID_RET_KO
	cpuid_sgx=0
	if is_intel; then
		read_cpuid 0x7 0x0 $EBX 2 1 1; ret=$?
	fi
	if [ $ret = $READ_CPUID_RET_OK ]; then
		pstatus blue SIM
		cpuid_sgx=1
	elif [ $ret = $READ_CPUID_RET_KO ]; then
		pstatus green NÃO
	else
		cpuid_sgx=-1
		pstatus yellow DESCONHECIDO "$read_cpuid_msg"
	fi

	_info_nol "  * CPU suporta Amostragem de dados de buffer de registro especial (SRBDS): "
	# A processor supports SRBDS if it enumerates CPUID (EAX=7H,ECX=0):EDX[9] as 1
	# That means the mitigation disabling SRBDS exists
	ret=$READ_CPUID_RET_KO
	cpuid_srbds=0
	srbds_on=0
	if is_intel; then
		read_cpuid 0x7 0x0 $EDX 9 1 1; ret=$?
	fi
	if [ $ret = $READ_CPUID_RET_OK ]; then
		pstatus blue SIM
		cpuid_srbds=1
		read_msr 0x123; ret=$?
		if [ $ret = $READ_MSR_RET_OK ]; then
			if [ $read_msr_value = 0 ]; then
				#SRBDS mitigation control exists and is enabled via microcode
				srbds_on=1
			else
				#SRBDS mitigation control exists but is disabled via microcode
				srbds_on=0
			fi
		else
			srbds_on=-1
		fi
	elif [ $ret = $READ_CPUID_RET_KO ]; then
		pstatus green NÃO
	else
		pstatus yellow DESCONHECIDO "$read_cpuid_msg"
		cpuid_srbds=0
	fi

	if is_amd; then
		_info_nol "  * O microcódigo da CPU é conhecido por corrigir o Zenbleed: "
		has_zenbleed_fixed_firmware; ret=$?
		if [ $ret -eq 0 ]; then
			# affected CPU, new fw
			pstatus green SIM
		elif [ $ret -eq 1 ]; then
			# affected CPU, old fw
			pstatus red NÃO "versão necessária: $zenbleed_fw_required"
		else
			# unaffected CPU
			pstatus yellow NÃO
		fi
	fi

	_info_nol "  * Sabe-se que o microcódigo da CPU causa problemas de estabilidade: "
	if is_ucode_blacklisted; then
		pstatus red SIM "$ucode_found"
		_warn
		_warn "Sabe-se que o microcódigo em que sua CPU está sendo executada causa problemas de instabilidade,"
		_warn "como reinicializações intempestivas ou falhas aleatórias."
		_warn "Recomenda-se reverter para uma versão anterior do microcódigo (que pode não ter"
		_warn "atenuações para Spectre) ou atualize para uma mais nova, se disponível."
		_warn
	else
		pstatus blue NÃO "$ucode_found"
	fi

	_info_nol "  * O microcódigo da CPU é a versão disponível mais recente conhecida: "
	is_latest_known_ucode; ret=$?
	if [ $ret -eq 0 ]; then
		pstatus green SIM "$ucode_latest"
	elif [ $ret -eq 1 ]; then
		pstatus red NÃO "$ucode_latest"
	else
		pstatus blue DESCONHECIDO "$ucode_latest"
	fi
}

check_cpu_vulnerabilities()
{
	_info     "* Vulnerabilidade da CPU às variantes de ataque de execução especulativa"
	for cve in $supported_cve_list; do
		_info_nol "  * Afetado por $cve ($(cve2name "$cve")): "
		if is_cpu_affected "$cve"; then
			pstatus yellow SIM
		else
			pstatus green NÃO
		fi
	done
}

check_redhat_canonical_spectre()
{
	# if we were already called, don't do it again
	[ -n "${redhat_canonical_spectre:-}" ] && return

	if ! command -v "${opt_arch_prefix}strings" >/dev/null 2>&1; then
		redhat_canonical_spectre=-1
	elif [ -n "$kernel_err" ]; then
		redhat_canonical_spectre=-2
	else
		# Red Hat / Ubuntu specific variant1 patch is difficult to detect,
		# let's use the two same tricks than the official Red Hat detection script uses:
		if "${opt_arch_prefix}strings" "$kernel" | grep -qw noibrs && "${opt_arch_prefix}strings" "$kernel" | grep -qw noibpb; then
			# 1) detect their specific variant2 patch. If it's present, it means
			# that the variant1 patch is also present (both were merged at the same time)
			_debug "versão redhat/canonical encontrada do patch variant2 (implica variant1)"
			redhat_canonical_spectre=1
		elif "${opt_arch_prefix}strings" "$kernel" | grep -q 'x86/pti:'; then
			# 2) detect their specific variant3 patch. If it's present, but the variant2
			# is not, it means that only variant1 is present in addition to variant3
			_debug "versão redhat/canonical encontrada do patch variant3 (implica na variante1, mas não na variante2)"
			redhat_canonical_spectre=2
		else
			redhat_canonical_spectre=0
		fi
	fi
}

check_has_vmm()
{
	_info_nol "* Este sistema é um host executando um hypervisor: "
	has_vmm=$opt_vmm
	if [ "$has_vmm" = -1 ] && [ "$opt_paranoid" = 1 ]; then
		# In paranoid mode, if --vmm was not specified on the command-line,
		# we want to be secure before everything else, so assume we're running
		# a hypervisor, as this requires more mitigations
		has_vmm=2
	elif [ "$has_vmm" = -1 ]; then
		# Here, we want to know if we are hosting a hypervisor, and running some VMs on it.
		# If we find no evidence that this is the case, assume we're not (to avoid scaring users),
		# this can always be overridden with --vmm in any case.
		has_vmm=0
		if command -v pgrep >/dev/null 2>&1; then
			# remove xenbus and xenwatch, also present inside domU
			# remove libvirtd as it can also be used to manage containers and not VMs
			# for each binary we want to grep, get the pids
			for _binary in qemu kvm xenstored xenconsoled
			do
				for _pid in $(pgrep -x $_binary)
				do
					# resolve the exe symlink, if it doesn't resolve with -m,
					# which doesn't even need the dest to exist, it means the symlink
					# is null, which is the case for kernel threads: ignore those to
					# avoid false positives (such as [kvm-irqfd-clean] under at least RHEL 7.6/7.7)
					if ! [ "$(readlink -m "/proc/$_pid/exe")" = "/proc/$_pid/exe" ]; then
						_debug "has_vmm: PID $_pid encontrado"
						has_vmm=1
					fi
				done
			done
			unset _binary _pid
		else
			# ignore SC2009 as `ps ax` is actually used as a fallback if `pgrep` isn't installed
			# shellcheck disable=SC2009
			if command -v ps >/dev/null && ps ax | grep -vw grep | grep -q -e '\<qemu' -e '/qemu' -e '<\kvm' -e '/kvm' -e '/xenstored' -e '/xenconsoled'; then
				has_vmm=1
			fi
		fi
	fi
	if [ "$has_vmm" = 0 ]; then
		if [ "$opt_vmm" != -1 ]; then
			pstatus green NÃO "forçado a partir da linha de comando"
		else
			pstatus green NÃO
		fi
	else
		if [ "$opt_vmm" != -1 ]; then
			pstatus blue SIM "forçado a partir da linha de comando"
		elif [ "$has_vmm" = 2 ]; then
			pstatus blue SIM "modo paranóico"
		else
			pstatus blue SIM
		fi
	fi
}

###################
# SPECTRE 1 SECTION

# bounds check bypass aka 'Spectre Variant 1'
check_CVE_2017_5753()
{
	cve='CVE-2017-5753'
	_info "\033[1;34m$cve também conhecido como '$(cve2name "$cve")'\033[0m"
	if [ "$os" = Linux ]; then
		check_CVE_2017_5753_linux
	elif echo "$os" | grep -q BSD; then
		check_CVE_2017_5753_bsd
	else
		_warn "SO não suportado ($os)"
	fi
}

check_CVE_2017_5753_linux()
{
	status=DESCONHECIDO
	sys_interface_available=0
	msg=''
	if sys_interface_check "/sys/devices/system/cpu/vulnerabilities/spectre_v1"; then
		# this kernel has the /sys interface, trust it over everything
		# v0.33+: don't. some kernels have backported the array_index_mask_nospec() workaround without
		# modifying the vulnerabilities/spectre_v1 file. that's bad. we can't trust it when it says Vulnerable :(
		# see "silent backport" detection at the bottom of this func
		sys_interface_available=1
	fi
	if [ "$opt_sysfs_only" != 1 ]; then
		# no /sys interface (or offline mode), fallback to our own ways
		_info_nol "* O kernel possui array_index_mask_nospec: "
		# vanilla: look for the Linus' mask aka array_index_mask_nospec()
		# that is inlined at least in raw_copy_from_user (__get_user_X symbols)
		#mov PER_CPU_VAR(current_task), %_ASM_DX
		#cmp TASK_addr_limit(%_ASM_DX),%_ASM_AX
		#jae bad_get_user
		# /* array_index_mask_nospec() are the 2 opcodes that follow */
		#+sbb %_ASM_DX, %_ASM_DX
		#+and %_ASM_DX, %_ASM_AX
		#ASM_STAC
		# x86 64bits: jae(0x0f 0x83 0x?? 0x?? 0x?? 0x??) sbb(0x48 0x19 0xd2) and(0x48 0x21 0xd0)
		# x86 32bits: cmp(0x3b 0x82 0x?? 0x?? 0x00 0x00) jae(0x73 0x??) sbb(0x19 0xd2) and(0x21 0xd0)
		#
		# arm32
		##ifdef CONFIG_THUMB2_KERNEL
		##define CSDB	".inst.w 0xf3af8014"
		##else
		##define CSDB	".inst	0xe320f014"     e320f014
		##endif
		#asm volatile(
		#	"cmp	%1, %2\n"      e1500003
		#"	sbc	%0, %1, %1\n"  e0c03000
		#CSDB
		#: "=r" (mask)
		#: "r" (idx), "Ir" (sz)
		#: "cc");
		#
		# http://git.arm.linux.org.uk/cgit/linux-arm.git/commit/?h=spectre&id=a78d156587931a2c3b354534aa772febf6c9e855
		v1_mask_nospec=''
		if [ -n "$kernel_err" ]; then
			pstatus yellow DESCONHECIDO "não pude verificar ($kernel_err)"
		elif ! command -v perl >/dev/null 2>&1; then
			pstatus yellow DESCONHECIDO "binário 'perl' ausente, instale-o"
		else
			perl -ne '/\x0f\x83....\x48\x19\xd2\x48\x21\xd0/ and $found++; END { exit($found) }' "$kernel"; ret=$?
			if [ $ret -gt 0 ]; then
				pstatus green SIM "$ret ocorrência (s) encontrada (s) de x86 64 bits array_index_mask_nospec()"
				v1_mask_nospec="x86 64 bits array_index_mask_nospec"
			else
				perl -ne '/\x3b\x82..\x00\x00\x73.\x19\xd2\x21\xd0/ and $found++; END { exit($found) }' "$kernel"; ret=$?
				if [ $ret -gt 0 ]; then
					pstatus green SIM "$ret ocorrência (s) encontrada (s) de x86 32 bits array_index_mask_nospec()"
					v1_mask_nospec="x86 32 bits array_index_mask_nospec"
				else
					ret=$("${opt_arch_prefix}objdump" $objdump_options "$kernel" | grep -w -e f3af8014 -e e320f014 -B2 | grep -B1 -w sbc | grep -w -c cmp)
					if [ "$ret" -gt 0 ]; then
						pstatus green SIM "$ret ocorrência (s) encontrada (s) do braço de 32 bits array_index_mask_nospec()"
						v1_mask_nospec="arm 32 bits array_index_mask_nospec"
					else
						pstatus yellow NÃO
					fi
				fi
			fi
		fi

		_info_nol "* O kernel possui o patch Red Hat/Ubuntu: "
		check_redhat_canonical_spectre
		if [ "$redhat_canonical_spectre" = -1 ]; then
			pstatus yellow DESCONHECIDO "faltando a ferramenta '${opt_arch_prefix}strings', instale-a, geralmente está no pacote binutils"
		elif [ "$redhat_canonical_spectre" = -2 ]; then
			pstatus yellow DESCONHECIDO "não pude verificar ($kernel_err)"
		elif [ "$redhat_canonical_spectre" = 1 ]; then
			pstatus green SIM
		elif [ "$redhat_canonical_spectre" = 2 ]; then
			pstatus green SIM "mas sem IBRS"
		else
			pstatus yellow NÃO
		fi

		_info_nol "* O kernel possui mask_nospec64 (arm64): "
		#.macro	mask_nospec64, idx, limit, tmp
		#sub	\tmp, \idx, \limit
		#bic	\tmp, \tmp, \idx
		#and	\idx, \idx, \tmp, asr #63
		#csdb
		#.endm
		#$ aarch64-linux-gnu-objdump -d vmlinux | grep -w bic -A1 -B1 | grep -w sub -A2 | grep -w and -B2
		#ffffff8008082e44:       cb190353        sub     x19, x26, x25
		#ffffff8008082e48:       8a3a0273        bic     x19, x19, x26
		#ffffff8008082e4c:       8a93ff5a        and     x26, x26, x19, asr #63
		#ffffff8008082e50:       d503229f        hint    #0x14
		# /!\ can also just be "csdb" instead of "hint #0x14" for native objdump
		#
		# if we have v1_mask_nospec or redhat_canonical_spectre>0, don't bother disassembling the kernel, the answer is no.
		if [ -n "$v1_mask_nospec" ] || [ "$redhat_canonical_spectre" -gt 0 ]; then
			pstatus yellow NÃO
		elif [ -n "$kernel_err" ]; then
			pstatus yellow DESCONHECIDO "não pude verificar ($kernel_err)"
		elif ! command -v perl >/dev/null 2>&1; then
			pstatus yellow DESCONHECIDO "falta o binário 'perl', instale-o"
		elif ! command -v "${opt_arch_prefix}objdump" >/dev/null 2>&1; then
			pstatus yellow DESCONHECIDO "faltando a ferramenta '${opt_arch_prefix}objdump', instale-a, geralmente está no pacote binutils"
		else
			"${opt_arch_prefix}objdump" $objdump_options "$kernel" | perl -ne 'push @r, $_; /\s(hint|csdb)\s/ && $r[0]=~/\ssub\s+(x\d+)/ && $r[1]=~/\sbic\s+$1,\s+$1,/ && $r[2]=~/\sand\s/ && exit(9); shift @r if @r>3'; ret=$?
			if [ "$ret" -eq 9 ]; then
				pstatus green SIM "macro mask_nospec64 está presente e é usada"
				v1_mask_nospec="arm64 mask_nospec64"
			else
				pstatus yellow NÃO
			fi
		fi

		_info_nol "* Kernel tem array_index_nospec (arm64): "
		# in 4.19+ kernels, the mask_nospec64 asm64 macro is replaced by array_index_nospec, defined in nospec.h, and used in invoke_syscall()
		# ffffff8008090a4c:       2a0203e2        mov     w2, w2
		# ffffff8008090a50:       eb0200bf        cmp     x5, x2
		# ffffff8008090a54:       da1f03e2        ngc     x2, xzr
		# ffffff8008090a58:       d503229f        hint    #0x14
		# /!\ can also just be "csdb" instead of "hint #0x14" for native objdump
		#
		# if we have v1_mask_nospec or redhat_canonical_spectre>0, don't bother disassembling the kernel, the answer is no.
		if [ -n "$v1_mask_nospec" ] || [ "$redhat_canonical_spectre" -gt 0 ]; then
			pstatus yellow NÃO
		elif [ -n "$kernel_err" ]; then
			pstatus yellow DESCONHECIDO "não pude verificar ($kernel_err)"
		elif ! command -v perl >/dev/null 2>&1; then
			pstatus yellow DESCONHECIDO "falta o binário 'perl', instale-o"
		elif ! command -v "${opt_arch_prefix}objdump" >/dev/null 2>&1; then
			pstatus yellow DESCONHECIDO "faltando a ferramenta '${opt_arch_prefix}objdump', instale-a, geralmente está no pacote binutils"
		else
			"${opt_arch_prefix}objdump" -d "$kernel" | perl -ne 'push @r, $_; /\s(hint|csdb)\s/ && $r[0]=~/\smov\s+(w\d+),\s+(w\d+)/ && $r[1]=~/\scmp\s+(x\d+),\s+(x\d+)/ && $r[2]=~/\sngc\s+$2,/ && exit(9); shift @r if @r>3'; ret=$?
			if [ "$ret" -eq 9 ]; then
				pstatus green SIM "macro array_index_nospec está presente e é usado"
				v1_mask_nospec="arm64 array_index_nospec"
			else
				pstatus yellow NÃO
			fi
		fi

		if [ "$opt_verbose" -ge 2 ] || { [ -z "$v1_mask_nospec" ] && [ "$redhat_canonical_spectre" != 1 ] && [ "$redhat_canonical_spectre" != 2 ]; }; then
			# this is a slow heuristic and we don't need it if we already know the kernel is patched
			# but still show it in verbose mode
			_info_nol "* Verificando a contagem de instruções LFENCE após um salto no kernel... "
			if [ -n "$kernel_err" ]; then
				pstatus yellow DESCONHECIDO "não pude verificar ($kernel_err)"
			else
				if ! command -v "${opt_arch_prefix}objdump" >/dev/null 2>&1; then
					pstatus yellow DESCONHECIDO "faltando a ferramenta '${opt_arch_prefix}objdump', por favor instale-o, geralmente está no pacote binutils"
				else
					# here we disassemble the kernel and count the number of occurrences of the LFENCE opcode
					# in non-patched kernels, this has been empirically determined as being around 40-50
					# in patched kernels, this is more around 70-80, sometimes way higher (100+)
					# v0.13: 68 found in a 3.10.23-xxxx-std-ipv6-64 (with lots of modules compiled-in directly), which doesn't have the LFENCE patches,
					# so let's push the threshold to 70.
					# v0.33+: now only count lfence opcodes after a jump, way less error-prone
					# non patched kernel have between 0 and 20 matches, patched ones have at least 40-45
					nb_lfence=$("${opt_arch_prefix}objdump" $objdump_options "$kernel" 2>/dev/null | grep -w -B1 lfence | grep -Ewc 'jmp|jne|je')
					if [ "$nb_lfence" -lt 30 ]; then
						pstatus yellow NÃO "apenas $nb_lfence jump-then-lfence instruções encontradas, devem ser >= 30 (heurística)"
					else
						v1_lfence=1
						pstatus green SIM "$nb_lfence jump-then-lfence instruções encontradas, devem ser >= 30 (heurística)"
					fi
				fi
			fi
		fi

	else
		# we have no sysfs but were asked to use it only!
		msg="A interface de vulnerabilidade /sys usa forçado, mas não está disponível!"
		status=DESCONHECIDO
	fi

	# report status
	if ! is_cpu_affected "$cve"; then
		# override status & msg in case CPU is not vulnerable after all
		pvulnstatus $cve OK "seu fornecedor de CPU relatou que seu modelo de CPU não é afetado"
	elif [ -z "$msg" ]; then
		# if msg is empty, sysfs check didn't fill it, rely on our own test
		if [ -n "$v1_mask_nospec" ]; then
			pvulnstatus $cve OK "A fonte do kernel foi corrigida para mitigar a vulnerabilidade ($v1_mask_nospec)"
		elif [ "$redhat_canonical_spectre" = 1 ] || [ "$redhat_canonical_spectre" = 2 ]; then
			pvulnstatus $cve OK "A fonte do kernel foi corrigida para mitigar a vulnerabilidade (patch Red Hat/Ubuntu)"
		elif [ "$v1_lfence" = 1 ]; then
			pvulnstatus $cve OK "A fonte do kernel PROVAVELMENTE foi corrigida para mitigar a vulnerabilidade (heurística de instruções jump-then-lfence)"
		elif [ -n "$kernel_err" ]; then
			pvulnstatus $cve DESCONHECIDO "Não foi possível encontrar a imagem do kernel ou ferramentas faltando para executar as verificações"
			explain "Execute novamente este script com privilégios de root, após instalar as ferramentas ausentes indicadas acima"
		else
			pvulnstatus $cve VULNERÁVEL "A fonte do kernel precisa ser corrigida para mitigar a vulnerabilidade"
			explain "Seu kernel é muito antigo para ter a mitigação da Variante 1, você deve atualizar para um kernel mais novo. Se você está usando uma distribuição Linux e não compilou o kernel por conta própria, atualize sua distribuição para obter um kernel mais novo."
		fi
	else
		if [ "$msg" = "Vulnerable" ] && [ -n "$v1_mask_nospec" ]; then
			pvulnstatus $cve OK "A fonte do kernel foi corrigida para mitigar a vulnerabilidade (backport silencioso de array_index_mask_nospec)"
		else
			if [ "$msg" = "Vulnerable" ]; then
				msg="A fonte do kernel precisa ser corrigida para mitigar a vulnerabilidade"
				_explain="Seu kernel é muito antigo para ter a mitigação da Variante 1, você deve atualizar para um kernel mais novo. Se você está usando uma distribuição Linux e não compilou o kernel por conta própria, atualize sua distribuição para obter um kernel mais novo."
			fi
			pvulnstatus $cve "$status" "$msg"
			[ -n "${_explain:-}" ] && explain "$_explain"
			unset _explain
		fi
	fi
}

check_CVE_2017_5753_bsd()
{
	if ! is_cpu_affected "$cve"; then
		# override status & msg in case CPU is not vulnerable after all
		pvulnstatus $cve OK "seu fornecedor de CPU relatou que seu modelo de CPU não é afetado"
	else
		pvulnstatus $cve VULNERÁVEL "nenhuma mitigação para BSD ainda"
	fi
}

###################
# SPECTRE 2 SECTION

# branch target injection aka 'Spectre Variant 2'
check_CVE_2017_5715()
{
	cve='CVE-2017-5715'
	_info "\033[1;34m$cve também conhecido como '$(cve2name "$cve")'\033[0m"
	if [ "$os" = Linux ]; then
		check_CVE_2017_5715_linux
	elif echo "$os" | grep -q BSD; then
		check_CVE_2017_5715_bsd
	else
		_warn "SO não suportado ($os)"
	fi
}

check_CVE_2017_5715_linux()
{
	status=DESCONHECIDO
	sys_interface_available=0
	msg=''
	if sys_interface_check "/sys/devices/system/cpu/vulnerabilities/spectre_v2"; then
		# this kernel has the /sys interface, trust it over everything
		sys_interface_available=1
	fi
	if [ "$opt_sysfs_only" != 1 ]; then
		_info "* Mitigação 1"

		ibrs_can_tell=0
		ibrs_supported=''
		ibrs_enabled=''
		ibpb_can_tell=0
		ibpb_supported=''
		ibpb_enabled=''

		if [ "$opt_live" = 1 ]; then
			# in live mode, we can check for the ibrs_enabled file in debugfs
			# all versions of the patches have it (NOT the case of IBPB or KPTI)
			ibrs_can_tell=1
			mount_debugfs
			for dir in \
				/sys/kernel/debug \
				/sys/kernel/debug/x86 \
				"$procfs/sys/kernel"; do
				if [ -e "$dir/ibrs_enabled" ]; then
					# if the file is there, we have IBRS compiled-in
					# /sys/kernel/debug/ibrs_enabled: vanilla
					# /sys/kernel/debug/x86/ibrs_enabled: Red Hat (see https://access.redhat.com/articles/3311301)
					# /proc/sys/kernel/ibrs_enabled: OpenSUSE tumbleweed
					specex_knob_dir=$dir
					ibrs_supported="$dir/ibrs_enabled existe"
					ibrs_enabled=$(cat "$dir/ibrs_enabled" 2>/dev/null)
					_debug "ibrs: encontrado $dir/ibrs_enabled=$ibrs_enabled"
					# if ibrs_enabled is there, ibpb_enabled will be in the same dir
					if [ -e "$dir/ibpb_enabled" ]; then
						# if the file is there, we have IBPB compiled-in (see note above for IBRS)
						ibpb_supported="$dir/ibpb_enabled existe"
						ibpb_enabled=$(cat "$dir/ibpb_enabled" 2>/dev/null)
						_debug "ibpb: encontrado $dir/ibpb_enabled=$ibpb_enabled"
					else
						_debug "ibpb: $dir/ibpb_enabled arquivo não existe"
					fi
					break
				else
					_debug "ibrs: $dir/ibrs_enabled arquivo não existe"
				fi
			done
			# on some newer kernels, the spec_ctrl_ibrs flag in "$procfs/cpuinfo"
			# is set when ibrs has been administratively enabled (usually from cmdline)
			# which in that case means ibrs is supported *and* enabled for kernel & user
			# as per the ibrs patch series v3
			if [ -z "$ibrs_supported" ]; then
				if grep ^flags "$procfs/cpuinfo" | grep -qw spec_ctrl_ibrs; then
					_debug "ibrs: encontrado o sinalizador spec_ctrl_ibrs em $procfs/cpuinfo"
					ibrs_supported="sinalizador spec_ctrl_ibrs em $procfs/cpuinfo"
					# enabled=2 -> kernel & user
					ibrs_enabled=2
					# XXX and what about ibpb ?
				fi
			fi
			if [ -n "$fullmsg" ]; then
				# when IBPB is enabled on 4.15+, we can see it in sysfs
				if echo "$fullmsg" | grep -q 'IBPB'; then
					_debug "ibpb: encontrado habilitado no sysfs"
					[ -z "$ibpb_supported" ] && ibpb_supported='IBPB encontrado habilitado no sysfs'
					[ -z "$ibpb_enabled"   ] && ibpb_enabled=1
				fi
				# when IBRS_FW is enabled on 4.15+, we can see it in sysfs
				if echo "$fullmsg" | grep -q 'IBRS_FW'; then
					_debug "ibrs: encontrado IBRS_FW em sysfs"
					[ -z "$ibrs_supported" ] && ibrs_supported='encontrado IBRS_FW em sysfs'
					ibrs_fw_enabled=1
				fi
				# when IBRS is enabled on 4.15+, we can see it in sysfs
				# on a more recent kernel, classic "IBRS" is not even longer an option, because of the performance impact.
				# only "Enhanced IBRS" is available (on CPUs with the IBRS_ALL flag)
				if echo "$fullmsg" | grep -q -e '\<IBRS\>' -e 'Indirect Branch Restricted Speculation'; then
					_debug "ibrs: encontrado IBRS em sysfs"
					[ -z "$ibrs_supported" ] && ibrs_supported='encontrado IBRS em sysfs'
					[ -z "$ibrs_enabled"   ] && ibrs_enabled=3
				fi
				# checking for 'Enhanced IBRS' in sysfs, enabled on CPUs with IBRS_ALL
				if echo "$fullmsg" | grep -q -e 'Enhanced IBRS'; then
					[ -z "$ibrs_supported" ] && ibrs_supported='encontrado IBRS aprimorado em sysfs'
					# 4 isn't actually a valid value of the now extinct "ibrs_enabled" flag file,
					# that only went from 0 to 3, so we use 4 as "enhanced ibrs is enabled"
					ibrs_enabled=4
				fi
			fi
			# in live mode, if ibrs or ibpb is supported and we didn't find these are enabled, then they are not
			[ -n "$ibrs_supported" ] && [ -z "$ibrs_enabled" ] && ibrs_enabled=0
			[ -n "$ibpb_supported" ] && [ -z "$ibpb_enabled" ] && ibpb_enabled=0
		fi
		if [ -z "$ibrs_supported" ]; then
			check_redhat_canonical_spectre
			if [ "$redhat_canonical_spectre" = 1 ]; then
				ibrs_supported="Variante Red Hat/Ubuntu"
				ibpb_supported="Variante Red Hat/Ubuntu"
			fi
		fi
		if [ -z "$ibrs_supported" ] && [ -n "$kernel" ]; then
			if ! command -v "${opt_arch_prefix}strings" >/dev/null 2>&1; then
				:
			else
				ibrs_can_tell=1
				ibrs_supported=$("${opt_arch_prefix}strings" "$kernel" | grep -Fw -e 'IBRS_FW' | head -1)
				if [ -n "$ibrs_supported" ]; then
					_debug "ibrs: encontrou evidências de ibrs na imagem do kernel ($ibrs_supported)"
					ibrs_supported="encontrado '$ibrs_supported' na imagem do kernel"
				fi
			fi
		fi
		if [ -z "$ibrs_supported" ] && [ -n "$opt_map" ]; then
			ibrs_can_tell=1
			if grep -q spec_ctrl "$opt_map"; then
				ibrs_supported="encontrado spec_ctrl no arquivo de símbolos"
				_debug "ibrs: encontrado o símbolo '*spec_ctrl*' em $opt_map"
			fi
		fi
		# recent (4.15) vanilla kernels have IBPB but not IBRS, and without the debugfs tunables of Red Hat
		# we can detect it directly in the image
		if [ -z "$ibpb_supported" ] && [ -n "$kernel" ]; then
			if ! command -v "${opt_arch_prefix}strings" >/dev/null 2>&1; then
				:
			else
				ibpb_can_tell=1
				ibpb_supported=$("${opt_arch_prefix}strings" "$kernel" | grep -Fw -e 'ibpb' -e ', IBPB' | head -1)
				if [ -n "$ibpb_supported" ]; then
					_debug "ibpb: encontrou evidências ibpb na imagem do kernel ($ibpb_supported)"
					ibpb_supported="encontrado '$ibpb_supported' na imagem do kernel"
				fi
			fi
		fi

		_info_nol "  * O kernel é compilado com o suporte do IBRS: "
		if [ -z "$ibrs_supported" ]; then
			if [ "$ibrs_can_tell" = 1 ]; then
				pstatus yellow NÃO
			else
				# problem obtaining/inspecting kernel or strings not installed, but if the later is true,
				# then readelf is not installed either (both in binutils) which makes the former true, so
				# either way kernel_err should be set
				pstatus yellow DESCONHECIDO "não pude verificar ($kernel_err)"
			fi
		else
			if [ "$opt_verbose" -ge 2 ]; then
				pstatus green SIM "$ibrs_supported"
			else
				pstatus green SIM
			fi
		fi

		_info_nol "    * IBRS ativado e ativo: "
		if [ "$opt_live" = 1 ]; then
			if [ "$ibpb_enabled" = 2 ]; then
				# if ibpb=2, ibrs is forcefully=0
				pstatus blue NÃO "IBPB usado em vez do IBRS em todos os pontos de entrada do kernel"
			else
				# 0 means disabled
				# 1 is enabled only for kernel space
				# 2 is enabled for kernel and user space
				# 3 is enabled
				# 4 is enhanced ibrs enabled
				case "$ibrs_enabled" in
					0)
						if [ "$ibrs_fw_enabled" = 1 ]; then
							pstatus blue SIM "apenas para código de firmware"
						else
							pstatus yellow NÃO
						fi
						;;
					1)	if [ "$ibrs_fw_enabled" = 1 ]; then pstatus green SIM "para espaço no kernel e código de firmware"; else pstatus green SIM "para espaço no kernel"; fi;;
					2)	if [ "$ibrs_fw_enabled" = 1 ]; then pstatus green SIM "para kernel, espaço do usuário e código de firmware" ; else pstatus green SIM "para o kernel e o espaço do usuário"; fi;;
					3)	if [ "$ibrs_fw_enabled" = 1 ]; then pstatus green SIM "para código de kernel e firmware"; else pstatus green SIM; fi;;
					4)	pstatus green SIM "Sabor aprimorado, o impacto no desempenho será bastante reduzido";;
					*)	if [ "$cpuid_ibrs" != 'SPEC_CTRL' ] && [ "$cpuid_ibrs" != 'IBRS_SUPPORT' ] && [ "$cpuid_spec_ctrl" != -1 ]; 
							then pstatus yellow NÃO; _debug "ibrs: CPU conhecida que não suporta SPEC-CTRL ou IBRS";
						else 
							pstatus yellow DESCONHECIDO; fi;;
				esac
			fi
		else
			pstatus blue N/A "não testável no modo offline"
		fi

		_info_nol "  * O kernel é compilado com suporte ao IBPB: "
		if [ -z "$ibpb_supported" ]; then
			if [ "$ibpb_can_tell" = 1 ]; then
				pstatus yellow NÃO
			else
				# if we're in offline mode without System.map, we can't really know
				pstatus yellow DESCONHECIDO "no modo offline, precisamos da imagem do kernel para poder dizer"
			fi
		else
			if [ "$opt_verbose" -ge 2 ]; then
				pstatus green SIM "$ibpb_supported"
			else
				pstatus green SIM
			fi
		fi

		_info_nol "    * IBPB ativado e ativo: "
		if [ "$opt_live" = 1 ]; then
			case "$ibpb_enabled" in
				"")
					if [ "$ibrs_supported" = 1 ]; then
						pstatus yellow DESCONHECIDO
					else
						pstatus yellow NÃO
					fi
					;;
				0)
					pstatus yellow NÃO
					;;
				1) pstatus green SIM;;
				2) pstatus green SIM "IBPB usado em vez do IBRS em todos os pontos de entrada do kernel";;
				*) pstatus yellow DESCONHECIDO;;
			esac
		else
			pstatus blue N/A "não testável no modo offline"
		fi

		_info "* Mitigação 2"
		_info_nol "  * Kernel tem proteção do preditor de ramificação (arm): "
		bp_harden_can_tell=0
		bp_harden=''
		if [ -r "$opt_config" ]; then
			bp_harden_can_tell=1
			bp_harden=$(grep -w 'CONFIG_HARDEN_BRANCH_PREDICTOR=y' "$opt_config")
			if [ -n "$bp_harden" ]; then
				pstatus green SIM
				_debug "bp_harden: encontrado '$bp_harden' em $opt_config"
			fi
		fi
		if [ -z "$bp_harden" ] && [ -n "$opt_map" ]; then
			bp_harden_can_tell=1
			bp_harden=$(grep -w bp_hardening_data "$opt_map")
			if [ -n "$bp_harden" ]; then
				pstatus green SIM
				_debug "bp_harden: encontrado '$bp_harden' em $opt_map"
			fi
		fi
		if [ -z "$bp_harden" ]; then
			if [ "$bp_harden_can_tell" = 1 ]; then
				pstatus yellow NÃO
			else
				pstatus yellow DESCONHECIDO
			fi
		fi

		_info_nol "  * Kernel compilado com a opção retpoline: "
		# We check the RETPOLINE kernel options
		retpoline=0
		if [ -r "$opt_config" ]; then
			if grep -q '^CONFIG_\(MITIGATION_\)\?RETPOLINE=y' "$opt_config"; then
				pstatus green SIM
				retpoline=1
				# shellcheck disable=SC2046
				_debug 'retpoline: encontrado '$(grep '^CONFIG_\(MITIGATION_\)\?RETPOLINE' "$opt_config")" em $opt_config"
			else
				pstatus yellow NÃO
			fi
		else
			pstatus yellow DESCONHECIDO "não conseguiu ler a configuração do seu kernel"
		fi

		if [ "$retpoline" = 1 ]; then
			# Now check if the compiler used to compile the kernel knows how to insert retpolines in generated asm
			# For gcc, this is -mindirect-branch=thunk-extern (detected by the kernel makefiles)
			# See gcc commit https://github.com/hjl-tools/gcc/commit/23b517d4a67c02d3ef80b6109218f2aadad7bd79
			# In latest retpoline LKML patches, the noretpoline_setup symbol exists only if CONFIG_MITIGATION_RETPOLINE is set
			# *AND* if the compiler is retpoline-compliant, so look for that symbol. The name of this kernel config 
			# option before version 6.9-rc1 is CONFIG_RETPOLINE.
			#
			# if there is "retpoline" in the file and NOT "minimal", then it's full retpoline
			# (works for vanilla and Red Hat variants)
			#
			# since 5.15.28, this is now "Retpolines" as the implementation was switched to a generic one,
			# so we look for both "retpoline" and "retpolines"
			if [ "$opt_live" = 1 ] && [ -n "$fullmsg" ]; then
				if echo "$fullmsg" | grep -qwi -e retpoline -e retpolines; then
					if echo "$fullmsg" | grep -qwi minimal; then
						retpoline_compiler=0
						retpoline_compiler_reason="O kernel relata compilação mínima de retpoline"
					else
						retpoline_compiler=1
						retpoline_compiler_reason="relatórios do kernel compilação completa do retpoline"
					fi
				fi
			elif [ -n "$opt_map" ]; then
				# look for the symbol
				if grep -qw noretpoline_setup "$opt_map"; then
					retpoline_compiler=1
					retpoline_compiler_reason="símbolo noretpoline_setup encontrado em System.map"
				fi
			elif [ -n "$kernel" ]; then
				# look for the symbol
				if command -v "${opt_arch_prefix}nm" >/dev/null 2>&1; then
					# the proper way: use nm and look for the symbol
					if "${opt_arch_prefix}nm" "$kernel" 2>/dev/null | grep -qw 'noretpoline_setup'; then
						retpoline_compiler=1
						retpoline_compiler_reason="noretpoline_setup encontrado nos símbolos do kernel"
					fi
				elif grep -q noretpoline_setup "$kernel"; then
					# if we don't have nm, nevermind, the symbol name is long enough to not have
					# any false positive using good old grep directly on the binary
					retpoline_compiler=1
					retpoline_compiler_reason="noretpoline_setup encontrado no kernel"
				fi
			fi
			if [ -n "$retpoline_compiler" ]; then
				_info_nol "    * Kernel compilado com um compilador compatível com retpoline: "
				if [ "$retpoline_compiler" = 1 ]; then
					if [ -n "$retpoline_compiler_reason" ]; then
						pstatus green SIM "$retpoline_compiler_reason"
					else
						pstatus green SIM
					fi
				else
					if [ -n "$retpoline_compiler_reason" ]; then
						pstatus red NÃO "$retpoline_compiler_reason"
					else
						pstatus red NÃO
					fi
				fi
			fi
		fi

		# only Red Hat has a tunable to disable it on runtime
		retp_enabled=-1
		if [ "$opt_live" = 1 ]; then
			if [ -e "$specex_knob_dir/retp_enabled" ]; then
				retp_enabled=$(cat "$specex_knob_dir/retp_enabled" 2>/dev/null)
				_debug "retpoline: encontrado $specex_knob_dir/retp_enabled=$retp_enabled"
				_info_nol "    * Retpoline está ativado: "
				if [ "$retp_enabled" = 1 ]; then
					pstatus green SIM
				else
					pstatus yellow NÃO
				fi
			fi
		fi

		# only for information, in verbose mode
		if [ "$opt_verbose" -ge 2 ]; then
			_info_nol "    * O gcc local reconhece a retpolina: "
			if command -v gcc >/dev/null 2>&1; then
				if [ -n "$(gcc -mindirect-branch=thunk-extern --version 2>&1 >/dev/null)" ]; then
					pstatus blue NÃO
				else
					pstatus green SIM
				fi
			else
				pstatus blue NÃO "O gcc não está instalado"
			fi
		fi

		if is_vulnerable_to_empty_rsb || [ "$opt_verbose" -ge 2 ]; then
			_info_nol "  * O kernel suporta o preenchimento de RSB: "
			rsb_filling=0
			if [ "$opt_live" = 1 ] && [ "$opt_no_sysfs" != 1 ]; then
				# if we're live and we aren't denied looking into /sys, let's do it
				if echo "$msg" | grep -qw RSB; then
					rsb_filling=1
					pstatus green SIM
				fi
			fi
			if [ "$rsb_filling" = 0 ]; then
				if [ -n "$kernel_err" ]; then
					pstatus yellow DESCONHECIDO "não pude verificar ($kernel_err)"
				else
					if grep -qw -e 'Filling RSB on context switch' "$kernel"; then
						rsb_filling=1
						pstatus green SIM
					else
						rsb_filling=0
						pstatus yellow NÃO
					fi
				fi
			fi
		fi

	elif [ "$sys_interface_available" = 0 ]; then
		# we have no sysfs but were asked to use it only!
		msg="interface de vulnerabilidade /sys usada forçada, mas não está disponível!"
		status=DESCONHECIDO
	fi

	if ! is_cpu_affected "$cve"; then
		# override status & msg in case CPU is not vulnerable after all
		pvulnstatus $cve OK "seu fornecedor de CPU relatou que seu modelo de CPU como não afetado"
	else
		if [ "$retpoline" = 1 ] && [ "$retpoline_compiler" = 1 ] && [ "$retp_enabled" != 0 ] && [ -n "$ibpb_enabled" ] && [ "$ibpb_enabled" -ge 1 ] && ( ! is_vulnerable_to_empty_rsb || [ "$rsb_filling" = 1 ] ); then
			pvulnstatus $cve OK "Retpoline completo + IBPB estão mitigando a vulnerabilidade"
		elif [ "$retpoline" = 1 ] && [ "$retpoline_compiler" = 1 ] && [ "$retp_enabled" != 0 ] && [ "$opt_paranoid" = 0 ] && ( ! is_vulnerable_to_empty_rsb || [ "$rsb_filling" = 1 ] ); then
			pvulnstatus $cve OK "A retpolina completa está atenuando a vulnerabilidade"
			if [ -n "$cpuid_ibpb" ]; then
				_warn "Você deve permitir que o IBPB complete a retpolina como uma mitigação da Variante 2"
			else
				_warn "O IBPB é considerado um bom complemento ao retpoline para mitigação da Variante 2, mas o microcódigo da CPU não o suporta"
			fi
		elif [ -n "$ibrs_enabled" ] && [ -n "$ibpb_enabled" ] && [ "$ibrs_enabled" -ge 1 ] && [ "$ibpb_enabled" -ge 1 ]; then
			if [ "$ibrs_enabled" = 4 ]; then
				pvulnstatus $cve OK "IBRS + IBPB aprimorados estão mitigando a vulnerabilidade"
			else
				pvulnstatus $cve OK "IBRS + IBPB estão mitigando a vulnerabilidade"
			fi
		elif [ "$ibpb_enabled" = 2 ] && ! is_cpu_smt_enabled; then
			pvulnstatus $cve OK "O IBPB completo está mitigando a vulnerabilidade"
		elif [ -n "$bp_harden" ]; then
			pvulnstatus $cve OK "O reforço do preditor de ramificação atenua a vulnerabilidade"
		elif [ -z "$bp_harden" ] && [ "$cpu_vendor" = ARM ]; then
			pvulnstatus $cve VULNERÁVEL "O fortalecimento do preditor de ramificação é necessário para reduzir a vulnerabilidade"
			explain "Seu kernel não foi compilado com a opção CONFIG_UNMAP_KERNEL_AT_EL0, recompile-o com esta opção ativada."
		elif [ "$opt_live" != 1 ]; then
			if [ "$retpoline" = 1 ] && [ -n "$ibpb_supported" ]; then
				pvulnstatus $cve OK "modo offline: o kernel suporta retpoline + IBPB para atenuar a vulnerabilidade"
			elif [ -n "$ibrs_supported" ] && [ -n "$ibpb_supported" ]; then
				pvulnstatus $cve OK "modo offline: o kernel suporta IBRS + IBPB para atenuar a vulnerabilidade"
			elif [ "$ibrs_can_tell" != 1 ]; then
				pvulnstatus $cve DESCONHECIDO "modo offline: informações insuficientes"
				explain "Execute novamente este script com privilégios de root e forneça a imagem do kernel (--kernel), a configuração do kernel (--config) e o arquivo System.map (--map) correspondente ao kernel que você deseja inspecionar."
			fi
		fi

		# if we arrive here and didn't already call pvulnstatus, then it's VULN, let's explain why
		if [ "$pvulnstatus_last_cve" != "$cve" ]; then
			# explain what's needed for this CPU
			if is_vulnerable_to_empty_rsb; then
				pvulnstatus $cve VULNERÁVEL "IBRS + IBPB ou retpoline + IBPB + preenchimento de RSB são necessários para atenuar a vulnerabilidade"
				explain "Para mitigar essa vulnerabilidade, você precisa de IBRS + IBPB, ambos exigindo suporte de hardware do microcódigo da CPU além do suporte de kernel, ou um kernel compilado com retpoline e IBPB, com retpoline exigindo um compilador com reconhecimento de retpoline (execute novamente este script com -v para saber se sua versão do gcc é compatível com retpoline) e o IBPB requer suporte de hardware do microcódigo da CPU. Você também precisa de um kernel recente o suficiente que suporte o preenchimento RSB se planeja usar retpoline. Para CPUs Skylake+, a abordagem IBRS + IBPB é geralmente preferida, pois garante proteção completa e o impacto no desempenho não é tão alto quanto com CPUs mais antigas em comparação com retpoline. Mais informações sobre como habilitar os bits ausentes para essas duas possíveis mitigações em seu sistema seguem. Você só precisa tomar uma das duas abordagens."
			elif is_zen_cpu || is_moksha_cpu; then
				pvulnstatus $cve VULNERÁVEL "retpoline + IBPB é necessário para atenuar a vulnerabilidade"
				explain "Para atenuar essa vulnerabilidade, você precisa de um kernel compilado com suporte ao retpoline + IBPB, com o retpoline exigindo um compilador com reconhecimento de retpoline (execute novamente esse script com -v para saber se sua versão do gcc é compatível com retpoline) e o IBPB exigindo suporte de hardware do seu microcódigo da CPU."
			elif is_intel || is_amd || is_hygon; then
				pvulnstatus $cve VULNERÁVEL "IBRS + IBPB ou retpoline + IBPB são necessários para atenuar a vulnerabilidade"
				explain "Para mitigar essa vulnerabilidade, você precisa do IBRS + IBPB, que requer suporte de hardware do microcódigo da CPU, além do suporte ao kernel, ou um kernel compilado com retpoline e IBPB, com o retpoline exigindo um compilador compatível com retpoline (execute novamente este script com -v para saber se sua versão do gcc é compatível com retpoline) e o IBPB que requer suporte de hardware do microcódigo da CPU. A abordagem retpolina + IBPB é geralmente preferida, pois o impacto no desempenho é menor. Mais informações sobre como habilitar os bits ausentes para essas duas possíveis mitigações em seu sistema seguem. Você só precisa seguir uma das duas abordagens."
			else
				# in that case, we might want to trust sysfs if it's there
				if [ -n "$msg" ]; then
					[ "$msg" = Vulnerable ] && msg="não existe mitigação conhecida para o fornecedor da CPU ($cpu_vendor)"
					pvulnstatus $cve $status "$msg"
				else
					pvulnstatus $cve VULNERÁVEL "não existe mitigação conhecida para o fornecedor da CPU ($cpu_vendor)"
				fi
			fi
		fi

		# if we are in live mode, we can check for a lot more stuff and explain further
		if [ "$opt_live" = 1 ] && [ "$vulnstatus" != "OK" ]; then
			_explain_hypervisor="Um microcódigo de CPU atualizado terá os recursos IBRS/IBPB indicados na seção Verificação de Hardware acima. Se você estiver executando em um hypervisor (KVM, Xen, VirtualBox, VMware, ...), o hypervisor precisará estar atualizado para poder exportar os novos sinalizadores da CPU do host para o convidado. Você pode executar este script no host para verificar se a CPU do host é IBRS/IBPB. Se for, e não aparecer no convidado, atualize o hypervisor. Pode ser necessário reconfigurar sua VM para usar um modelo de CPU com capacidade de IBRS; no Libvirt, essas CPUs são listadas com um sufixo IBRS."
			# IBPB (amd & intel)
			if { [ -z "$ibpb_enabled" ] || [ "$ibpb_enabled" = 0 ]; } && { is_intel || is_amd || is_hygon; }; then
				if [ -z "$cpuid_ibpb" ]; then
					explain "O microcódigo da sua CPU precisa ser atualizado para poder usar o IBPB. Isso geralmente é feito no momento da inicialização pelo seu kernel (a atualização não é persistente nas reinicializações, e é por isso que é feita em cada inicialização). Se você estiver usando uma distribuição, verifique se está atualizado, pois as atualizações de microcódigo geralmente são enviadas juntamente com o kernel da distribuição. A disponibilidade de uma atualização de microcódigo para o modelo da CPU depende do fornecedor da CPU. Geralmente, você pode descobrir on-line se uma atualização de microcódigo está disponível para sua CPU pesquisando seu CPUID (indicado na seção Verificação de Hardware). $_explain_hypervisor"
				fi
				if [ -z "$ibpb_supported" ]; then
					explain "Seu kernel não possui suporte IBPB, portanto, você precisa atualizar seu kernel (se estiver usando uma distribuição) ou recompilar um kernel mais recente."
				fi
				if [ -n "$cpuid_ibpb" ] && [ -n "$ibpb_supported" ]; then
					if [ -e "$specex_knob_dir/ibpb_enabled" ]; then
						# newer (April 2018) Red Hat kernels have ibpb_enabled as ro, and automatically enables it with retpoline
						if [ ! -w "$specex_knob_dir/ibpb_enabled" ] && [ -e "$specex_knob_dir/retp_enabled" ]; then
							explain "Sua CPU e seu kernel têm suporte a IBPB, mas atualmente está desativado. O kernel deve ativar o IBPB automaticamente se você ativar o retpoline. Você pode habilitá-lo com \`echo 1 > $specex_knob_dir/retp_enabled\`."
						else
							explain "Sua CPU e seu kernel têm suporte a IBPB, mas atualmente está desativado. Você pode habilitá-lo com \`echo 1 > $specex_knob_dir/ibpb_enabled\`."
						fi
					else
						explain "Sua CPU e seu kernel têm suporte a IBPB, mas atualmente está desativado. Você pode habilitá-lo. Verifique a documentação da sua distribuição sobre como fazer isso."
					fi
				fi
			elif [ "$ibpb_enabled" = 2 ] && is_cpu_smt_enabled; then
				explain "Você definiu ibpb_enabled como 2, mas ele oferece proteção suficiente apenas quando a multithread simultânea (também conhecida como SMT ou HyperThreading) está desativada. Você deve reiniciar o sistema com o parâmetro do kernel \`nosmt\`."
			fi
			# /IBPB

			# IBRS (amd & intel)
			if { [ -z "$ibrs_enabled" ] || [ "$ibrs_enabled" = 0 ]; } && { is_intel || is_amd || is_hygon; }; then
				if [ -z "$cpuid_ibrs" ]; then
					explain "O microcódigo da sua CPU precisa ser atualizado para poder usar o IBRS. Isso geralmente é feito no momento da inicialização pelo seu kernel (a atualização não é persistente nas reinicializações, e é por isso que é feita em cada inicialização). Se você estiver usando uma distribuição, verifique se está atualizado, pois as atualizações de microcódigo geralmente são enviadas juntamente com o kernel da distribuição. A disponibilidade de uma atualização de microcódigo para o modelo da CPU depende do fornecedor da CPU. Geralmente, você pode descobrir on-line se uma atualização de microcódigo está disponível para sua CPU pesquisando seu CPUID (indicado na seção Verificação de Hardware). $_explain_hypervisor"
				fi
				if [ -z "$ibrs_supported" ]; then
					explain "Seu kernel não possui suporte para IBRS, portanto, você precisa atualizar seu kernel (se estiver usando uma distribuição) ou recompilar um kernel mais recente."
				fi
				if [ -n "$cpuid_ibrs" ] && [ -n "$ibrs_supported" ]; then
					if [ -e "$specex_knob_dir/ibrs_enabled" ]; then
						explain "Sua CPU e seu kernel têm suporte para IBRS, mas atualmente está desativado. Você pode habilitá-lo com \`echo 1 > $specex_knob_dir/ibrs_enabled\`."
					else
						explain "Sua CPU e seu kernel têm suporte para IBRS, mas atualmente está desativado. Você pode habilitá-lo. Verifique a documentação da sua distribuição sobre como fazer isso."
					fi
				fi
			fi
			# /IBRS
			unset _explain_hypervisor

			# RETPOLINE (amd & intel &hygon )
			if is_amd || is_intel || is_hygon; then
				if [ "$retpoline" = 0 ]; then
					explain "Seu kernel não é compilado com suporte a retpoline, então você precisa atualizar seu kernel (se estiver usando uma distro) ou recompilar seu kernel com a opção CONFIG_MITIGATION_RETPOLINE habilitada (era chamado CONFIG_RETPOLINE antes do kernel 6.9-rc1). Você também precisa compilar seu kernel com um compilador compatível com retpoline (execute novamente este script com -v para saber se sua versão do gcc é compatível com retpoline)."
				elif [ "$retpoline" = 1 ] && [ "$retpoline_compiler" = 0 ]; then
					explain "Seu kernel é compilado com retpoline, mas sem um compilador com reconhecimento de retpoline (execute novamente esse script com -v para saber se sua versão do gcc tem reconhecimento de retpoline)."
				elif [ "$retpoline" = 1 ] && [ "$retpoline_compiler" = 1 ] && [ "$retp_enabled" = 0 ]; then
					explain "Seu kernel possui suporte a retpoline e foi compilado com um compilador compatível com retpoline, mas o retpoline está desabilitado. Você deve habilitá-lo com \`echo 1 > $specex_knob_dir/retp_enabled\`."
				fi
			fi
			# /RETPOLINE
		fi
	fi
	# sysfs msgs:
	#1 "Vulnerable"
	#2 "Vulnerable: Minimal generic ASM retpoline"
	#2 "Vulnerable: Minimal AMD ASM retpoline"
	# "Mitigation: Full generic retpoline"
	# "Mitigation: Full AMD retpoline"
	# $MITIGATION + ", IBPB"
	# $MITIGATION + ", IBRS_FW"
	#5 $MITIGATION + " - vulnerable module loaded"
	# Red Hat only:
	#2 "Vulnerable: Minimal ASM retpoline",
	#3 "Vulnerable: Retpoline without IBPB",
	#4 "Vulnerable: Retpoline on Skylake+",
	#5 "Vulnerable: Retpoline with unsafe module(s)",
	# "Mitigation: Full retpoline",
	# "Mitigation: Full retpoline and IBRS (user space)",
	# "Mitigation: IBRS (kernel)",
	# "Mitigation: IBRS (kernel and user space)",
	# "Mitigation: IBP disabled",
}

check_CVE_2017_5715_bsd()
{
	_info     "* Mitigação 1"
	_info_nol "  * Kernel suporta IBRS: "
	ibrs_disabled=$(sysctl -n hw.ibrs_disable 2>/dev/null)
	if [ -z "$ibrs_disabled" ]; then
		pstatus yellow NÃO
	else
		pstatus green SIM
	fi

	_info_nol "  * IBRS ativado e ativo: "
	ibrs_active=$(sysctl -n hw.ibrs_active 2>/dev/null)
	if [ "$ibrs_active" = 1 ]; then
		pstatus green SIM
	else
		pstatus yellow NÃO
	fi

	_info     "* Mitigação 2"
	_info_nol "  * Kernel compilado com RETPOLINE: "
	retpoline=0
	if [ -n "$kernel_err" ]; then
		pstatus yellow DESCONHECIDO "não pude verificar ($kernel_err)"
	else
		if ! command -v "${opt_arch_prefix}readelf" >/dev/null 2>&1; then
			pstatus yellow DESCONHECIDO "faltando a ferramenta '${opt_arch_prefix}readelf', instale-a, geralmente está no pacote binutils"
		else
			nb_thunks=$("${opt_arch_prefix}readelf" -s "$kernel" | grep -c -e __llvm_retpoline_ -e __llvm_external_retpoline_ -e __x86_indirect_thunk_)
			if [ "$nb_thunks" -gt 0 ]; then
				retpoline=1
				pstatus green SIM "encontrado $nb_thunks thunk(s)"
			else
				pstatus yellow NÃO
			fi
		fi
	fi

	if ! is_cpu_affected "$cve"; then
		# override status & msg in case CPU is not vulnerable after all
		pvulnstatus $cve OK "seu fornecedor de CPU relatou que seu modelo de CPU como não afetado"
	elif [ "$retpoline" = 1 ]; then
		pvulnstatus $cve OK "Retpoline atenua a vulnerabilidade"
	elif [ "$ibrs_active" = 1 ]; then
		pvulnstatus $cve OK "IBRS atenua a vulnerabilidade"
	elif [ "$ibrs_disabled" = 0 ]; then
		pvulnstatus $cve VULNERÁVEL "O IBRS é suportado pelo seu kernel, mas o microcódigo da CPU não possui suporte"
		explain "O microcódigo da sua CPU precisa ser atualizado para poder usar o IBRS. A disponibilidade de uma atualização de microcódigo para o modelo da CPU depende do fornecedor da CPU. Geralmente, você pode descobrir on-line se uma atualização de microcódigo está disponível para sua CPU pesquisando seu CPUID (indicado na seção Verificação de Hardware). Para fazer uma atualização de microcódigo, você pode procurar nas portas a ferramenta \`cpupdate\`. As atualizações de microcódigo feitas dessa maneira não são à prova de reinicialização, portanto, faça isso sempre que o sistema inicializar."
	elif [ "$ibrs_disabled" = 1 ]; then
		pvulnstatus $cve VULNERÁVEL "O IBRS é suportado, mas desativado administrativamente em seu sistema"
		explain "Para ativar o IBRS, use \`sysctl hw.ibrs_disable=0\`"
	else
		pvulnstatus $cve VULNERÁVEL "O IBRS é necessário para atenuar a vulnerabilidade, mas seu suporte está ausente"
		explain "Você precisa atualizar seu kernel ou recompilar uma versão mais recente com suporte ao IBRS"
	fi
}

##################
# MELTDOWN SECTION

# no security impact but give a hint to the user in verbose mode
# about PCID/INVPCID cpuid features that must be present to avoid
# too big a performance impact with PTI
# refs:
# https://marc.info/?t=151532047900001&r=1&w=2
# https://groups.google.com/forum/m/#!topic/mechanical-sympathy/L9mHTbeQLNU
pti_performance_check()
{
	_info_nol "  * Impacto reduzido no desempenho da PTI: "
	if [ -e "$procfs/cpuinfo" ] && grep ^flags "$procfs/cpuinfo" | grep -qw pcid; then
		cpu_pcid=1
	else
		read_cpuid 0x1 0x0 $ECX 17 1 1; ret=$?
		if [ $ret = $READ_CPUID_RET_OK ]; then
			cpu_pcid=1
		fi
	fi

	if [ -e "$procfs/cpuinfo" ] && grep ^flags "$procfs/cpuinfo" | grep -qw invpcid; then
		cpu_invpcid=1
	else
		read_cpuid 0x7 0x0 $EBX 10 1 1; ret=$?
		if [ $ret = $READ_CPUID_RET_OK ]; then
			cpu_invpcid=1
		fi
	fi

	if [ "$cpu_invpcid" = 1 ]; then
		pstatus green SIM 'CPU suporta INVPCID, o impacto no desempenho da PTI será bastante reduzido'
	elif [ "$cpu_pcid" = 1 ]; then
		pstatus green SIM 'CPU suporta PCID, o impacto no desempenho da PTI será reduzido'
	else
		pstatus blue NÃO 'PCID/INVPCID não suportado, o impacto no desempenho da PTI será significativo'
	fi
}

# rogue data cache load aka 'Meltdown' aka 'Variant 3'
check_CVE_2017_5754()
{
	cve='CVE-2017-5754'
	_info "\033[1;34m$cve também conhecido como '$(cve2name "$cve")'\033[0m"
	if [ "$os" = Linux ]; then
		check_CVE_2017_5754_linux
	elif echo "$os" | grep -q BSD; then
		check_CVE_2017_5754_bsd
	else
		_warn "SO não suportado ($os)"
	fi
}

check_CVE_2017_5754_linux()
{
	status=DESCONHECIDO
	sys_interface_available=0
	msg=''
	if sys_interface_check "/sys/devices/system/cpu/vulnerabilities/meltdown"; then
		# this kernel has the /sys interface, trust it over everything
		sys_interface_available=1
	fi
	if [ "$opt_sysfs_only" != 1 ]; then
		_info_nol "* O kernel suporta isolamento de tabela de páginas (PTI): "
		kpti_support=''
		kpti_can_tell=0
		if [ -n "$opt_config" ]; then
			kpti_can_tell=1
			kpti_support=$(grep -E -w -e 'CONFIG_(MITIGATION_)?PAGE_TABLE_ISOLATION=y' -e CONFIG_KAISER=y -e CONFIG_UNMAP_KERNEL_AT_EL0=y "$opt_config")
			if [ -n "$kpti_support" ]; then
				_debug "kpti_support: opção encontrada '$kpti_support' em $opt_config"
			fi
		fi
		if [ -z "$kpti_support" ] && [ -n "$opt_map" ]; then
			# it's not an elif: some backports don't have the PTI config but still include the patch
			# so we try to find an exported symbol that is part of the PTI patch in System.map
			# parse_kpti: arm
			kpti_can_tell=1
			kpti_support=$(grep -w -e kpti_force_enabled -e parse_kpti "$opt_map")
			if [ -n "$kpti_support" ]; then
				_debug "kpti_support: encontrado '$kpti_support' em $opt_map"
			fi
		fi
		if [ -z "$kpti_support" ] && [ -n "$kernel" ]; then
			# same as above but in case we don't have System.map and only kernel, look for the
			# nopti option that is part of the patch (kernel command line option)
			# 'kpti=': arm
			kpti_can_tell=1
			if ! command -v "${opt_arch_prefix}strings" >/dev/null 2>&1; then
				pstatus yellow DESCONHECIDO "faltando a ferramenta '${opt_arch_prefix}strings', instale-a, geralmente está no pacote binutils"
			else
				kpti_support=$("${opt_arch_prefix}strings" "$kernel" | grep -w -e nopti -e kpti=)
				if [ -n "$kpti_support" ]; then
					_debug "kpti_support: encontrado '$kpti_support' em $kernel"
				fi
			fi
		fi

		if [ -n "$kpti_support" ]; then
			if [ "$opt_verbose" -ge 2 ]; then
				pstatus green SIM "encontrado '$kpti_support'"
			else
				pstatus green SIM
			fi
		elif [ "$kpti_can_tell" = 1 ]; then
			pstatus yellow NÃO
		else
			pstatus yellow DESCONHECIDO "Não foi possível ler a configuração do kernel nem o arquivo System.map"
		fi

		mount_debugfs
		_info_nol "  * PTI ativado e ativo: "
		if [ "$opt_live" = 1 ]; then
			dmesg_grep="Kernel/User page tables isolation: enabled"
			dmesg_grep="$dmesg_grep|Kernel page table isolation enabled"
			dmesg_grep="$dmesg_grep|x86/pti: Unmapping kernel while in userspace"
			# aarch64
			dmesg_grep="$dmesg_grep|CPU features: detected( feature)?: Kernel page table isolation \(KPTI\)"
			if grep ^flags "$procfs/cpuinfo" | grep -qw pti; then
				# vanilla PTI patch sets the 'pti' flag in cpuinfo
				_debug "kpti_enabled: flag 'pti' encontrado em $procfs/cpuinfo"
				kpti_enabled=1
			elif grep ^flags "$procfs/cpuinfo" | grep -qw kaiser; then
				# kernel line 4.9 sets the 'kaiser' flag in cpuinfo
				_debug "kpti_enabled: encontrado o sinalizador 'kaiser' em $procfs/cpuinfo"
				kpti_enabled=1
			elif [ -e /sys/kernel/debug/x86/pti_enabled ]; then
				# Red Hat Backport creates a dedicated file, see https://access.redhat.com/articles/3311301
				kpti_enabled=$(cat /sys/kernel/debug/x86/pti_enabled 2>/dev/null)
				_debug "kpti_enabled: arquivo /sys/kernel/debug/x86/pti_enabled existe e diz: $kpti_enabled"
			elif is_xen_dom0; then
				pti_xen_pv_domU=$(xl dmesg | grep 'XPTI' | grep 'DomU enabled' | head -1)

				[ -n "$pti_xen_pv_domU" ] && kpti_enabled=1
			fi
			if [ -z "$kpti_enabled" ]; then
				dmesg_grep "$dmesg_grep"; ret=$?
				if [ $ret -eq 0 ]; then
					_debug "kpti_enabled: dica encontrada no dmesg: $dmesg_grepped"
					kpti_enabled=1
				elif [ $ret -eq 2 ]; then
					_debug "kpti_enabled: dmesg truncado"
					kpti_enabled=-1
				fi
			fi
			if [ -z "$kpti_enabled" ]; then
				_debug "kpti_enabled: não foi possível encontrar nenhuma dica de que a PTI está ativada"
				kpti_enabled=0
			fi
			if [ "$kpti_enabled" = 1 ]; then
				pstatus green SIM
			elif [ "$kpti_enabled" = -1 ]; then
				pstatus yellow DESCONHECIDO "dmesg truncado, reinicie e relançar este script"
			else
				pstatus yellow NÃO
			fi
		else
			pstatus blue N/A "não testável no modo offline"
		fi

		pti_performance_check

	elif [ "$sys_interface_available" = 0 ]; then
		# we have no sysfs but were asked to use it only!
		msg="uso da interface de vulnerabilidade /sys forçado, mas não está disponível!"
		status=DESCONHECIDO
	fi


	# Test if the current host is a Xen PV Dom0 / DomU
	xen_pv_domo=0
	xen_pv_domu=0
	is_xen_dom0 && xen_pv_domo=1
	is_xen_domU && xen_pv_domu=1

	if [ "$opt_live" = 1 ]; then
		# checking whether we're running under Xen PV 64 bits. If yes, we are affected by variant3
		# (unless we are a Dom0)
		_info_nol "* Executando como um Xen PV DomU: "
		if [ "$xen_pv_domu" = 1 ]; then
			pstatus yellow SIM
		else
			pstatus blue NÃO
		fi
	fi

	if ! is_cpu_affected "$cve"; then
		# override status & msg in case CPU is not vulnerable after all
		pvulnstatus $cve OK "o fornecedor da sua CPU relatou que o modelo da sua CPU não foi afetado"
	elif [ -z "$msg" ]; then
		# if msg is empty, sysfs check didn't fill it, rely on our own test
		if [ "$opt_live" = 1 ]; then
			if [ "$kpti_enabled" = 1 ]; then
				pvulnstatus $cve OK "PTI atenua a vulnerabilidade"
			elif [ "$xen_pv_domo" = 1 ]; then
				pvulnstatus $cve OK "Xen Dom0s são seguros e não exigem PTI"
			elif [ "$xen_pv_domu" = 1 ]; then
				pvulnstatus $cve VULNERÁVEL "As Xen PV DomUs são vulneráveis e precisam ser executadas no modo HVM, PVHVM, PVH ou o hipervisor Xen deve ter o próprio patch PTI do Xen"
				explain "Vá para https://blog.xenproject.org/2018/01/22/xen-project-spectre-meltdown-faq-jan-22-update/ para mais informações"
			elif [ "$kpti_enabled" = -1 ]; then
				pvulnstatus $cve DESCONHECIDO "não foi possível encontrar nenhuma pista da ativação da PTI devido a um dmesg truncado, reinicie e reinicie este script"
			else
				pvulnstatus $cve VULNERÁVEL "A PTI é necessária para atenuar a vulnerabilidade"
				if [ -n "$kpti_support" ]; then
					if [ -e "/sys/kernel/debug/x86/pti_enabled" ]; then
						explain "Seu kernel suporta PTI mas está desabilitado, você pode habilitá-lo com \`echo 1 > /sys/kernel/debug/x86/pti_enabled\`"
					elif echo "$kernel_cmdline" | grep -q -w -e nopti -e pti=off; then
						explain "Seu kernel suporta PTI, mas foi desabilitado na linha de comando, remova a opção nopti ou pti=off da configuração do bootloader"
					else
						explain "Seu kernel suporta PTI, mas foi desabilitado, verifique \`dmesg\` logo após a inicialização para encontrar pistas de por que o sistema o desabilitou"
					fi
				else
					explain "Se você estiver usando um kernel de distribuição, atualize sua distribuição para obter o kernel mais recente disponível. Caso contrário, recompile o kernel com a opção CONFIG_PAGE_TABLE_ISOLATION (chamada CONFIG_KAISER para alguns kernels) ou a opção CONFIG_UNMAP_KERNEL_AT_EL0 (para ARM64)"
				fi
			fi
		else
			if [ -n "$kpti_support" ]; then
				pvulnstatus $cve OK "modo offline: PTI irá mitigar a vulnerabilidade se ativado em tempo de execução"
			elif [ "$kpti_can_tell" = 1 ]; then
				pvulnstatus $cve VULNERÁVEL "PTI é necessária para mitigar a vulnerabilidade"
				explain "Se você estiver usando um kernel de distribuição, atualize sua distribuição para obter o kernel mais recente disponível. Caso contrário, recompile o kernel com a opção CONFIG_PAGE_TABLE_ISOLATION (chamada CONFIG_KAISER para alguns kernels) ou a opção CONFIG_UNMAP_KERNEL_AT_EL0 (para ARM64)"
			else
				pvulnstatus $cve DESCONHECIDO "modo offline: informações insuficientes"
				explain "Execute novamente este script com privilégios de root e forneça a imagem do kernel (--kernel), a configuração do kernel (--config) e o arquivo System.map (--map) correspondente ao kernel que você gostaria de inspecionar."
			fi
		fi
	else
		if [ "$xen_pv_domo" = 1 ]; then
			msg="Xen Dom0s são seguros e não requerem PTI"
			status="OK"
		elif [ "$xen_pv_domu" = 1 ]; then
			msg="Xen PV DomUs são vulneráveis e precisam ser executados no modo HVM, PVHVM, PVH ou o hipervisor Xen deve ter o próprio patch PTI do Xen"
			status="VULNERÁVEL"
			_explain="Vá para https://blog.xenproject.org/2018/01/22/xen-project-spectre-meltdown-faq-jan-22-update/ for more information"
		elif [ "$msg" = "Vulnerable" ]; then
			msg="PTI é necessária para mitigar a vulnerabilidade"
			_explain="Se você estiver usando um kernel de distribuição, atualize sua distribuição para obter o kernel mais recente disponível. Caso contrário, recompile o kernel com a opção CONFIG_PAGE_TABLE_ISOLATION (chamada CONFIG_KAISER para alguns kernels) ou a opção CONFIG_UNMAP_KERNEL_AT_EL0 (para ARM64)"
		fi
		pvulnstatus $cve "$status" "$msg"
		[ -z "${_explain:-}" ] && [ "$msg" = "Vulnerable" ] && _explain="Se você estiver usando um kernel de distribuição, atualize sua distribuição para obter o kernel mais recente disponível. Caso contrário, recompile o kernel com a opção CONFIG_PAGE_TABLE_ISOLATION (chamada CONFIG_KAISER para alguns kernels) ou a opção CONFIG_UNMAP_KERNEL_AT_EL0 (para ARM64)"
		[ -n "${_explain:-}" ] && explain "$_explain"
		unset _explain
	fi

	# Warn the user about XSA-254 recommended mitigations
	if [ "$xen_pv_domo" = 1 ]; then
		_warn
		_warn "Este host é um Xen Dom0. Por favor, certifique-se de que você está executando seus DomUs"
		_warn "no modo HVM, PVHVM ou PVH para evitar ataques de convidado a host / host a convidado."
		_warn
		_warn "Consulte https://blog.xenproject.org/2018/01/22/xen-project-spectre-meltdown-faq-jan-22-update/ e XSA-254 para detalhes."
	fi
}

check_CVE_2017_5754_bsd()
{
	_info_nol "* Kernel suporta isolamento de tabela de página (PTI): "
	kpti_enabled=$(sysctl -n vm.pmap.pti 2>/dev/null)
	if [ -z "$kpti_enabled" ]; then
		pstatus yellow NÃO
	else
		pstatus green SIM
	fi

	_info_nol "  * PTI ativado e ativo: "
	if [ "$kpti_enabled" = 1 ]; then
		pstatus green SIM
	else
		pstatus yellow NÃO
	fi

	pti_performance_check

	if ! is_cpu_affected "$cve"; then
		# override status & msg in case CPU is not vulnerable after all
		pvulnstatus $cve OK "seu fornecedor de CPU relatou que seu modelo de CPU não foi afetado"
	elif [ "$kpti_enabled" = 1 ]; then
		pvulnstatus $cve OK "PTI mitiga a vulnerabilidade"
	elif [ -n "$kpti_enabled" ]; then
		pvulnstatus $cve VULNERÁVEL "PTI é suportado, mas desativado em seu sistema"
	else
		pvulnstatus $cve VULNERÁVEL "A PTI é necessária para mitigar a vulnerabilidade"
	fi
}

####################
# VARIANT 3A SECTION

# rogue system register read aka 'Variant 3a'
check_CVE_2018_3640()
{
	cve='CVE-2018-3640'
	_info "\033[1;34m$cve também conhecido como '$(cve2name "$cve")'\033[0m"

	status=DESCONHECIDO
	sys_interface_available=0
	msg=''

	_info_nol "* O microcódigo da CPU reduz a vulnerabilidade: "
	if [ -n "$cpuid_ssbd" ]; then
		# microcodes that ship with SSBD are known to also fix variant3a
		# there is no specific cpuid bit as far as we know
		pstatus green SIM
	else
		pstatus yellow NÃO
	fi

	if ! is_cpu_affected "$cve"; then
		# override status & msg in case CPU is not vulnerable after all
		pvulnstatus $cve OK "seu fornecedor de CPU relatou que seu modelo de CPU como não afetado"
	elif [ -n "$cpuid_ssbd" ]; then
		pvulnstatus $cve OK "seu microcódigo da CPU reduz a vulnerabilidade"
	else
		pvulnstatus $cve VULNERÁVEL "é necessário um microcódigo de CPU atualizado para mitigar essa vulnerabilidade"
		explain "O microcódigo da sua CPU precisa ser atualizado para reduzir essa vulnerabilidade. Isso geralmente é feito no momento da inicialização pelo seu kernel (a atualização não é persistente nas reinicializações, e é por isso que é feita em cada inicialização). Se você estiver usando uma distribuição, verifique se está atualizado, pois as atualizações de microcódigo geralmente são enviadas juntamente com o kernel da distribuição. A disponibilidade de uma atualização de microcódigo para o modelo da CPU depende do fornecedor da CPU. Geralmente, você pode descobrir on-line se uma atualização de microcódigo está disponível para sua CPU pesquisando seu CPUID (indicado na seção Verificação de Hardware). A atualização do microcódigo é suficiente, não são necessárias alterações adicionais no SO, no kernel ou no software."
	fi
}

###################
# VARIANT 4 SECTION

# speculative store bypass aka 'Variant 4'
check_CVE_2018_3639()
{
	cve='CVE-2018-3639'
	_info "\033[1;34m$cve também conhecido como '$(cve2name "$cve")'\033[0m"
	if [ "$os" = Linux ]; then
		check_CVE_2018_3639_linux
	elif echo "$os" | grep -q BSD; then
		check_CVE_2018_3639_bsd
	else
		_warn "SO não suportado ($os)"
	fi
}

check_CVE_2018_3639_linux()
{
	status=DESCONHECIDO
	sys_interface_available=0
	msg=''
	if sys_interface_check "/sys/devices/system/cpu/vulnerabilities/spec_store_bypass"; then
		# this kernel has the /sys interface, trust it over everything
		sys_interface_available=1
	fi
	if [ "$opt_sysfs_only" != 1 ]; then
		_info_nol "* O kernel suporta a desativação do desvio de armazenamento especulativo (SSB): "
		if [ "$opt_live" = 1 ]; then
			if grep -Eq 'Speculation.?Store.?Bypass:' "$procfs/self/status" 2>/dev/null; then
				kernel_ssb="encontrado em $procfs/self/status"
				_debug "encontrado Speculation.Store.Bypass: em $procfs/self/status"
			fi
		fi
		# arm64 kernels can have cpu_show_spec_store_bypass with ARM64_SSBD, so exclude them
		if [ -z "$kernel_ssb" ] && [ -n "$kernel" ] && ! grep -q 'arm64_sys_' "$kernel"; then
			kernel_ssb=$("${opt_arch_prefix}strings" "$kernel" | grep spec_store_bypass | head -n1);
			[ -n "$kernel_ssb" ] && kernel_ssb="encontrado $kernel_ssb no kernel"
		fi
		# arm64 kernels can have cpu_show_spec_store_bypass with ARM64_SSBD, so exclude them
		if [ -z "$kernel_ssb" ] && [ -n "$opt_map" ] && ! grep -q 'arm64_sys_' "$opt_map"; then
			kernel_ssb=$(grep spec_store_bypass "$opt_map" | awk '{print $3}' | head -n1)
			[ -n "$kernel_ssb" ] && kernel_ssb="encontrado $kernel_ssb no System.map"
		fi
		# arm64 only:
		if [ -z "$kernel_ssb" ] && [ -n "$opt_map" ]; then
			kernel_ssb=$(grep -w cpu_enable_ssbs "$opt_map" | awk '{print $3}' | head -n1)
			[ -n "$kernel_ssb" ] && kernel_ssb="encontrado $kernel_ssb no System.map"
		fi
		if [ -z "$kernel_ssb" ] && [ -n "$opt_config" ]; then
			kernel_ssb=$(grep -w 'CONFIG_ARM64_SSBD=y' "$opt_config")
			[ -n "$kernel_ssb" ] && kernel_ssb="CONFIG_ARM64_SSBD habilitado em kconfig"
		fi
		if [ -z "$kernel_ssb" ] && [ -n "$kernel" ]; then
			# this string only appears in kernel if CONFIG_ARM64_SSBD is set
			kernel_ssb=$(grep -w "Especulative Store Bypassing Safe (SSBS)" "$kernel")
			[ -n "$kernel_ssb" ] && kernel_ssb="encontrado 'Especulative Store Bypassing Safe (SSBS)' no kernel"
		fi
		# /arm64 only

		if [ -n "$kernel_ssb" ]; then
			pstatus green SIM "$kernel_ssb"
		else
			pstatus yellow NÃO
		fi

		kernel_ssbd_enabled=-1
		if [ "$opt_live" = 1 ]; then
			# https://elixir.bootlin.com/linux/v5.0/source/fs/proc/array.c#L340
			_info_nol "* A mitigação de SSB está habilitada e ativa: "
			if grep -Eq 'Speculation.?Store.?Bypass:[[:space:]]+thread' "$procfs/self/status" 2>/dev/null; then
				kernel_ssbd_enabled=1
				pstatus green SIM "por thread por meio de prctl"
			elif grep -Eq 'Speculation.?Store.?Bypass:[[:space:]]+globally mitigated' "$procfs/self/status" 2>/dev/null; then
				kernel_ssbd_enabled=2
				pstatus green SIM "global"
			elif grep -Eq 'Speculation.?Store.?Bypass:[[:space:]]+vulnerable' "$procfs/self/status" 2>/dev/null; then
				kernel_ssbd_enabled=0
				pstatus yellow NÃO
			elif grep -Eq 'Speculation.?Store.?Bypass:[[:space:]]+not vulnerable' "$procfs/self/status" 2>/dev/null; then
				kernel_ssbd_enabled=-2
				pstatus blue NÃO "não vulnerável"
			elif grep -Eq 'Speculation.?Store.?Bypass:[[:space:]]+unknown' "$procfs/self/status" 2>/dev/null; then
				kernel_ssbd_enabled=0
				pstatus blue NÃO
			else
				pstatus blue DESCONHECIDO "valor desconhecido: $(grep -E 'Speculation.?Store.?Bypass:' "$procfs/self/status" 2>/dev/null | cut -d: -f2-)"
			fi

			if [ "$kernel_ssbd_enabled" = 1 ]; then
				_info_nol "* Mitigação de SSB atualmente ativa para processos selecionados: "
				# silence grep's stderr here to avoid ENOENT errors from processes that have exited since the shell's expansion of the *
				mitigated_processes=$(find /proc -mindepth 2 -maxdepth 2 -type f -name status -print0 2>/dev/null \
					| xargs -r0 grep -El 'Speculation.?Store.?Bypass:[[:space:]]+thread (force )?mitigated' 2>/dev/null \
					| sed s/status/exe/ | xargs -r -n1 readlink -f 2>/dev/null | xargs -r -n1 basename | sort -u | tr "\n" " " | sed 's/ $//')
				if [ -n "$mitigated_processes" ]; then
					pstatus green SIM "$mitigated_processes"
				else
					pstatus yellow NÃO "nenhum processo encontrado usando a mitigação de SSB por meio de prctl"
				fi
			fi
		fi

	elif [ "$sys_interface_available" = 0 ]; then
		# we have no sysfs but were asked to use it only!
		msg="uso da interface de vulnerabilidade /sys forçado, mas não está disponível!"
		status=DESCONHECIDO
	fi

	if ! is_cpu_affected "$cve"; then
		# override status & msg in case CPU is not vulnerable after all
		pvulnstatus $cve OK "seu fornecedor de CPU relatou que seu modelo de CPU como não afetado"
	elif [ -z "$msg" ] || [ "$msg" = "Vulnerable" ]; then
		# if msg is empty, sysfs check didn't fill it, rely on our own test
		if [ -n "$cpuid_ssbd" ]; then
			if [ -n "$kernel_ssb" ]; then
				if [ "$opt_live" = 1 ]; then
					if [ "$kernel_ssbd_enabled" -gt 0 ]; then
						pvulnstatus $cve OK "sua CPU e kernel suportam SSBD e a mitigação é ativada"
					else
						pvulnstatus $cve VULNERÁVEL "sua CPU e kernel suportam SSBD, mas a atenuação não está ativa"
					fi
				else
					pvulnstatus $cve OK "seu sistema fornece as ferramentas necessárias para mitigação de software"
				fi
			else
				pvulnstatus $cve VULNERÁVEL "seu kernel precisa ser atualizado"
				explain "Você tem um microcódigo de CPU recente o suficiente, mas seu kernel é muito antigo para usar os novos recursos exportados pelo microcódigo de sua CPU. Se você estiver usando um kernel de distribuição, atualize sua distribuição para obter o kernel mais recente disponível. Caso contrário, recompile o kernel de fontes recentes o suficiente."
			fi
		else
			if [ -n "$kernel_ssb" ]; then
				pvulnstatus $cve VULNERÁVEL "Sua CPU não suporta SSBD"
				explain "Seu kernel é recente o suficiente para usar os recursos de microcódigo da CPU para mitigação, mas o microcódigo da CPU não fornece os recursos necessários para o kernel usar. O microcódigo da sua CPU precisa, portanto, ser atualizado. Isso geralmente é feito no momento da inicialização pelo seu kernel (a atualização não é persistente nas reinicializações, e é por isso que é feita em cada inicialização). Se você estiver usando uma distribuição, verifique se está atualizado, pois as atualizações de microcódigo geralmente são enviadas juntamente com o kernel da distribuição. A disponibilidade de uma atualização de microcódigo para o modelo da CPU depende do fornecedor da CPU. Geralmente, você pode descobrir on-line se uma atualização de microcódigo está disponível para sua CPU pesquisando seu CPUID (indicado na seção Verificação de Hardware)."
			else
				pvulnstatus $cve VULNERÁVEL "Nem sua CPU nem seu kernel suportam SSBD"
				explain "O microcódigo da CPU e o kernel estão sem suporte para mitigação. Se você estiver usando um kernel de distribuição, atualize sua distribuição para obter o kernel mais recente disponível. Caso contrário, recompile o kernel de fontes recentes o suficiente. O microcódigo da sua CPU também precisa ser atualizado. Isso geralmente é feito no momento da inicialização pelo seu kernel (a atualização não é persistente nas reinicializações, e é por isso que é feita em cada inicialização). Se você estiver usando uma distribuição, verifique se está atualizado, pois as atualizações de microcódigo geralmente são enviadas juntamente com o kernel da distribuição. A disponibilidade de uma atualização de microcódigo para o modelo da CPU depende do fornecedor da CPU. Geralmente, você pode descobrir on-line se uma atualização de microcódigo está disponível para sua CPU pesquisando seu CPUID (indicado na seção Verificação de Hardware)."
			fi
		fi
	else
		pvulnstatus $cve "$status" "$msg"
	fi
}

check_CVE_2018_3639_bsd()
{
	_info_nol "* O kernel suporta desvio de armazenamento de especulação: "
	if sysctl hw.spec_store_bypass_disable >/dev/null 2>&1; then
		kernel_ssb=1
		pstatus green SIM
	else
		kernel_ssb=0
		pstatus yellow NÃO
	fi

	_info_nol "* O desvio de armazenamento de especulação está ativado administrativamente: "
	ssb_enabled=$(sysctl -n hw.spec_store_bypass_disable 2>/dev/null)
	_debug "hw.spec_store_bypass_disable=$ssb_enabled"
	case "$ssb_enabled" in
		0) pstatus yellow NÃO "disabled";;
		1) pstatus green SIM "enabled";;
		2) pstatus green SIM "auto mode";;
		*) pstatus yellow NÃO "unavailable";;
	esac

	_info_nol "* O desvio de armazenamento de especulação está ativo no momento: "
	ssb_active=$(sysctl -n hw.spec_store_bypass_disable_active 2>/dev/null)
	_debug "hw.spec_store_bypass_disable_active=$ssb_active"
	case "$ssb_active" in
		1) pstatus green SIM;;
		*) pstatus yellow NÃO;;
	esac

	if ! is_cpu_affected "$cve"; then
		pvulnstatus $cve OK "seu fornecedor de CPU relatou que seu modelo de CPU como não afetado"
	else
		if [ "$ssb_active" = 1 ]; then
				pvulnstatus $cve OK "SSBD atenua a vulnerabilidade"
		elif [ -n "$cpuid_ssbd" ]; then
			if [ "$kernel_ssb" = 1 ]; then
				pvulnstatus $cve VULNERÁVEL "você precisa habilitar o SSBD por meio do sysctl para reduzir a vulnerabilidade"
				explain "Para ativar o SSBD agora, você pode executar \`sysctl hw.spec_store_bypass_disable=2'. Para tornar essa alteração persistente nas reinicializações, você pode adicionar 'sysctl hw.spec_store_bypass_disable=2' para /etc/sysctl.conf."
			else
				pvulnstatus $cve VULNERÁVEL "seu kernel precisa ser atualizado"
			fi
		else
			if [ "$kernel_ssb" = 1 ]; then
				pvulnstatus $cve VULNERÁVEL "Sua CPU não suporta SSBD"
			else
				pvulnstatus $cve VULNERÁVEL "Nem sua CPU nem seu kernel suportam SSBD"
			fi
		fi
	fi
}

###########################
# L1TF / FORESHADOW SECTION

# L1 terminal fault (SGX) aka 'Foreshadow'
check_CVE_2018_3615()
{
	cve='CVE-2018-3615'
	_info "\033[1;34m$cve também conhecido como '$(cve2name "$cve")'\033[0m"

	_info_nol "* O microcódigo da CPU reduz a vulnerabilidade: "
	if { [ "$cpu_flush_cmd" = 1 ] || { [ "$msr_locked_down" = 1 ] && [ "$cpuid_l1df" = 1 ]; }; } && [ "$cpuid_sgx" = 1 ]; then
		# no easy way to detect a fixed SGX but we know that
		# microcodes that have the FLUSH_CMD MSR also have the
		# fixed SGX (for CPUs that support it), because Intel
		# delivered fixed microcodes for both issues at the same time
		#
		# if the system we're running on is locked down (no way to write MSRs),
		# make the assumption that if the L1D flush CPUID bit is set, probably
		# that FLUSH_CMD MSR is here too
		pstatus green SIM
	elif [ "$cpuid_sgx" = 1 ]; then
		pstatus red NÃO
	else
		pstatus blue N/A
	fi

	if ! is_cpu_affected "$cve"; then
		# override status & msg in case CPU is not vulnerable after all
		pvulnstatus $cve OK "seu fornecedor de CPU relatou que seu modelo de CPU como não afetado"
	elif [ "$cpu_flush_cmd" = 1 ] || { [ "$msr_locked_down" = 1 ] && [ "$cpuid_l1df" = 1 ]; } ; then
		pvulnstatus $cve OK "seu microcódigo da CPU reduz a vulnerabilidade"
	else
		pvulnstatus $cve VULNERÁVEL "sua CPU suporta SGX e o microcódigo não está atualizado"
	fi
}

# L1 terminal fault (OS) aka 'Foreshadow-NG (OS)'
check_CVE_2018_3620()
{
	cve='CVE-2018-3620'
	_info "\033[1;34m$cve também conhecido como '$(cve2name "$cve")'\033[0m"
	if [ "$os" = Linux ]; then
		check_CVE_2018_3620_linux
	elif echo "$os" | grep -q BSD; then
		check_CVE_2018_3620_bsd
	else
		_warn "SO não suportado ($os)"
	fi
}

check_CVE_2018_3620_linux()
{
	status=DESCONHECIDO
	sys_interface_available=0
	msg=''
	if sys_interface_check "/sys/devices/system/cpu/vulnerabilities/l1tf"; then
		# this kernel has the /sys interface, trust it over everything
		sys_interface_available=1
	fi
	if [ "$opt_sysfs_only" != 1 ]; then
		_info_nol "* O kernel suporta inversão PTE: "
		if ! command -v "${opt_arch_prefix}strings" >/dev/null 2>&1; then
			pstatus yellow DESCONHECIDO "ferramenta 'strings' em falta, instale-a"
			pteinv_supported=-1
		elif [ -n "$kernel_err" ]; then
			pstatus yellow DESCONHECIDO "$kernel_err"
			pteinv_supported=-1
		else
			if "${opt_arch_prefix}strings" "$kernel" | grep -Fq 'Inversão PTE'; then
				pstatus green SIM "encontrado na imagem do kernel"
				_debug "pteinv: encontraram evidências de inversão de pte na imagem do kernel"
				pteinv_supported=1
			else
				pstatus yellow NÃO
				pteinv_supported=0
			fi
		fi

		_info_nol "* Inversão de PTE ativada e ativa: "
		if [ "$opt_live" = 1 ]; then
			if [ -n "$fullmsg" ]; then
				if echo "$fullmsg" | grep -q 'Mitigação: Inversão PTE'; then
					pstatus green SIM
					pteinv_active=1
				else
					pstatus yellow NÃO
					pteinv_active=0
				fi
			else
				pstatus yellow DESCONHECIDO "interface sysfs não disponível"
				pteinv_active=-1
			fi
		else
			pstatus blue N/A "não testável no modo offline"
		fi
	elif [ "$sys_interface_available" = 0 ]; then
		# we have no sysfs but were asked to use it only!
		msg="uso da interface de vulnerabilidade /sys forçado, mas não está disponível!"
		status=DESCONHECIDO
	fi

	if ! is_cpu_affected "$cve"; then
		# override status & msg in case CPU is not vulnerable after all
		pvulnstatus $cve OK "seu fornecedor de CPU relatou que seu modelo de CPU como não afetado"
	elif [ -z "$msg" ]; then
		# if msg is empty, sysfs check didn't fill it, rely on our own test
		if [ "$pteinv_supported" = 1 ]; then
			if [ "$pteinv_active" = 1 ] || [ "$opt_live" != 1 ]; then
				pvulnstatus $cve OK "Inversão de PTE atenua a vulnerabilidade"
			else
				pvulnstatus $cve VULNERÁVEL "Seu kernel suporta inversão PTE, mas não parece estar ativado"
			fi
		else
			pvulnstatus $cve VULNERÁVEL "Seu kernel não suporta inversão PTE, atualize-o"
		fi
	else
		pvulnstatus $cve "$status" "$msg"
	fi
}

check_CVE_2018_3620_bsd()
{
	_info_nol "* O kernel reservou a página de memória no endereço físico 0x0: "
	if ! kldstat -q -m vmm; then
		kldload vmm 2>/dev/null && kldload_vmm=1
		_debug "tentou carregar o módulo vmm, kldload_vmm=$kldload_vmm"
	else
		_debug "módulo vmm já carregado"
	fi
	if sysctl hw.vmm.vmx.l1d_flush >/dev/null 2>&1; then
		# https://security.FreeBSD.org/patches/SA-18:09/l1tf-11.2.patch
		# this is very difficult to detect that the kernel reserved the 0 page, but this fix
		# is part of the exact same patch than the other L1TF CVE, so we detect it
		# and deem it as OK if the other patch is there
		pstatus green SIM
		bsd_zero_reserved=1
	else
		pstatus yellow NÃO
		bsd_zero_reserved=0
	fi

	if ! is_cpu_affected "$cve"; then
		pvulnstatus $cve OK "seu fornecedor de CPU relatou que seu modelo de CPU como não afetado"
	else
		if [ "$bsd_zero_reserved" = 1 ]; then
			pvulnstatus $cve OK "kernel mitiga a vulnerabilidade"
		else
			pvulnstatus $cve VULNERÁVEL "seu kernel precisa ser atualizado"
		fi
	fi
}

# L1TF VMM
check_CVE_2018_3646()
{
	cve='CVE-2018-3646'
	_info "\033[1;34m$cve também conhecido como '$(cve2name "$cve")'\033[0m"
	if [ "$os" = Linux ]; then
		check_CVE_2018_3646_linux
	elif echo "$os" | grep -q BSD; then
		check_CVE_2018_3646_bsd
	else
		_warn "SO não suportado ($os)"
	fi
}

check_CVE_2018_3646_linux()
{
	status=DESC
	sys_interface_available=0
	msg=''
	if sys_interface_check "/sys/devices/system/cpu/vulnerabilities/l1tf" '.*' quiet; then
		# this kernel has the /sys interface, trust it over everything
		sys_interface_available=1
	fi
	l1d_mode=-1
	if [ "$opt_sysfs_only" != 1 ]; then
		check_has_vmm

		_info "* Mitigação 1 (KVM)"
		_info_nol "  * O EPT está desativado: "
		ept_disabled=-1
		if [ "$opt_live" = 1 ]; then
			if ! [ -r /sys/module/kvm_intel/parameters/ept ]; then
				pstatus blue N/A "o módulo kvm_intel não está carregado"
			elif [ "$(cat /sys/module/kvm_intel/parameters/ept)" = N ]; then
				pstatus green SIM
				ept_disabled=1
			else
				pstatus yellow NÃO
			fi
		else
			pstatus blue N/A "não testável no modo offline"
		fi

		_info "* Mitigação 2"
		_info_nol "  * O L1D flush é suportado pelo kernel: "
		if [ "$opt_live" = 1 ] && grep -qw flush_l1d "$procfs/cpuinfo"; then
			l1d_kernel="encontrado flush_l1d em $procfs/cpuinfo"
		fi
		if [ -z "$l1d_kernel" ]; then
			if ! command -v "${opt_arch_prefix}strings" >/dev/null 2>&1; then
				l1d_kernel_err="faltando a ferramenta '${opt_arch_prefix}strings', instale-a, geralmente está no pacote binutils"
			elif [ -n "$kernel_err" ]; then
				l1d_kernel_err="$kernel_err"
			elif "${opt_arch_prefix}strings" "$kernel" | grep -qw flush_l1d; then
				l1d_kernel='encontrado flush_l1d na imagem do kernel'
			fi
		fi

		if [ -n "$l1d_kernel" ]; then
			pstatus green SIM "$l1d_kernel"
		elif [ -n "$l1d_kernel_err" ]; then
			pstatus yellow DESCONHECIDO "$l1d_kernel_err"
		else
			pstatus yellow NÃO
		fi

		_info_nol "  * Liberação L1D ativada: "
		if [ "$opt_live" = 1 ]; then
			if [ -n "$fullmsg" ]; then
				# vanilla: VMX: $l1dstatus, SMT $smtstatus
				# Red Hat: VMX: SMT $smtstatus, L1D $l1dstatus
				# $l1dstatus is one of (auto|vulnerable|conditional cache flushes|cache flushes|EPT disabled|flush not necessary)
				# $smtstatus is one of (vulnerable|disabled)
				# can also just be "Not affected"
				if echo "$fullmsg" | grep -Eq -e 'Not affected' -e '(VMX:|L1D) (EPT disabled|vulnerable|flush not necessary)'; then
					l1d_mode=0
					pstatus yellow NÃO
				elif echo "$fullmsg" | grep -Eq '(VMX:|L1D) conditional cache flushes'; then
					l1d_mode=1
					pstatus green SIM "descargas condicionais"
				elif echo "$fullmsg" | grep -Eq '(VMX:|L1D) cache flushes'; then
					l1d_mode=2
					pstatus green SIM "descargas incondicionais"
				else
					if is_xen_dom0; then
						l1d_xen_hardware=$(xl dmesg | grep 'Hardware features:' | grep 'L1D_FLUSH' | head -1)
						l1d_xen_hypervisor=$(xl dmesg | grep 'Xen settings:' | grep 'L1D_FLUSH' | head -1)
						l1d_xen_pv_domU=$(xl dmesg | grep 'PV L1TF shadowing:' | grep 'DomU enabled' | head -1)

						if [ -n "$l1d_xen_hardware" ] && [ -n "$l1d_xen_hypervisor" ] && [ -n "$l1d_xen_pv_domU" ]; then
							l1d_mode=5
							pstatus green SIM "para convidados XEN"
						elif [ -n "$l1d_xen_hardware" ] && [ -n "$l1d_xen_hypervisor" ]; then
							l1d_mode=4
							pstatus yellow SIM "para convidados XEN (apenas HVM)"
						elif [ -n "$l1d_xen_pv_domU" ]; then
							l1d_mode=3
							pstatus yellow SIM "para convidados XEN (somente PV)"
						else
							l1d_mode=0
							pstatus yellow NÃO "para convidados XEN"
						fi
					else
						l1d_mode=-1
						pstatus yellow DESCONHECIDO "modo não reconhecido"
					fi
				fi
			else
				l1d_mode=-1
				pstatus yellow DESCONHECIDO "não consegue encontrar ou ler /sys/devices/system/cpu/vulnerabilities/l1tf"
			fi
		else
			l1d_mode=-1
			pstatus blue N/A "não testável no modo offline"
		fi

		_info_nol "  * Flush L1D suportado por hardware suportado: "
		if [ "$opt_live" = 1 ]; then
			if grep -qw flush_l1d "$procfs/cpuinfo" || [ -n "$l1d_xen_hardware" ]; then
				pstatus green SIM "impacto no desempenho da mitigação será bastante reduzido"
			else
				pstatus blue NÃO "flush será feito em software, isso é mais lento"
			fi
		else
			pstatus blue N/A "não testável no modo offline"
		fi

		_info_nol "  * O Hyper-Threading (SMT) está ativado: "
		is_cpu_smt_enabled; smt_enabled=$?
		if [ "$smt_enabled" = 0 ]; then
			pstatus yellow SIM
		elif [ "$smt_enabled" = 1 ]; then
			pstatus green NÃO
		else
			pstatus yellow DESCONHECIDO
		fi

	elif [ "$sys_interface_available" = 0 ]; then
		# we have no sysfs but were asked to use it only!
		msg="uso da interface de vulnerabilidade /sys forçado, mas não está disponível!"
		status=DESCONHECIDO
		l1d_mode=-1
	fi

	if ! is_cpu_affected "$cve"; then
		# override status & msg in case CPU is not vulnerable after all
		pvulnstatus $cve OK "seu fornecedor de CPU relatou que seu modelo de CPU como não afetado"
	elif [ "$fullmsg" = "Não afetado" ]; then
		# just in case a very recent kernel knows better than we do
		pvulnstatus $cve OK "seu kernel relatou seu modelo de CPU como não afetado"
	elif [ "$has_vmm" = 0 ]; then
		pvulnstatus $cve OK "este sistema não está executando um hypervisor"
	else
		if [ "$ept_disabled" = 1 ]; then
			pvulnstatus $cve OK "O EPT está desativado, o que atenua a vulnerabilidade"
		elif [ "$opt_paranoid" = 0 ]; then
			if [ "$l1d_mode" -ge 1 ]; then
				pvulnstatus $cve OK "A liberação do L1D está ativada e atenua a vulnerabilidade"
			else
				pvulnstatus $cve VULNERÁVEL "desabilite o EPT ou ative a liberação de L1D para atenuar a vulnerabilidade"
			fi
		else
			if [ "$l1d_mode" -ge 2 ]; then
				if [ "$smt_enabled" = 1 ]; then
					pvulnstatus $cve OK "A descarga incondicional do L1D e o Hyper-Threading desativado estão mitigando a vulnerabilidade"
				else
					pvulnstatus $cve VULNERÁVEL "O Hyper-Threading deve estar desabilitado para reduzir totalmente a vulnerabilidade"
				fi
			else
				if [ "$smt_enabled" = 1 ]; then
					pvulnstatus $cve VULNERÁVEL "A descarga incondicional do L1D deve ser ativada para reduzir completamente a vulnerabilidade"
				else
					pvulnstatus $cve VULNERÁVEL "habilite a liberação incondicional do L1D e desative o Hyper-Threading para reduzir completamente a vulnerabilidade"
				fi
			fi
		fi

		if [ $l1d_mode -gt 3 ]; then
			_warn
			_warn "Este host é um Xen Dom0. Verifique se você está executando seus DomUs"
			_warn "com um kernel que contém atenuações CVE-2018-3646."
			_warn
			_warn "Veja https://www.suse.com/support/kb/doc/?id=7023078 e XSA-273 para detalhes."
		fi
	fi
}

check_CVE_2018_3646_bsd()
{
	_info_nol "* O kernel suporta liberação L1D: "
	if sysctl hw.vmm.vmx.l1d_flush >/dev/null 2>&1; then
		pstatus green SIM
		kernel_l1d_supported=1
	else
		pstatus yellow NÃO
		kernel_l1d_supported=0
	fi

	_info_nol "* A descarga do L1D está ativada: "
	kernel_l1d_enabled=$(sysctl -n hw.vmm.vmx.l1d_flush 2>/dev/null)
	case "$kernel_l1d_enabled" in
		0) pstatus yellow NÃO;;
		1) pstatus green SIM;;
		"") pstatus yellow NÃO;;
		*) pstatus yellow DESCONHECIDO;;
	esac

	if ! is_cpu_affected "$cve"; then
		pvulnstatus $cve OK "seu fornecedor de CPU relatou que seu modelo de CPU como não afetado"
	else
		if [ "$kernel_l1d_enabled" = 1 ]; then
			pvulnstatus $cve OK "A descarga de L1D atenua a vulnerabilidade"
		elif [ "$kernel_l1d_supported" = 1 ]; then
			pvulnstatus $cve VULNERÁVEL "A liberação do L1D é suportada pelo seu kernel, mas está desativada"
		else
			pvulnstatus $cve VULNERÁVEL "seu kernel precisa ser atualizado"
		fi
	fi
}

###################
# MSBDS SECTION

# Microarchitectural Store Buffer Data Sampling
check_CVE_2018_12126()
{
	cve='CVE-2018-12126'
	check_mds $cve
}

###################
# MFBDS SECTION

# Microarchitectural Fill Buffer Data Sampling
check_CVE_2018_12130()
{
	cve='CVE-2018-12130'
	check_mds $cve
}

###################
# MLPDS SECTION

# Microarchitectural Load Port Data Sampling
check_CVE_2018_12127()
{
	cve='CVE-2018-12127'
	check_mds $cve
}

###################
# MDSUM SECTION

# Microarchitectural Data Sampling Uncacheable Memory 
check_CVE_2019_11091()
{
	cve='CVE-2019-11091'
	check_mds $cve
}

# Microarchitectural Data Sampling
check_mds()
{
	cve=$1
	_info "\033[1;34m$cve também conhecido como '$(cve2name "$cve")'\033[0m"
	if [ "$os" = Linux ]; then
		check_mds_linux "$cve"
	elif echo "$os" | grep -q BSD; then
		check_mds_bsd "$cve"
	else
		_warn "SO não suportado ($os)"
	fi
}

check_mds_bsd()
{
	_info_nol "* O kernel suporta o uso da mitigação MD_CLEAR: "
	if [ "$opt_live" = 1 ]; then
		if sysctl hw.mds_disable >/dev/null 2>&1; then
			pstatus green SIM
			kernel_md_clear=1
		else
			pstatus yellow NÃO
			kernel_md_clear=0
		fi
	else
		if grep -Fq hw.mds_disable $opt_kernel; then
			pstatus green SIM
			kernel_md_clear=1
		else
			kernel_md_clear=0
			pstatus yellow NÃO
		fi
	fi

	_info_nol "* O Hyper-Threading da CPU (SMT) está desativado: "
	if sysctl machdep.hyperthreading_allowed >/dev/null 2>&1; then
		kernel_smt_allowed=$(sysctl -n machdep.hyperthreading_allowed 2>/dev/null)
		if [ "$kernel_smt_allowed" = 1 ]; then
			pstatus yellow NÃO
		else
			pstatus green SIM
		fi
	else
		pstatus yellow DESCONHECIDO "sysctl machdep.hyperthreading_allowed não existe"
	fi

	_info_nol "* A atenuação do kernel está ativada: "
	if [ "$kernel_md_clear" = 1 ]; then
		kernel_mds_enabled=$(sysctl -n hw.mds_disable 2>/dev/null)
	else
		kernel_mds_enabled=0
	fi
	case "$kernel_mds_enabled" in
		0) pstatus yellow NÃO;;
		1) pstatus green SIM "com suporte a microcódigo";;
		2) pstatus green SIM "suporte somente de software (LENTO)";;
		3) pstatus green SIM;;
		*) pstatus yellow DESCONHECIDO "valor desconhecido $kernel_mds_enabled"
	esac

	_info_nol "* A mitigação do kernel está ativa: "
	if [ "$kernel_md_clear" = 1 ]; then
		kernel_mds_state=$(sysctl -n hw.mds_disable_state 2>/dev/null)
	else
		kernel_mds_state=inactive
	fi
	# https://github.com/freebsd/freebsd/blob/master/sys/x86/x86/cpu_machdep.c#L953
	case "$kernel_mds_state" in
		inactive)  pstatus yellow NÃO;;
		VERW)      pstatus green SIM "com suporte a microcódigo";;
		software*) pstatus green SIM "suporte somente de software (LENTO)";;
		*)         pstatus yellow DESCONHECIDO
	esac

	if ! is_cpu_affected "$cve"; then
		pvulnstatus "$cve" OK "seu fornecedor de CPU relatou que seu modelo de CPU como não afetado"
	else
		if [ "$cpuid_md_clear" = 1 ]; then
			if [ "$kernel_md_clear" = 1 ]; then
				if [ "$opt_live" = 1 ]; then
					# mitigation must also be enabled
					if [ "$kernel_mds_enabled" -ge 1 ]; then
						if [ "$opt_paranoid" != 1 ] || [ "$kernel_smt_allowed" = 0 ]; then
							pvulnstatus "$cve" OK "Seu microcódigo e kernel estão atualizados para essa mitigação, e a mitigação está ativada"
						else
							pvulnstatus "$cve" VULNERÁVEL "Seu microcódigo e kernel estão atualizados para essa atenuação, mas você deve desativar o SMT (Hyper-Threading) para obter uma atenuação completa"
						fi
					else
						pvulnstatus "$cve" VULNERÁVEL "Seu microcódigo e kernel estão atualizados para essa atenuação, mas a atenuação não está ativa"
						explain "Para habilitar a mitigação, execute \`sysctl hw.mds_disable=1'. Para tornar essa alteração persistente nas reinicializações, você pode adicionar 'hw.mds_disable=1' para /etc/sysctl.conf."
					fi
				else
					pvulnstatus "$cve" OK "Seu microcódigo e kernel estão atualizados para essa mitigação"
				fi
			else
				pvulnstatus "$cve" VULNERÁVEL "Seu microcódigo suporta mitigação, mas seu kernel não, atualize-o para reduzir a vulnerabilidade"
			fi
		else
			if [ "$kernel_md_clear" = 1 ]; then
				pvulnstatus "$cve" VULNERÁVEL "Seu kernel suporta mitigação, mas o microcódigo da CPU também precisa ser atualizado para reduzir a vulnerabilidade"
			else
				pvulnstatus "$cve" VULNERÁVEL "Nem o seu kernel nem o seu microcódigo suportam mitigação, atualize os dois para reduzir a vulnerabilidade"
			fi
		fi
	fi
}

check_mds_linux()
{
	status=DESCONHECIDO
	sys_interface_available=0
	msg=''
	if sys_interface_check "/sys/devices/system/cpu/vulnerabilities/mds" '^[^;]+'; then
		sys_interface_available=1
	fi

	if [ "$opt_sysfs_only" != 1 ]; then
		_info_nol "* O kernel suporta o uso da mitigação MD_CLEAR: "
		kernel_md_clear=''
		kernel_md_clear_can_tell=1
		if [ "$opt_live" = 1 ] && grep ^flags "$procfs/cpuinfo" | grep -qw md_clear; then
			kernel_md_clear="md_clear encontrado em  $procfs/cpuinfo"
			pstatus green SIM "$kernel_md_clear"
		fi
		if [ -z "$kernel_md_clear" ]; then
			if ! command -v "${opt_arch_prefix}strings" >/dev/null 2>&1; then
				kernel_md_clear_can_tell=0
			elif [ -n "$kernel_err" ]; then
				kernel_md_clear_can_tell=0
			elif "${opt_arch_prefix}strings" "$kernel" | grep -q 'Clear CPU buffers'; then
				_debug "md_clear: encontrou a string 'Clear CPU buffers' na imagem do kernel"
				kernel_md_clear='encontrou evidências de implementação md_clear na imagem do kernel'
				pstatus green SIM "$kernel_md_clear"
			fi
		fi
		if [ -z "$kernel_md_clear" ]; then
			if [ "$kernel_md_clear_can_tell" = 1 ]; then
				pstatus yellow NÃO
			else
				pstatus yellow DESCONHECIDO
			fi
		fi

		if [ "$opt_live" = 1 ] && [ "$sys_interface_available" = 1 ]; then
			_info_nol "* A mitigação do kernel está ativada e ativa: "
			if echo "$fullmsg" | grep -qi ^mitigation; then
				mds_mitigated=1
				pstatus green SIM
			else
				mds_mitigated=0
				pstatus yellow NÃO
			fi
			_info_nol "* O SMT é mitigado ou desativado: "
			if echo "$fullmsg" | grep -Eq 'SMT (disabled|mitigated)'; then
				mds_smt_mitigated=1
				pstatus green SIM
			else
				mds_smt_mitigated=0
				pstatus yellow NÃO
			fi
		fi
	elif [ "$sys_interface_available" = 0 ]; then
		# we have no sysfs but were asked to use it only!
		msg="uso da interface de vulnerabilidade /sys forçado, mas não está disponível!"
		status=DESCONHECIDO
	fi

	if ! is_cpu_affected "$cve"; then
		# override status & msg in case CPU is not vulnerable after all
		pvulnstatus "$cve" OK "seu fornecedor de CPU relatou que seu modelo de CPU como não afetado"
	else
		if [ "$opt_sysfs_only" != 1 ]; then
			# compute mystatus and mymsg from our own logic
			if [ "$cpuid_md_clear" = 1 ]; then
				if [ -n "$kernel_md_clear" ]; then
					if [ "$opt_live" = 1 ]; then
						# mitigation must also be enabled
						if [ "$mds_mitigated" = 1 ]; then
							if [ "$opt_paranoid" != 1 ] || [ "$mds_smt_mitigated" = 1 ]; then
								mystatus=OK
								mymsg="Seu microcódigo e kernel estão atualizados para essa mitigação, e a mitigação está ativada"
							else
								mystatus=VULNERÁVEL
								mymsg="Seu microcódigo e kernel estão atualizados para essa atenuação, mas você deve desativar o SMT (Hyper-Threading) para obter uma atenuação completa"
							fi
						else
							mystatus=VULNERÁVEL
							mymsg="Seu microcódigo e kernel estão atualizados para essa atenuação, mas a atenuação não está ativa"
						fi
					else
						mystatus=OK
						mymsg="Seu microcódigo e kernel estão atualizados para essa mitigação"
					fi
				else
					mystatus=VULNERÁVEL
					mymsg="Seu microcódigo suporta mitigação, mas seu kernel não, atualize-o para reduzir a vulnerabilidade"
				fi
			else
				if [ -n "$kernel_md_clear" ]; then
					mystatus=VULNERÁVEL
					mymsg="Seu kernel suporta mitigação, mas o microcódigo da CPU também precisa ser atualizado para reduzir a vulnerabilidade"
				else
					mystatus=VULNERÁVEL
					mymsg="Nem o seu kernel nem o seu microcódigo suportam mitigação, atualize os dois para reduzir a vulnerabilidade"
				fi
			fi
		else
			# sysfs only: return the status/msg we got
			pvulnstatus "$cve" "$status" "$fullmsg"
			return
		fi

		# if we didn't get a msg+status from sysfs, use ours
		if [ -z "$msg" ]; then
			pvulnstatus "$cve" "$mystatus" "$mymsg"
		elif [ "$opt_paranoid" = 1 ]; then
			# if paranoid mode is enabled, we now that we won't agree on status, so take ours
			pvulnstatus "$cve" "$mystatus" "$mymsg"
		elif [ "$status" = "$mystatus" ]; then
			# if we agree on status, we'll print the common status and our message (more detailed than the sysfs one)
			pvulnstatus "$cve" "$status" "$mymsg"
		else
			# if we don't agree on status, maybe our logic is flawed due to a new kernel/mitigation? use the one from sysfs
			pvulnstatus "$cve" "$status" "$msg"
		fi
	fi
}


###################
# TAA SECTION

# Transactional Synchronization Extension (TSX) Asynchronous Abort
check_CVE_2019_11135()
{
	cve='CVE-2019-11135'
	_info "\033[1;34m$cve também conhecido como '$(cve2name "$cve")'\033[0m"
	if [ "$os" = Linux ]; then
		check_CVE_2019_11135_linux
	elif echo "$os" | grep -q BSD; then
		check_CVE_2019_11135_bsd
	else
		_warn "SO não suportado ($os)"
	fi
}

check_CVE_2019_11135_linux()
{
	status=DESC
	sys_interface_available=0
	msg=''
	if sys_interface_check "/sys/devices/system/cpu/vulnerabilities/tsx_async_abort"; then
		# this kernel has the /sys interface, trust it over everything
		sys_interface_available=1
	fi
	if [ "$opt_sysfs_only" != 1 ]; then
		_info_nol "* A mitigação de TAA é suportada pelo kernel: "
		kernel_taa=''
		if [ -n "$kernel_err" ]; then
			kernel_taa_err="$kernel_err"
		elif grep -q 'tsx_async_abort' "$kernel"; then
			kernel_taa="tsx_async_abort encontrado na imagem do kernel"
		fi
		if [ -n "$kernel_taa" ]; then
			pstatus green SIM "$kernel_taa"
		elif [ -n "$kernel_taa_err" ]; then
			pstatus yellow DESCONHECIDO "$kernel_taa_err"
		else
			pstatus yellow NÃO
		fi

		_info_nol "* Atenuação de TAA ativada e ativa: "
		if [ "$opt_live" = 1 ]; then
			if [ -n "$fullmsg" ]; then
				if echo "$fullmsg" | grep -qE '^Mitigation'; then
					pstatus green SIM "$fullmsg"
				else
					pstatus yellow NÃO
				fi
			else
				pstatus yellow NÃO "tsx_async_abort não encontrado na hierarquia do sysfs"
			fi
		else
			pstatus blue N/A "não testável no modo offline"
		fi
	elif [ "$sys_interface_available" = 0 ]; then
		# we have no sysfs but were asked to use it only!
		msg="uso da interface de vulnerabilidade /sys forçado, mas não está disponível!"
		status=DESC
	fi

	if ! is_cpu_affected "$cve" ; then
		# override status & msg in case CPU is not vulnerable after all
		pvulnstatus "$cve" OK "seu fornecedor de CPU relatou que seu modelo de CPU como não afetado"
	elif [ -z "$msg" ]; then
		# if msg is empty, sysfs check didn't fill it, rely on our own test
		if [ "$opt_live" = 1 ]; then
			# if we're in live mode and $msg is empty, sysfs file is not there so kernel is too old
			pvulnstatus $cve VULNERÁVEL "Seu kernel não suporta mitigação de TAA, atualize-o"
		else
			if [ -n "$kernel_taa" ]; then
				pvulnstatus $cve OK "Seu kernel suporta mitigação de TAA"
			else
				pvulnstatus $cve VULNERÁVEL "Seu kernel não suporta mitigação de TAA, atualize-o"
			fi
		fi
	else
		if [ "$opt_paranoid" = 1 ]; then
			# in paranoid mode, TSX or SMT enabled are not OK, even if TAA is mitigated
			if ! echo "$fullmsg" | grep -qF 'TSX desativado'; then
				pvulnstatus $cve VULNERÁVEL "O TSX deve estar desativado para mitigação total"
			elif echo "$fullmsg" | grep -qF 'Vulnerável a SMT'; then
				pvulnstatus $cve VULNERÁVEL "O SMT (HyperThreading) deve estar desativado para mitigação total"
			else
				pvulnstatus $cve "$status" "$msg"
			fi
		else
			pvulnstatus $cve "$status" "$msg"
		fi
	fi
}

check_CVE_2019_11135_bsd()
{
	if ! is_cpu_affected "$cve" ; then
		# override status & msg in case CPU is not vulnerable after all
		pvulnstatus "$cve" OK "seu fornecedor de CPU relatou que seu modelo de CPU não foi afetado"
	else
		pvulnstatus "$cve" DESCONHECIDO "sua CPU é afetada, mas a detecção de mitigação ainda não foi implementada para BSD neste script"
	fi
}

#######################
# iTLB Multihit section

check_CVE_2018_12207()
{
	cve='CVE-2018-12207'
	_info "\033[1;34m$cve também conhecido como '$(cve2name "$cve")'\033[0m"
	if [ "$os" = Linux ]; then
		check_CVE_2018_12207_linux
	elif echo "$os" | grep -q BSD; then
		check_CVE_2018_12207_bsd
	else
		_warn "SO não suportado ($os)"
	fi
}

check_CVE_2018_12207_linux()
{
	status=DESCONHECIDO
	sys_interface_available=0
	msg=''
	if sys_interface_check "/sys/devices/system/cpu/vulnerabilities/itlb_multihit"; then
		# this kernel has the /sys interface, trust it over everything
		sys_interface_available=1
	fi
	if [ "$opt_sysfs_only" != 1 ]; then
		check_has_vmm

		_info_nol "* A atenuação do iTLB Multihit é suportada pelo kernel: "
		kernel_itlbmh=''
		if [ -n "$kernel_err" ]; then
			kernel_itlbmh_err="$kernel_err"
		# commit 5219505fcbb640e273a0d51c19c38de0100ec5a9
		elif grep -q 'itlb_multihit' "$kernel"; then
			kernel_itlbmh="encontrou itlb_multihit na imagem do kernel"
		fi
		if [ -n "$kernel_itlbmh" ]; then
			pstatus green SIM "$kernel_itlbmh"
		elif [ -n "$kernel_itlbmh_err" ]; then
			pstatus yellow DESCONHECIDO "$kernel_itlbmh_err"
		else
			pstatus yellow NÃO
		fi

		_info_nol "* Ativação iTLB Multihit ativada e ativa: "
		if [ "$opt_live" = 1 ]; then
			if [ -n "$fullmsg" ]; then
				if echo "$fullmsg" | grep -qF 'Mitigation'; then
					pstatus green SIM "$fullmsg"
				else
					pstatus yellow NÃO
				fi
			else
				pstatus yellow NÃO "itlb_multihit não encontrado na hierarquia do sysfs"
			fi
		else
			pstatus blue N/A "not testable in offline mode"
		fi
	elif [ "$sys_interface_available" = 0 ]; then
		# we have no sysfs but were asked to use it only!
		msg="uso da interface de vulnerabilidade /sys forçado, mas não está disponível!"
		status=DESCONHECIDO
	fi

	if ! is_cpu_affected "$cve" ; then
		# override status & msg in case CPU is not vulnerable after all
		pvulnstatus "$cve" OK "seu fornecedor de CPU relatou que seu modelo de CPU como não afetado"
	elif [ "$has_vmm" = 0 ]; then
		pvulnstatus "$cve" OK "este sistema não está executando um hypervisor"
	elif [ -z "$msg" ]; then
		# if msg is empty, sysfs check didn't fill it, rely on our own test
		if [ "$opt_live" = 1 ]; then
			# if we're in live mode and $msg is empty, sysfs file is not there so kernel is too old
			pvulnstatus $cve VULNERÁVEL "Seu kernel não suporta a atenuação do iTLB Multihit, atualize-o"
		else
			if [ -n "$kernel_itlbmh" ]; then
				pvulnstatus $cve OK "Seu kernel suporta a atenuação do iTLB Multihit"
			else
				pvulnstatus $cve VULNERÁVEL "Seu kernel não suporta a atenuação do iTLB Multihit, atualize-o"
			fi
		fi
	else
		pvulnstatus $cve "$status" "$msg"
	fi
}

check_CVE_2018_12207_bsd()
{
	_info_nol "* Kernel suporta desabilitar superpáginas para mapeamentos executáveis em EPT: "
	kernel_2m_x_ept=$(sysctl -n vm.pmap.allow_2m_x_ept 2>/dev/null)
	if [ -z "$kernel_2m_x_ept" ]; then
		pstatus yellow NÃO
	else
		pstatus green SIM
	fi

	_info_nol "* Superpáginas estão desabilitadas para mapeamentos executáveis em EPT: "
	if [ "$kernel_2m_x_ept" = 0 ]; then
		pstatus green SIM
	else
		pstatus yellow NÃO
	fi

	if ! is_cpu_affected "$cve"; then
		# override status & msg in case CPU is not vulnerable after all
		pvulnstatus $cve OK "seu fornecedor de CPU relatou que seu modelo de CPU não foi afetado"
	elif [ -z "$kernel_2m_x_ept" ]; then
		pvulnstatus $cve VULNERÁVEL "Seu kernel não suporta mitigar este CVE, você deve atualizá-lo"
	elif [ "$kernel_2m_x_ept" != 0 ]; then
		pvulnstatus $cve VULNERÁVEL "Seu kernel suporta a mitigação deste CVE, mas a mitigação está desabilitada"
		explain "Para habilitar a mitigação, use \`sysctl vm.pmap.allow_2m_x_ept=0\`"
	else
		pvulnstatus $cve OK "Seu kernel tem suporte para mitigação e a mitigação está habilitada"
	fi
}

###################
# SRBDS SECTION

# Special Register Buffer Data Sampling (SRBDS)
check_CVE_2020_0543()
{
	cve='CVE-2020-0543'
	_info "\033[1;34m$cve também conhecido como '$(cve2name "$cve")'\033[0m"
	if [ "$os" = Linux ]; then
		check_CVE_2020_0543_linux
	elif echo "$os" | grep -q BSD; then
		check_CVE_2020_0543_bsd
	else
		_warn "SO não suportado ($os)"
	fi
}

check_CVE_2020_0543_linux()
{
	status=DESC
	sys_interface_available=0
	msg=''
	if sys_interface_check "/sys/devices/system/cpu/vulnerabilities/srbds"; then
		# this kernel has the /sys interface, trust it over everything
		sys_interface_available=1
	fi
	if [ "$opt_sysfs_only" != 1 ]; then
		_info_nol "* O controle de mitigação SRBDS é suportado pelo kernel: "
		kernel_srbds=''
		if [ -n "$kernel_err" ]; then
			kernel_srbds_err="$kernel_err"
		elif grep -q 'Dependente do hipervisor' "$kernel"; then
			kernel_srbds="encontrou evidências de implementação de SRBDS na imagem do kernel. Seu kernel está atualizado para mitigação SRBDS"
		fi
		if [ -n "$kernel_srbds" ]; then
			pstatus green SIM "$kernel_srbds"
		elif [ -n "$kernel_srbds_err" ]; then
			pstatus yellow DESCONHECIDO "$kernel_srbds_err"
		else
			pstatus yellow NÃO
		fi
		_info_nol "* O controle de mitigação SRBDS está habilitado e ativo: "
		if [ "$opt_live" = 1 ]; then
			if [ -n "$fullmsg" ]; then
				if echo "$fullmsg" | grep -qE '^Mitigation'; then
					pstatus green SIM "$fullmsg"
				else
					pstatus yellow NÃO
				fi
			else
				pstatus yellow NÃO "SRBDS não encontrado na hierarquia sysfs"
			fi
		else
			pstatus blue N/A "não testável em modo offline"
		fi
	elif [ "$sys_interface_available" = 0 ]; then
		# we have no sysfs but were asked to use it only!
		msg="A interface de vulnerabilidade /sys usa forçado, mas não está disponível!"
		status=DESCONHECIDO
	fi
	if ! is_cpu_affected "$cve" ; then
		# override status & msg in case CPU is not vulnerable after all
		pvulnstatus "$cve" OK "seu fornecedor de CPU relatou que seu modelo de CPU não é afetado"
	else
		if [ "$opt_sysfs_only" != 1 ]; then
			if [ "$cpuid_srbds" = 1 ]; then
				# SRBDS mitigation control exists
				if [ "$srbds_on" = 1 ]; then
					# SRBDS mitigation control is enabled
					if [ -z "$msg" ]; then
						# if msg is empty, sysfs check didn't fill it, rely on our own test
						if [ "$opt_live" = 1 ]; then
							# if we're in live mode and $msg is empty, sysfs file is not there so kernel is too old
							pvulnstatus "$cve" OK "Seu microcódigo está atualizado para o controle de mitigação SRBDS. O kernel precisa ser atualizado"
						fi
					else
						if [ -n "$kernel_srbds" ]; then
							pvulnstatus "$cve" OK "Seu microcódigo e kernel estão atualizados para o controle de mitigação SRBDS. Mitigação está habilitada"
						else
							pvulnstatus "$cve" OK "Seu microcódigo está atualizado para o controle de mitigação SRBDS. O kernel precisa ser atualizado"
						fi
					fi
				elif [ "$srbds_on" = 0 ]; then
					# SRBDS mitigation control is disabled
					if [ -z "$msg" ]; then
						if [ "$opt_live" = 1 ]; then
							# if we're in live mode and $msg is empty, sysfs file is not there so kernel is too old
							pvulnstatus "$cve" VULNERÁVEL "Seu microcódigo está atualizado para o controle de mitigação SRBDS. O kernel precisa ser atualizado. Mitigação está desativada"
						fi
					else
						if [ -n "$kernel_srbds" ]; then
							pvulnstatus "$cve" VULNERÁVEL "Seu microcódigo e kernel estão atualizados para o controle de mitigação SRBDS. Mitigação está desativada"
						else
							pvulnstatus "$cve" VULNERÁVEL "Seu microcódigo está atualizado para o controle de mitigação SRBDS. O kernel precisa ser atualizado. Mitigação está desativada"
						fi
					fi
				else
					# rdmsr: CPU 0 cannot read MSR 0x00000123
					pvulnstatus "$cve" DESCONHECIDO "Não é possível enumerar MSR para controle de mitigação SRBDS"
				fi
			else
				# [ $cpuid_srbds != 1 ]
				pvulnstatus "$cve" VULNERÁVEL "Seu microcódigo de CPU pode precisar ser atualizado para mitigar a vulnerabilidade"
			fi
		else
			# sysfs only: return the status/msg we got
			pvulnstatus "$cve" "$status" "$fullmsg"
			return
		fi
	fi
}

check_CVE_2020_0543_bsd()
{
	if ! is_cpu_affected "$cve"; then
		# override status & msg in case CPU is not vulnerable after all
		pvulnstatus $cve OK "seu fornecedor de CPU relatou que seu modelo de CPU não foi afetado"
	else
		pvulnstatus "$cve" DESCONHECIDO "sua CPU é afetada, mas a detecção de mitigação ainda não foi implementada para BSD neste script"
	fi
}

####################
# Zenbleed section

check_CVE_2023_20593()
{
	cve='CVE-2023-20593'
	_info "\033[1;34m$cve também conhecido como '$(cve2name "$cve")'\033[0m"
	if [ "$os" = Linux ]; then
		check_CVE_2023_20593_linux
	#elif echo "$os" | grep -q BSD; then
	#	check_CVE_2023_20593_bsd
	else
		_warn "SO não compatível ($os)"
	fi
}

check_CVE_2023_20593_linux()
{
	status=DESC
	sys_interface_available=0
	msg=''
	if [ "$opt_sysfs_only" != 1 ]; then
		_info_nol "* A mitigação do Zenbleed é suportada pelo kernel: "
		kernel_zenbleed=''
		if [ -n "$kernel_err" ]; then
			kernel_zenbleed_err="$kernel_err"
		# commit 522b1d69219d8f083173819fde04f994aa051a98
		elif grep -q 'Zenbleed:' "$kernel"; then
			kernel_zenbleed="mensagem zenbleed encontrada na imagem do kernel"
		fi
		if [ -n "$kernel_zenbleed" ]; then
			pstatus green SIM "$kernel_zenbleed"
		elif [ -n "$kernel_zenbleed_err" ]; then
			pstatus yellow DESCONHECIDO "$kernel_zenbleed_err"
		else
			pstatus yellow NÃO
		fi
		_info_nol "* Mitigação do kernel Zenbleed habilitada e ativa: "
		if [ "$opt_live" = 1 ]; then
			# read the DE_CFG MSR, we want to check the 9th bit
			# don't do it on non-Zen2 AMD CPUs or later, aka Family 17h,
			# as the behavior could be unknown on others
			if is_amd && [ "$cpu_family" -ge $((0x17)) ]; then
				read_msr 0xc0011029; ret=$?
				if [ $ret = $READ_MSR_RET_OK ]; then
					if [ $(( read_msr_value >> 9 & 1 )) -eq 1 ]; then
						pstatus green SIM "Bit FP_BACKUP_FIX definido em DE_CFG"
						fp_backup_fix=1
					else
						pstatus yellow NÃO "FP_BACKUP_FIX é limpo em DE_CFG"
						fp_backup_fix=0
					fi
				elif [ $ret = $READ_MSR_RET_KO ]; then
					pstatus yellow DESCONHECIDO "Não foi possível ler o DE_CFG MSR"
				else
					pstatus yellow DESCONHECIDO "$read_msr_msg"
				fi
			else
				fp_backup_fix=0
				pstatus blue N/A "CPU é incompatível"
			fi
		else
			pstatus blue N/A "não testável no modo offline"
		fi

		_info_nol "* A mitigação do Zenbleed é suportada pelo microcódigo da CPU: "
		has_zenbleed_fixed_firmware; ret=$?
		if [ $ret -eq 0 ]; then
			pstatus green SIM
			cpu_ucode_zenbleed=1
		elif [ $ret -eq 1 ]; then
			pstatus yellow NÃO
			cpu_ucode_zenbleed=2
		else
			pstatus yellow DESCONHECIDO
			cpu_ucode_zenbleed=3
		fi

	elif [ "$sys_interface_available" = 0 ]; then
		# we have no sysfs but were asked to use it only!
		msg="interface de vulnerabilidade /sys usa forçado, mas não está disponível!"
		status=DESCONHECIDO
	fi

	if ! is_cpu_affected "$cve" ; then
		# override status & msg in case CPU is not vulnerable after all
		pvulnstatus "$cve" OK "seu fornecedor de CPU relatou seu modelo de CPU como não afetado"
	elif [ -z "$msg" ]; then
		# if msg is empty, sysfs check didn't fill it, rely on our own test
		zenbleed_print_vuln=0
		if [ "$opt_live" = 1 ]; then
			if [ "$fp_backup_fix" = 1 ] && [ "$cpu_ucode_zenbleed" = 1 ]; then
				# this should never happen, but if it does, it's interesting to know
				pvulnstatus $cve OK "Tanto o microcódigo da CPU quanto o kernel estão mitigando o Zenbleed"
			elif [ "$cpu_ucode_zenbleed" = 1 ]; then
				pvulnstatus $cve OK "O microcódigo da sua CPU mitiga o Zenbleed"
			elif [ "$fp_backup_fix" = 1 ]; then
				pvulnstatus $cve OK "Seu kernel mitiga o Zenbleed"
			else
				zenbleed_print_vuln=1
			fi
		else
			if [ "$cpu_ucode_zenbleed" = 1 ]; then
				pvulnstatus $cve OK "O microcódigo da sua CPU mitiga o Zenbleed"
			elif [ -n "$kernel_zenbleed" ]; then
				pvulnstatus $cve OK "Seu kernel mitiga o Zenbleed"
			else
				zenbleed_print_vuln=1
			fi
		fi
		if [ "$zenbleed_print_vuln" = 1 ]; then
			pvulnstatus $cve VULNERÁVEL "Seu kernel é muito antigo para atenuar o Zenbleed e seu microcódigo de CPU também não o atenua"
explique "Seu fornecedor de CPU pode ter um novo microcódigo para seu modelo de CPU que atenua esse problema (consulte a seção de hardware acima).\n " \
"Caso contrário, o kernel do Linux é capaz de mitigar esse problema independentemente da versão do microcódigo que você possui, mas neste caso\n " \
"seu kernel é muito antigo para suportar isso, seu fornecedor de distribuição Linux pode ter uma versão mais recente para a qual você deve atualizar.\n " \
"Observe que ter um microcódigo atualizado OU um kernel atualizado é suficiente para atenuar esse problema.\n " \
"Para atenuar manualmente o problema agora, você pode usar o seguinte comando: \`wrmsr -a 0xc0011029 \$((\$(rdmsr -c 0xc0011029) | (1<<9)))\`,\n " \
"no entanto, observe que esta mitigação manual só estará ativa até a próxima reinicialização."
		fi
		unset zenbleed_print_vuln
	else
		pvulnstatus $cve "$status" "$msg"
	fi
}

#########################
# Downfall section

check_CVE_2022_40982() {
	cve='CVE-2022-40982'
	_info "\033[1;34m$cve também conhecido como '$(cve2name "$cve")'\033[0m"
	if [ "$os" = Linux ]
	then
		check_CVE_2022_40982_linux
	else
		_warn "SO não suportado ($os)."
	fi
}

check_CVE_2022_40982_linux() {
	status=DESC
	sys_interface_available=0
	msg=''

	if sys_interface_check "/sys/devices/system/cpu/vulnerabilities/gather_data_sampling"; then
		# this kernel has the /sys interface, trust it over everything
		sys_interface_available=1
	fi

	if [ "$opt_sysfs_only" != 1 ]; then
		_info_nol "* O GDS é mitigado pelo microcódigo: "
		if [ "$capabilities_gds_ctrl" = 1 ] && [ "$mcu_opt_ctrl_gds_mitg_dis" = 0 ]; then
			pstatus green OK "a mitigação de microcódigo é suportada e habilitada"
		else
			pstatus yellow NÃO
		fi
		_info_nol "* O kernel oferece suporte à mitigação de software desativando o AVX: "
		if [ -n "$kernel_err" ]; then	
			kernel_gds_err="$kernel_err"
		elif grep -q 'gather_data_sampling' "$kernel"; then
			kernel_gds="encontrado gather_data_sampling na imagem do kernel"
		fi
		if [ -n "$kernel_gds" ]; then
			pstatus green SIM "$kernel_gds"
		elif [ -n "$kernel_gds_err" ]; then
			pstatus yellow DESCONHECIDO "$kernel_gds_err"
		else
			pstatus yellow NÃO
		fi

		if [ -n "$kernel_gds" ]; then
			_info_nol "* Kernel desativou o AVX como uma mitigação: "

			# Check dmesg message to see whether AVX has been disabled
			dmesg_grep 'Atualização de microcódigo necessária! Desativando o AVX como mitigação'; dmesgret=$?
			if [ $dmesgret -eq 0 ]; then
				kernel_avx_disabled="AVX desativado pelo kernel (dmesg)"
				pstatus green SIM "$kernel_avx_disabled"
			elif [ "$has_avx2" = 0 ]; then
				# Find out by ourselves
				# cpuinfo says we don't have AVX2, query
				# the CPU directly about AVX2 support
				read_cpuid 0x7 0x0 $EBX 5 1 1; ret=$?
				if [ $ret -eq $READ_CPUID_RET_OK ]; then
					kernel_avx_disabled="AVX desativado pelo kernel (cpuid)"
					pstatus green SIM "$kernel_avx_disabled"
				elif [ $ret -eq $READ_CPUID_RET_KO ]; then
					pstatus yellow NÃO "CPU não suporta AVX"
				elif [ $dmesgret -eq 2 ]; then
					pstatus yellow DESCONHECIDO "dmesg truncado, não sei se a mitigação está ativa. Por favor, reinicie e abra novamente este script"
				else
					pstatus yellow DESCONHECIDO "Nenhum sinal de mitigação no dmesg e não foi possível ler as informações do cpuid"
				fi
			else
					pstatus yellow NÃO "O suporte AVX está ativado"
			fi
		fi

	elif [ "$sys_interface_available" = 0 ]; then
		# we have no sysfs but were asked to use it only!
		msg="interface de vulnerabilidade /sys usa forçado, mas não está disponível!"
		status=DESC
	fi

	if ! is_cpu_affected "$cve" ; then
		# override status & msg in case CPU is not vulnerable after all
		pvulnstatus "$cve" OK "seu fornecedor de CPU relatou seu modelo de CPU como não afetado"
	elif [ -z "$msg" ]; then
		# if msg is empty, sysfs check didn't fill it, rely on our own test
		if [ "$capabilities_gds_ctrl" = 1 ] && [ "$mcu_opt_ctrl_gds_mitg_dis" = 0 ]; then
			pvulnstatus $cve OK "Seu microcódigo está atualizado e a mitigação está habilitada"
		elif [ "$capabilities_gds_ctrl" = 1 ] && [ "$mcu_opt_ctrl_gds_mitg_dis" = 1 ]; then
			pvulnstatus $cve VULNERÁVEL "Seu microcódigo está atualizado, mas a mitigação está desativada"
		elif [ -z "$kernel_gds" ]; then
			pvulnstatus $cve VULNERÁVEL "Seu microcódigo não atenua a vulnerabilidade e seu kernel não oferece suporte à mitigação"
		elif [ -z "$kernel_avx_disabled" ]; then
			pvulnstatus $cve VULNERÁVEL "Seu microcódigo não atenua a vulnerabilidade, seu kernel suporta a mitigação, mas o script não detectou o AVX como desativado pelo kernel"
		else
			pvulnstatus $cve OK "Seu microcódigo não atenua a vulnerabilidade, mas seu kernel desativou o suporte AVX"
		fi
	else
		pvulnstatus $cve "$status" "$msg"
	fi
}

#######################
# Inception section

check_CVE_2023_20569() {
	cve='CVE-2023-20569'
	_info "\033[1;34m$cve também conhecido como '$(cve2name "$cve")'\033[0m"
	if [ "$os" = Linux ]
	then
		check_CVE_2023_20569_linux
	else
		_warn "SO não suportado ($os)."
	fi
}

check_CVE_2023_20569_linux() {
	status=DES
	sys_interface_available=0
	msg=''

	if sys_interface_check "/sys/devices/system/cpu/vulnerabilities/spec_rstack_overflow"; then
		# this kernel has the /sys interface, trust it over everything
		sys_interface_available=1
	fi

	if [ "$opt_sysfs_only" != 1 ]; then
		_info_nol "* O kernel suporta mitigação: "
		if [ -n "$kernel_err" ]; then
			kernel_sro_err="$kernel_err"
		elif grep -q 'spec_rstack_overflow' "$kernel"; then
			kernel_sro="encontrado spec_rstack_overflow na imagem do kernel"
		fi
		if [ -n "$kernel_sro" ]; then
			pstatus green SIM "$kernel_sro"
		elif [ -n "$kernel_sro_err" ]; then
			pstatus yellow DESCONHECIDO "$kernel_sro_err"
		else
			pstatus yellow NÃO
		fi

		_info_nol "* Kernel compilado com suporte SRSO: "
		if [ -r "$opt_config" ]; then
			# CONFIG_CPU_SRSO: Linux < 6.9
			# CONFIG_MITIGATION_SRSO: Linux >= 6.9
			if grep -Eq '^CONFIG_(CPU|MITIGATION)_SRSO=y' "$opt_config"; then
				pstatus green SIM
				kernel_srso="CONFIG_(CPU|MITIGATION)_SRSO=y encontrado na configuração do kernel"
			else
				pstatus yellow NÃO "necessário para mitigações seguras de RET e ibpb_on_vmexit"
			fi
		else
			# https://github.com/torvalds/linux/commit/138bcddb86d8a4f842e4ed6f0585abc9b1a764ff#diff-17bd24a7a7850613cced545790ac30646097e8d6207348c2bd1845f397acb390R2313
			if [ -n "$kernel_err" ]; then
				pstatus yellow DESCONHECIDO "$kernel_err"
			elif grep -Eq 'WARNING: kernel not compiled with (CPU|MITIGATION)_SRSO' "$kernel"; then
				# this msg is optimized out at compile time if the option is not enabled, see commit referenced above
				# if it's present, then SRSO is NOT compiled in
				pstatus yellow NÃO "kernel não compilado com (CPU|MITIGATION)_SRSO"
			else
				# if it's not present, then SRSO is compiled in IF kernel_sro==1, otherwise we're just
				# in front of an old kernel that doesn't have the mitigation logic at all
				if [ "$kernel_sro" = 1 ]; then
					kernel_srso="A lógica de mitigação do SRSO é compilada no kernel"
					pstatus green OK "$kernel_srso"
				else
					pstatus yellow NÃO "seu kernel é muito antigo e não tem lógica de mitigação"
				fi
			fi
		fi

		_info_nol "* Kernel compilado com suporte IBPB_ENTRY: "
		if [ -r "$opt_config" ]; then
			# CONFIG_CPU_IBPB_ENTRY: Linux < 6.9
			# CONFIG_MITIGATION_IBPB_ENTRY: Linux >= 6.9
			if grep -Eq '^CONFIG_(CPU|MITIGATION)_IBPB_ENTRY=y' "$opt_config"; then
				pstatus green SIM
				kernel_ibpb_entry="CONFIG_(CPU|MITIGATION)_IBPB_ENTRY=y encontrado na configuração do kernel"
			else
				pstatus yellow NÃO
			fi
		else
			# https://github.com/torvalds/linux/commit/138bcddb86d8a4f842e4ed6f0585abc9b1a764ff#diff-17bd24a7a7850613cced545790ac30646097e8d6207348c2bd1845f397acb390R2325
			if [ -n "$kernel_err" ]; then
				pstatus yellow DESCONHECIDO "$kernel_err"
			elif grep -Eq 'WARNING: kernel not compiled with (CPU|MITIGATION)_IBPB_ENTRY' "$kernel"; then
				# this msg is optimized out at compile time if the option is not enabled, see commit referenced above
				# if it's present, then IBPB_ENTRY is NOT compiled in
				pstatus yellow NÃO "kernel não compilado com CPU_IBPB_ENTRY"
			else
				# if it's not present, then IBPB_ENTRY is compiled in IF kernel_sro==1, otherwise we're just
				# in front of an old kernel that doesn't have the mitigation logic at all
				if [ "$kernel_sro" = 1 ]; then
					kernel_ibpb_entry="A lógica de mitigação IBPB_ENTRY é compilada no kernel"
					pstatus green OK "$kernel_ibpb_entry"
				else
					pstatus yellow NÃO "seu kernel é muito antigo e não possui lógica de mitigação"
				fi
			fi
		fi

		# Zen & Zen2 : if the right IBPB microcode applied + SMT off --> not vuln
		if [ "$cpu_family" = $(( 0x17 )) ]; then
			_info_nol "* CPU suporta IBPB: "
			if [ -n "$cpuid_ibpb" ]; then
				pstatus green SIM "$cpuid_ibpb"
			else
				pstatus yellow NÃO
			fi

			_info_nol "* Hyper-Threading (SMT) está habilitado: "
			is_cpu_smt_enabled; smt_enabled=$?
			if [ "$smt_enabled" = 0 ]; then
				pstatus yellow SIM
			else
				pstatus green NÃO
			fi
		# Zen 3/4 microcode brings SBPB mitigation
		elif [ "$cpu_family" = $(( 0x19 )) ]; then
			_info_nol "* CPU suporta SBPB: "
			if [ "$cpuid_sbpb" = 1 ]; then
				pstatus green SIM
			elif [ "$cpuid_sbpb" = 3 ]; then
				pstatus yellow DESCONHECIDO "não é possível escrever MSR, execute novamente com --allow-msr-write"
			else
				pstatus yellow NÃO
			fi
		fi

	elif [ "$sys_interface_available" = 0 ]; then
		# we have no sysfs but were asked to use it only!
		msg="Uso forçado da interface de vulnerabilidade /sys, mas não está disponível!"
		status=DESCONHECIDO
	fi

	if ! is_cpu_affected "$cve" ; then
		# override status & msg in case CPU is not vulnerable after all
		pvulnstatus "$cve" OK "seu fornecedor de CPU relatou seu modelo de CPU como não afetado"
	elif [ -z "$msg" ]; then
		# if msg is empty, sysfs check didn't fill it, so we rely on our own logic
		# Zen/Zen2
		if [ "$cpu_family" = $(( 0x17 )) ]; then
			if [ "$smt_enabled" = 0 ]; then
				pvulnstatus "$cve" VULNERÁVEL "SMT está habilitado em sua CPU Zen/Zen2, o que torna a mitigação ineficaz"
				explain "Para CPUs Zen/Zen2, a mitigação adequada precisa de um microcódigo atualizado e o SMT precisa ser desabilitado (isso pode ser feito adicionando \`nosmt\` à linha de comando do kernel)"
			elif [ -z "$kernel_sro" ]; then
				pvulnstatus "$cve" VULNERÁVEL "Seu kernel é muito antigo e não possui a lógica de mitigação SRSO"
			elif [ -n "$cpuid_ibpb" ]; then
				pvulnstatus "$cve" OK "SMT está desabilitado e tanto o kernel quanto o microcódigo suportam mitigação"
			else
				pvulnstatus "$cve" VULNERÁVEL "Seu microcódigo é muito antigo"
			fi
		# Zen3/Zen4
		elif [ "$cpu_family" = $(( 0x19 )) ]; then
			if [ -z "$kernel_sro" ]; then
				pvulnstatus "$cve" VULNERÁVEL "Seu kernel é muito antigo e não possui a lógica de mitigação SRSO"
			elif [ -z "$kernel_srso" ] && [ -z "$kernel_ibpb_entry" ]; then
				pvulnstatus "$cve" VULNERÁVEL "Seu kernel não possui SRSO ou IBPB_ENTRY compilado"
			elif [ "$cpuid_sbpb" = 3 ]; then
				pvulnstatus "$cve" DESCONHECIDO "Não foi possível verificar se o seu microcódigo suporta IBPB (executar novamente com --allow-msr-write)"
			elif [ "$cpuid_sbpb" = 2 ]; then
				pvulnstatus "$cve" VULNERÁVEL "Seu microcódigo não é compatível com SBPB"
			else
				pvulnstatus "$cve" OK "Seu kernel e microcódigo suportam mitigação"
			fi
		else
			# not supposed to happen, as normally this CPU should not be affected and not run this code
			pvulnstatus "$cve" OK "seu fornecedor de CPU relatou seu modelo de CPU como não afetado"
		fi
	else
		pvulnstatus $cve "$status" "$msg"
	fi
}

#######################
# Reptar section

check_CVE_2023_23583() {
	cve='CVE-2023-23583'
	_info "\033[1;34m$cve também conhecido como '$(cve2name "$cve")'\033[0m"
	if [ "$os" = Linux ]
	then
		check_CVE_2023_23583_linux
	else
		_warn "SO não suportado ($os)."
	fi
}

check_CVE_2023_23583_linux() {
	status=DESCONHECIDO
	sys_interface_available=0
	msg=''

	# there is no sysfs file for this vuln, and no kernel patch,
	# the mitigation is only ucode-based and there's no flag exposed,
	# so most of the work has already been done by is_cpu_affected()
	if ! is_cpu_affected "$cve" ; then
		pvulnstatus "$cve" OK "seu fornecedor de CPU relatou seu modelo de CPU como não afetado"
	else
		_info_nol "* Reptar é mitigado por microcódigo: "
		if [ "$cpu_ucode" -lt "$reptar_fixed_ucode_version" ]; then
			pstatus yellow NÃO "Você tem ucode $(printf "0x%x" $cpu_ucode) e a versão $(printf "0x%x" $reptar_fixed_ucode_version) mínima é necessária"
			pvulnstatus $cve VULNERÁVEL "Seu microcódigo é muito antigo para mitigar a vulnerabilidade"
		else
			pstatus green SIM "Você tem ucode $(printf "0x%x" $cpu_ucode) que é recente o suficiente (>= $(printf "0x%x" $reptar_fixed_ucode_version))"
			pvulnstatus $cve OK "Seu microcódigo atenua a vulnerabilidade"
		fi
	fi
}

#######################
# END OF VULNS SECTIONS

if [ "$opt_no_hw" = 0 ] && [ -z "$opt_arch_prefix" ]; then
	check_cpu
	check_cpu_vulnerabilities
	_info
fi

# now run the checks the user asked for
for cve in $supported_cve_list
do
	if [ "$opt_cve_all" = 1 ] || echo "$opt_cve_list" | grep -qw "$cve"; then
		check_"$(echo "$cve" | tr - _)"
		_info
	fi
done

if [ -n "$final_summary" ]; then
	_info "> \033[46m\033[30mRESUMO:\033[0m$final_summary"
	_info ""
fi

if [ "$bad_accuracy" = 1 ]; then
	_warn "Faltam algumas informações do kernel (consulte -v), a precisão pode ser reduzida"
fi

_vars=$(set | grep -Ev '^[A-Z_[:space:]]' | grep -v -F 'mockme=' | sort | tr "\n" '|')
_debug "variáveis no final do script: $_vars"

if [ -n "$mockme" ] && [ "$opt_mock" = 1 ]; then
	if command -v "gzip" >/dev/null 2>&1; then
		# not a useless use of cat: gzipping cpuinfo directly doesn't work well
		# shellcheck disable=SC2002
		if command -v "base64" >/dev/null 2>&1; then
			mock_cpuinfo="$(cat /proc/cpuinfo | gzip -c | base64 -w0)"
		elif command -v "uuencode" >/dev/null 2>&1; then
			mock_cpuinfo="$(cat /proc/cpuinfo | gzip -c | uuencode -m - | grep -Fv 'begin-base64' | grep -Fxv -- '====' | tr -d "\n")"
		fi
	fi
	if [ -n "$mock_cpuinfo" ]; then
		mockme=$(printf "%b\n%b" "$mockme" "SMC_MOCK_CPUINFO='$mock_cpuinfo'")
		unset mock_cpuinfo
	fi
	_info ""
	# shellcheck disable=SC2046
	_warn "Para zombar desta CPU, defina essas variáveis: "$(echo "$mockme" | sort -u)
fi

# root check
if [ "$(id -u)" -ne 0 ]; then
	_warn "Observe que você deve iniciar este script com privilégios de root para obter informações completamente precisas."
	_warn "Para executá-lo como root, você pode tentar o seguinte comando: sudo $0"
	_warn
fi

if [ "$opt_explain" = 0 ]; then
	_info "Precisa de informações mais detalhadas sobre as opções de mitigação? Use --explain"
fi

_info "Uma falsa sensação de segurança é pior do que nenhuma segurança, veja --disclaimer"

if [ "$mocked" = 1 ]; then
	_info ""
	_warn "Um ou vários valores foram simulados. Isso só deve ser feito ao depurar/testar este script."
	_warn "Os resultados NÃO refletem o status real do sistema em que estamos executando."
fi

if [ "$opt_batch" = 1 ] && [ "$opt_batch_format" = "nrpe" ]; then
	if [ -n "$nrpe_vuln" ]; then
		echo "Vulnerável:$nrpe_vuln"
	else
		echo "OK"
	fi
fi

if [ "$opt_batch" = 1 ] && [ "$opt_batch_format" = "short" ]; then
	_echo 0 "${short_output% }"
fi

if [ "$opt_batch" = 1 ] && [ "$opt_batch_format" = "json" ]; then
	_echo 0 "${json_output%?}]"
fi

if [ "$opt_batch" = 1 ] && [ "$opt_batch_format" = "prometheus" ]; then
	echo "# TYPE specex_vuln_status sem tipo"
	echo "# HELP specex_vuln_status Exposição do sistema a vulnerabilidades de execução especulativas"
	printf "%b\n" "$prometheus_output"
fi

# exit with the proper exit code
[ "$global_critical" = 1 ] && exit 2  # critical
[ "$global_unknown"  = 1 ] && exit 3  # unknown
exit 0  # ok

# Dump from Intel affected CPU page:
# - https://www.intel.com/content/www/us/en/developer/topic-technology/software-security-guidance/processors-affected-consolidated-product-cpu-model.html
# Only currently-supported CPUs are listed, so only rely on it if the current CPU happens to be in the list.
# We merge it with info from the following file:
# - https://software.intel.com/content/dam/www/public/us/en/documents/affected-processors-transient-execution-attacks-by-cpu-aug02.xlsx
# As it contains some information from older processors, however when information is contradictory between the two sources, the HTML takes precedence as
# it is expected to be updated, whereas the xslx seems to be frozen.
#
# N: Not affected
# S: Affected, software fix
# H: Affected, hardware fix
# M: Affected, MCU update needed
# B: Affected, BIOS update needed
# X: Affected, no planned mitigation
# Y: Affected (this is from the xlsx, no details are available)
#
# %%% INTELDB
# 0x000206A7,2017-5715=Y,2017-5753=Y,2017-5754=Y,2018-12126=Y,2018-12127=Y,2018-12130=Y,2018-12207=Y,2018-3615=Y,2018-3620=Y,2018-3639=Y,2018-3640=Y,2018-3646=Y,2019-11135=N,2020-0543=N,
# 0x000206D6,2017-5715=Y,2017-5753=Y,2017-5754=Y,2018-12126=Y,2018-12127=Y,2018-12130=Y,2018-12207=Y,2018-3615=Y,2018-3620=Y,2018-3639=Y,2018-3640=Y,2018-3646=Y,2019-11135=N,2020-0543=N,
# 0x000206D7,2017-5715=Y,2017-5753=Y,2017-5754=Y,2018-12126=Y,2018-12127=Y,2018-12130=Y,2018-12207=Y,2018-3615=Y,2018-3620=Y,2018-3639=Y,2018-3640=Y,2018-3646=Y,2019-11135=N,2020-0543=N,
# 0x00030673,2017-5715=Y,2017-5753=Y,2017-5754=Y,2018-12126=Y,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=N,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,
# 0x00030678,2017-5715=Y,2017-5753=Y,2017-5754=Y,2018-12126=Y,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=N,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,
# 0x00030679,2017-5715=Y,2017-5753=Y,2017-5754=Y,2018-12126=Y,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=N,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,
# 0x000306A9,2017-5715=Y,2017-5753=Y,2017-5754=Y,2018-12126=Y,2018-12127=Y,2018-12130=Y,2018-12207=Y,2018-3615=Y,2018-3620=Y,2018-3639=Y,2018-3640=Y,2018-3646=Y,2019-11135=N,2020-0543=Y,
# 0x000306C3,2017-5715=Y,2017-5753=Y,2017-5754=Y,2018-12126=Y,2018-12127=Y,2018-12130=Y,2018-12207=Y,2018-3615=Y,2018-3620=Y,2018-3639=Y,2018-3640=Y,2018-3646=Y,2019-11135=N,2020-0543=Y,
# 0x000306D4,2017-5715=Y,2017-5753=Y,2017-5754=Y,2018-12126=Y,2018-12127=Y,2018-12130=Y,2018-12207=Y,2018-3615=Y,2018-3620=Y,2018-3639=Y,2018-3640=Y,2018-3646=Y,2019-11135=Y,2020-0543=Y,
# 0x000306E4,2017-5715=Y,2017-5753=Y,2017-5754=Y,2018-12126=Y,2018-12127=Y,2018-12130=Y,2018-12207=Y,2018-3615=Y,2018-3620=Y,2018-3639=Y,2018-3640=Y,2018-3646=Y,2019-11135=N,2020-0543=N,
# 0x000306E7,2017-5715=Y,2017-5753=Y,2017-5754=Y,2018-12126=Y,2018-12127=Y,2018-12130=Y,2018-12207=Y,2018-3615=Y,2018-3620=Y,2018-3639=Y,2018-3640=Y,2018-3646=Y,2019-11135=N,2020-0543=N,
# 0x000306F2,2017-5715=MS,2017-5753=S,2017-5754=S,2018-12126=MS,2018-12127=MS,2018-12130=MS,2018-12207=S,2018-3615=MS,2018-3620=MS,2018-3639=MS,2018-3640=M,2018-3646=MS,2019-11135=N,2020-0543=N,2022-40982=N,
# 0x000306F4,2017-5715=MS,2017-5753=S,2017-5754=S,2018-12126=MS,2018-12127=MS,2018-12130=MS,2018-12207=S,2018-3615=MS,2018-3620=MS,2018-3639=MS,2018-3640=M,2018-3646=MS,2019-11135=MS,2020-0543=N,2022-40982=N,
# 0x00040651,2017-5715=Y,2017-5753=Y,2017-5754=Y,2018-12126=Y,2018-12127=Y,2018-12130=Y,2018-12207=Y,2018-3615=Y,2018-3620=Y,2018-3639=Y,2018-3640=Y,2018-3646=Y,2019-11135=N,2020-0543=Y,
# 0x00040661,2017-5715=Y,2017-5753=Y,2017-5754=Y,2018-12126=Y,2018-12127=Y,2018-12130=Y,2018-12207=Y,2018-3615=Y,2018-3620=Y,2018-3639=Y,2018-3640=Y,2018-3646=Y,2019-11135=N,2020-0543=Y,
# 0x00040671,2017-5715=Y,2017-5753=Y,2017-5754=Y,2018-12126=Y,2018-12127=Y,2018-12130=Y,2018-12207=Y,2018-3615=Y,2018-3620=Y,2018-3639=Y,2018-3640=Y,2018-3646=Y,2019-11135=Y,2020-0543=Y,
# 0x000406A0,2017-5715=Y,2017-5753=Y,2017-5754=Y,2018-12126=Y,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=N,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,
# 0x000406C3,2017-5715=Y,2017-5753=Y,2017-5754=Y,2018-12126=Y,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=N,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,
# 0x000406C4,2017-5715=Y,2017-5753=Y,2017-5754=Y,2018-12126=Y,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=N,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,
# 0x000406D8,2017-5715=Y,2017-5753=Y,2017-5754=Y,2018-12126=Y,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=N,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,
# 0x000406E3,2017-5715=MS,2017-5753=S,2017-5754=S,2018-12126=MS,2018-12127=MS,2018-12130=MS,2018-12207=S,2018-3615=MS,2018-3620=MS,2018-3639=MS,2018-3640=M,2018-3646=MS,2019-11135=MS,2020-0543=MS,
# 0x000406F1,2017-5715=MS,2017-5753=S,2017-5754=S,2018-12126=MS,2018-12127=MS,2018-12130=MS,2018-12207=S,2018-3615=MS,2018-3620=MS,2018-3639=MS,2018-3640=M,2018-3646=MS,2019-11135=MS,2020-0543=N,2022-40982=N,
# 0x00050653,2017-5715=MS,2017-5753=S,2017-5754=S,2018-12126=MS,2018-12127=MS,2018-12130=MS,2018-12207=S,2018-3615=MS,2018-3620=MS,2018-3639=MS,2018-3640=M,2018-3646=MS,2019-11135=MS,2020-0543=N,2022-40982=M,
# 0x00050654,2017-5715=MS,2017-5753=S,2017-5754=S,2018-12126=MS,2018-12127=MS,2018-12130=MS,2018-12207=S,2018-3615=MS,2018-3620=MS,2018-3639=MS,2018-3640=M,2018-3646=MS,2019-11135=MS,2020-0543=N,2022-40982=M,
# 0x00050656,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=S,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=MS,2020-0543=N,2022-40982=M,
# 0x00050657,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=S,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=MS,2020-0543=N,2022-40982=M,
# 0x0005065A,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=S,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=M,
# 0x0005065B,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=S,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=M,
# 0x00050662,2017-5715=Y,2017-5753=Y,2017-5754=Y,2018-12126=Y,2018-12127=Y,2018-12130=Y,2018-12207=Y,2018-3615=Y,2018-3620=Y,2018-3639=Y,2018-3640=Y,2018-3646=Y,2019-11135=Y,2020-0543=N,
# 0x00050663,2017-5715=MS,2017-5753=S,2017-5754=S,2018-12126=MS,2018-12127=MS,2018-12130=MS,2018-12207=S,2018-3615=MS,2018-3620=MS,2018-3639=MS,2018-3640=M,2018-3646=MS,2019-11135=MS,2020-0543=N,2022-40982=N,
# 0x00050664,2017-5715=MS,2017-5753=S,2017-5754=S,2018-12126=MS,2018-12127=MS,2018-12130=MS,2018-12207=S,2018-3615=MS,2018-3620=MS,2018-3639=MS,2018-3640=M,2018-3646=MS,2019-11135=MS,2020-0543=N,2022-40982=N,
# 0x00050665,2017-5715=MS,2017-5753=S,2017-5754=S,2018-12126=MS,2018-12127=MS,2018-12130=MS,2018-12207=S,2018-3615=MS,2018-3620=MS,2018-3639=MS,2018-3640=M,2018-3646=MS,2019-11135=MS,2020-0543=N,2022-40982=N,
# 0x000506A0,2017-5715=Y,2017-5753=Y,2017-5754=Y,2018-12126=Y,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=N,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,
# 0x000506C9,2017-5715=MS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=MS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=N,
# 0x000506CA,2017-5715=MS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=MS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=N,
# 0x000506D0,2017-5715=Y,2017-5753=Y,2017-5754=Y,2018-12126=Y,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=N,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,
# 0x000506E3,2017-5715=MS,2017-5753=S,2017-5754=S,2018-12126=MS,2018-12127=MS,2018-12130=MS,2018-12207=S,2018-3615=MS,2018-3620=MS,2018-3639=MS,2018-3640=M,2018-3646=MS,2019-11135=MS,2020-0543=MS,2022-40982=N,
# 0x000506F1,2017-5715=MS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=MS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=N,
# 0x00060650,2017-5715=Y,2017-5753=Y,2017-5754=Y,2018-12126=Y,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=N,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,
# 0x000606A0,2017-5715=Y,2017-5753=Y,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=Y,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,
# 0x000606A4,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=M,
# 0x000606A5,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=M,
# 0x000606A6,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=M,
# 0x000606C1,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=M,
# 0x000606E1,2017-5715=Y,2017-5753=Y,2017-5754=Y,2018-12126=Y,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=N,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,
# 0x0007065A,2017-5715=Y,2017-5753=Y,2017-5754=Y,2018-12126=Y,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=N,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,
# 0x000706A1,2017-5715=MS,2017-5753=S,2017-5754=S,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=MS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=N,
# 0x000706A8,2017-5715=MS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=N,
# 0x000706E5,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=HM,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=M,
# 0x00080660,2017-5715=Y,2017-5753=Y,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=Y,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,
# 0x00080664,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=N,
# 0x00080665,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=MS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=N,
# 0x00080667,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=MS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=N,
# 0x000806A0,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=HM,2018-12127=N,2018-12130=N,2018-12207=S,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=N,
# 0x000806A1,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=HM,2018-12127=N,2018-12130=N,2018-12207=S,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=N,
# 0x000806C0,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=M,
# 0x000806C1,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=M,
# 0x000806C2,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=M,
# 0x000806D0,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=M,
# 0x000806D1,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=M,
# 0x000806E9,2017-5715=MS,2017-5753=S,2017-5754=S,2018-12126=MS,2018-12127=MS,2018-12130=MS,2018-12207=S,2018-3615=MS,2018-3620=MS,2018-3639=MS,2018-3640=M,2018-3646=MS,2019-11135=MS,2020-0543=M,2022-40982=M,
# 0x000806EA,2017-5715=MS,2017-5753=S,2017-5754=S,2018-12126=MS,2018-12127=MS,2018-12130=MS,2018-12207=S,2018-3615=MS,2018-3620=MS,2018-3639=MS,2018-3640=M,2018-3646=MS,2019-11135=MS,2020-0543=MS,2022-40982=M,
# 0x000806EB,2017-5715=MS,2017-5753=S,2017-5754=N,2018-12126=MS,2018-12127=MS,2018-12130=MS,2018-12207=S,2018-3615=N,2018-3620=N,2018-3639=MS,2018-3640=M,2018-3646=N,2019-11135=MS,2020-0543=MS,2022-40982=M,
# 0x000806EC,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=S,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=MS,2020-0543=MS,2022-40982=M,
# 0x000806F7,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=N,
# 0x000806F8,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=N,
# 0x00090660,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=N,
# 0x00090661,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=N,
# 0x00090670,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=N,
# 0x00090671,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=N,
# 0x00090672,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=N,
# 0x00090673,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=N,
# 0x00090674,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=N,
# 0x00090675,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=MS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=N,
# 0x000906A0,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=MS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=N,
# 0x000906A2,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=MS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=N,
# 0x000906A3,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=MS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=N,
# 0x000906A4,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=MS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=N,
# 0x000906C0,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=N,
# 0x000906E9,2017-5715=MS,2017-5753=S,2017-5754=S,2018-12126=MS,2018-12127=MS,2018-12130=MS,2018-12207=S,2018-3615=MS,2018-3620=MS,2018-3639=MS,2018-3640=M,2018-3646=MS,2019-11135=MS,2020-0543=MS,2022-40982=M,
# 0x000906EA,2017-5715=MS,2017-5753=S,2017-5754=S,2018-12126=MS,2018-12127=MS,2018-12130=MS,2018-12207=S,2018-3615=MS,2018-3620=MS,2018-3639=MS,2018-3640=M,2018-3646=MS,2019-11135=MS,2020-0543=MS,2022-40982=M,
# 0x000906EB,2017-5715=MS,2017-5753=S,2017-5754=S,2018-12126=MS,2018-12127=MS,2018-12130=MS,2018-12207=S,2018-3615=MS,2018-3620=MS,2018-3639=MS,2018-3640=M,2018-3646=MS,2019-11135=MS,2020-0543=MS,2022-40982=M,
# 0x000906EC,2017-5715=MS,2017-5753=S,2017-5754=N,2018-12126=MS,2018-12127=MS,2018-12130=MS,2018-12207=S,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=M,2018-3646=N,2019-11135=MS,2020-0543=MS,2022-40982=M,
# 0x000906ED,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=S,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=M,2018-3646=N,2019-11135=MS,2020-0543=MS,2022-40982=M,
# 0x000A0650,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=S,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=M,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=M,
# 0x000A0651,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=S,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=M,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=M,
# 0x000A0652,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=S,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=M,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=M,
# 0x000A0653,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=S,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=M,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=M,
# 0x000A0655,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=S,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=M,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=M,
# 0x000A0660,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=S,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=M,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=M,
# 0x000A0661,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=S,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=M,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=M,
# 0x000A0670,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=M,
# 0x000A0671,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=M,
# 0x000A0680,2017-5715=Y,2017-5753=Y,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=Y,2018-3615=N,2018-3620=N,2018-3639=Y,2018-3640=Y,2018-3646=N,2019-11135=N,2020-0543=N,
# 0x000B0671,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=N,
# 0x000B06A2,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=N,
# 0x000B06A3,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=N,
# 0x000B06F2,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=N,
# 0x000B06F5,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=N,
# %%% ENDOFINTELDB

# We're using MCE.db from the excellent platomav's MCExtractor project
# The builtin version follows, but the user can download an up-to-date copy (to be stored in their $HOME) by using --update-fwdb
# To update the builtin version itself (by *modifying* this very file), use --update-builtin-fwdb
#
# The format below is:
# X,CPUID_HEX,MICROCODE_VERSION_HEX,YYYYMMDD
# with X being either I for Intel, or A for AMD
# When the date is unknown it defaults to 20000101

# %%% MCEDB v296+i20240514+988c
# I,0x00000611,0xFF,0x00000B27,19961218
# I,0x00000612,0xFF,0x000000C6,19961210
# I,0x00000616,0xFF,0x000000C6,19961210
# I,0x00000617,0xFF,0x000000C6,19961210
# I,0x00000619,0xFF,0x000000D2,19980218
# I,0x00000630,0xFF,0x00000013,19960827
# I,0x00000632,0xFF,0x00000020,19960903
# I,0x00000633,0xFF,0x00000036,19980923
# I,0x00000634,0xFF,0x00000037,19980923
# I,0x00000650,0x01,0x00000040,19990525
# I,0x00000650,0x02,0x00000041,19990525
# I,0x00000650,0x08,0x00000045,19990525
# I,0x00000651,0x01,0x00000040,19990525
# I,0x00000652,0x01,0x0000002A,19990512
# I,0x00000652,0x02,0x0000002C,19990517
# I,0x00000652,0x04,0x0000002B,19990512
# I,0x00000653,0x01,0x00000010,19990628
# I,0x00000653,0x02,0x0000000C,19990518
# I,0x00000653,0x04,0x0000000B,19990520
# I,0x00000653,0x08,0x0000000D,19990518
# I,0x00000660,0x01,0x0000000A,19990505
# I,0x00000665,0x10,0x00000003,19990505
# I,0x0000066A,0x02,0x0000000C,19990505
# I,0x0000066A,0x08,0x0000000D,19990505
# I,0x0000066A,0x20,0x0000000B,19990505
# I,0x0000066D,0x02,0x00000005,19990312
# I,0x0000066D,0x08,0x00000006,19990312
# I,0x0000066D,0x20,0x00000007,19990505
# I,0x00000670,0xFF,0x00000007,19980602
# I,0x00000671,0x04,0x00000014,19980811
# I,0x00000672,0x04,0x00000038,19990922
# I,0x00000673,0x04,0x0000002E,19990910
# I,0x00000680,0xFF,0x00000017,19990610
# I,0x00000681,0x01,0x0000000D,19990921
# I,0x00000681,0x04,0x00000010,19990921
# I,0x00000681,0x08,0x0000000F,19990921
# I,0x00000681,0x10,0x00000011,19990921
# I,0x00000681,0x20,0x0000000E,19990921
# I,0x00000683,0x08,0x00000008,19991015
# I,0x00000683,0x20,0x00000007,19991015
# I,0x00000686,0x01,0x00000007,20000505
# I,0x00000686,0x02,0x0000000A,20000504
# I,0x00000686,0x04,0x00000002,20000504
# I,0x00000686,0x10,0x00000008,20000505
# I,0x00000686,0x80,0x0000000C,20000504
# I,0x0000068A,0x10,0x00000001,20001102
# I,0x0000068A,0x20,0x00000004,20001207
# I,0x0000068A,0x80,0x00000005,20001207
# I,0x00000690,0xFF,0x00000004,20000206
# I,0x00000691,0xFF,0x00000001,20020527
# I,0x00000692,0xFF,0x00000001,20020620
# I,0x00000694,0xFF,0x00000002,20020926
# I,0x00000695,0x10,0x00000007,20041109
# I,0x00000695,0x20,0x00000007,20041109
# I,0x00000695,0x80,0x00000047,20041109
# I,0x00000696,0xFF,0x00000001,20000707
# I,0x000006A0,0x04,0x00000003,20000110
# I,0x000006A1,0x04,0x00000001,20000306
# I,0x000006A4,0xFF,0x00000001,20000616
# I,0x000006B0,0xFF,0x0000001A,20010129
# I,0x000006B1,0x10,0x0000001C,20010215
# I,0x000006B1,0x20,0x0000001D,20010220
# I,0x000006B4,0x10,0x00000001,20020110
# I,0x000006B4,0x20,0x00000002,20020111
# I,0x000006D0,0xFF,0x00000006,20030522
# I,0x000006D1,0xFF,0x00000009,20030709
# I,0x000006D2,0xFF,0x00000010,20030814
# I,0x000006D6,0x20,0x00000018,20041017
# I,0x000006D8,0xFF,0x00000021,20060831
# I,0x000006E0,0xFF,0x00000008,20050215
# I,0x000006E1,0xFF,0x0000000C,20050413
# I,0x000006E4,0xFF,0x00000026,20050816
# I,0x000006E8,0x20,0x00000039,20051115
# I,0x000006EC,0x20,0x00000054,20060501
# I,0x000006EC,0x80,0x00000059,20060912
# I,0x000006F0,0xFF,0x00000005,20050818
# I,0x000006F1,0xFF,0x00000012,20051129
# I,0x000006F2,0x01,0x0000005D,20101002
# I,0x000006F2,0x20,0x0000005C,20101002
# I,0x000006F4,0xFF,0x00000028,20060417
# I,0x000006F5,0xFF,0x00000039,20060727
# I,0x000006F6,0x01,0x000000D0,20100930
# I,0x000006F6,0x04,0x000000D2,20101001
# I,0x000006F6,0x20,0x000000D1,20101001
# I,0x000006F7,0x10,0x0000006A,20101002
# I,0x000006F7,0x40,0x0000006B,20101002
# I,0x000006F9,0xFF,0x00000084,20061012
# I,0x000006FA,0x80,0x00000095,20101002
# I,0x000006FB,0x01,0x000000BA,20101003
# I,0x000006FB,0x04,0x000000BC,20101003
# I,0x000006FB,0x08,0x000000BB,20101003
# I,0x000006FB,0x10,0x000000BA,20101003
# I,0x000006FB,0x20,0x000000BA,20101003
# I,0x000006FB,0x40,0x000000BC,20101003
# I,0x000006FB,0x80,0x000000BA,20101003
# I,0x000006FD,0x01,0x000000A4,20101002
# I,0x000006FD,0x20,0x000000A4,20101002
# I,0x000006FD,0x80,0x000000A4,20101002
# I,0x00000F00,0xFF,0xFFFF0001,20000130
# I,0x00000F01,0xFF,0xFFFF0007,20000404
# I,0x00000F02,0xFF,0xFFFF000B,20000518
# I,0x00000F03,0xFF,0xFFFF0001,20000518
# I,0x00000F04,0xFF,0xFFFF0010,20000803
# I,0x00000F05,0xFF,0x0000000C,20000824
# I,0x00000F06,0xFF,0x00000004,20000911
# I,0x00000F07,0x01,0x00000012,20020716
# I,0x00000F07,0x02,0x00000008,20001115
# I,0x00000F08,0xFF,0x00000008,20001101
# I,0x00000F09,0xFF,0x00000008,20010104
# I,0x00000F0A,0x01,0x00000013,20020716
# I,0x00000F0A,0x02,0x00000015,20020821
# I,0x00000F0A,0x04,0x00000014,20020716
# I,0x00000F11,0xFF,0x0000000A,20030729
# I,0x00000F12,0x04,0x0000002E,20030502
# I,0x00000F13,0xFF,0x00000005,20030508
# I,0x00000F20,0xFF,0x00000001,20010423
# I,0x00000F21,0xFF,0x00000003,20010529
# I,0x00000F22,0xFF,0x00000005,20030729
# I,0x00000F23,0xFF,0x0000000D,20010817
# I,0x00000F24,0x02,0x0000001F,20030605
# I,0x00000F24,0x04,0x0000001E,20030605
# I,0x00000F24,0x10,0x00000021,20030610
# I,0x00000F25,0x01,0x00000029,20040811
# I,0x00000F25,0x02,0x0000002A,20040811
# I,0x00000F25,0x04,0x0000002B,20040811
# I,0x00000F25,0x10,0x0000002C,20040826
# I,0x00000F26,0x02,0x00000010,20040805
# I,0x00000F27,0x02,0x00000038,20030604
# I,0x00000F27,0x04,0x00000037,20030604
# I,0x00000F27,0x08,0x00000039,20030604
# I,0x00000F29,0x02,0x0000002D,20040811
# I,0x00000F29,0x04,0x0000002E,20040811
# I,0x00000F29,0x08,0x0000002F,20040811
# I,0x00000F30,0xFF,0x00000013,20030815
# I,0x00000F31,0xFF,0x0000000B,20031021
# I,0x00000F32,0x0D,0x0000000A,20040511
# I,0x00000F33,0x0D,0x0000000C,20050421
# I,0x00000F34,0x1D,0x00000017,20050421
# I,0x00000F36,0xFF,0x00000007,20040309
# I,0x00000F37,0xFF,0x00000003,20031218
# I,0x00000F40,0xFF,0x00000006,20040318
# I,0x00000F41,0x02,0x00000016,20050421
# I,0x00000F41,0xBD,0x00000017,20050422
# I,0x00000F42,0xFF,0x00000003,20050421
# I,0x00000F43,0x9D,0x00000005,20050421
# I,0x00000F44,0x9D,0x00000006,20050421
# I,0x00000F46,0xFF,0x00000004,20050411
# I,0x00000F47,0x9D,0x00000003,20050421
# I,0x00000F48,0x01,0x0000000C,20060508
# I,0x00000F48,0x02,0x0000000E,20080115
# I,0x00000F48,0x5F,0x00000007,20050630
# I,0x00000F49,0xBD,0x00000003,20050421
# I,0x00000F4A,0x5C,0x00000004,20051214
# I,0x00000F4A,0x5D,0x00000002,20050610
# I,0x00000F60,0xFF,0x00000005,20050124
# I,0x00000F61,0xFF,0x00000008,20050610
# I,0x00000F62,0x04,0x0000000F,20051215
# I,0x00000F63,0xFF,0x00000005,20051010
# I,0x00000F64,0x01,0x00000002,20051215
# I,0x00000F64,0x34,0x00000004,20051223
# I,0x00000F65,0x01,0x00000008,20060426
# I,0x00000F66,0xFF,0x0000001B,20060310
# I,0x00000F68,0x22,0x00000009,20060714
# I,0x00001632,0x00,0x00000002,19980610
# I,0x00010650,0xFF,0x00000002,20060513
# I,0x00010660,0xFF,0x00000004,20060612
# I,0x00010661,0x01,0x00000043,20101004
# I,0x00010661,0x02,0x00000042,20101004
# I,0x00010661,0x80,0x00000044,20101004
# I,0x00010670,0xFF,0x00000005,20070209
# I,0x00010671,0xFF,0x00000106,20070329
# I,0x00010674,0xFF,0x84050100,20070726
# I,0x00010676,0x01,0x0000060F,20100929
# I,0x00010676,0x04,0x0000060F,20100929
# I,0x00010676,0x10,0x0000060F,20100929
# I,0x00010676,0x40,0x0000060F,20100929
# I,0x00010676,0x80,0x0000060F,20100929
# I,0x00010677,0x10,0x0000070A,20100929
# I,0x0001067A,0x11,0x00000A0B,20100928
# I,0x0001067A,0x44,0x00000A0B,20100928
# I,0x0001067A,0xA0,0x00000A0B,20100928
# I,0x000106A0,0xFF,0xFFFF001A,20071128
# I,0x000106A1,0xFF,0xFFFF000B,20080220
# I,0x000106A2,0xFF,0xFFFF0019,20080714
# I,0x000106A4,0x03,0x00000012,20130621
# I,0x000106A5,0x03,0x0000001D,20180511
# I,0x000106C0,0xFF,0x00000007,20070824
# I,0x000106C1,0xFF,0x00000109,20071203
# I,0x000106C2,0x01,0x00000217,20090410
# I,0x000106C2,0x04,0x00000218,20090410
# I,0x000106C2,0x08,0x00000219,20090410
# I,0x000106C9,0xFF,0x00000007,20090213
# I,0x000106CA,0x01,0x00000107,20090825
# I,0x000106CA,0x04,0x00000107,20090825
# I,0x000106CA,0x08,0x00000107,20090825
# I,0x000106CA,0x10,0x00000107,20090825
# I,0x000106D0,0xFF,0x00000005,20071204
# I,0x000106D1,0x08,0x00000029,20100930
# I,0x000106E0,0xFF,0xFFFF0022,20090116
# I,0x000106E1,0xFF,0xFFFF000D,20090206
# I,0x000106E2,0xFF,0xFFFF0011,20090924
# I,0x000106E3,0xFF,0xFFFF0011,20090512
# I,0x000106E4,0xFF,0x00000003,20130701
# I,0x000106E5,0x13,0x0000000A,20180508
# I,0x000106F0,0xFF,0xFFFF0009,20090210
# I,0x000106F1,0xFF,0xFFFF0007,20090210
# I,0x00020650,0xFF,0xFFFF0008,20090218
# I,0x00020651,0xFF,0xFFFF0018,20090818
# I,0x00020652,0x12,0x00000011,20180508
# I,0x00020654,0xFF,0xFFFF0007,20091124
# I,0x00020655,0x92,0x00000007,20180423
# I,0x00020661,0x01,0x00000104,20091023
# I,0x00020661,0x02,0x00000105,20110718
# I,0x000206A0,0xFF,0x00000029,20091102
# I,0x000206A1,0xFF,0x00000007,20091223
# I,0x000206A2,0xFF,0x00000027,20100502
# I,0x000206A3,0xFF,0x00000009,20100609
# I,0x000206A4,0xFF,0x00000022,20100414
# I,0x000206A5,0xFF,0x00000007,20100722
# I,0x000206A6,0xFF,0x90030028,20100924
# I,0x000206A7,0x12,0x0000002F,20190217
# I,0x000206C0,0xFF,0xFFFF001C,20091214
# I,0x000206C1,0xFF,0x00000006,20091222
# I,0x000206C2,0x03,0x0000001F,20180508
# I,0x000206D0,0xFF,0x80000006,20100816
# I,0x000206D1,0xFF,0x80000106,20101201
# I,0x000206D2,0xFF,0xAF506958,20110714
# I,0x000206D3,0xFF,0xAF50696A,20110816
# I,0x000206D5,0xFF,0xAF5069E5,20120118
# I,0x000206D6,0x6D,0x00000621,20200304
# I,0x000206D7,0x6D,0x0000071A,20200324
# I,0x000206E0,0xFF,0xE3493401,20090108
# I,0x000206E1,0xFF,0xE3493402,20090224
# I,0x000206E2,0xFF,0xFFFF0004,20081001
# I,0x000206E3,0xFF,0xE4486547,20090701
# I,0x000206E4,0xFF,0xFFFF0008,20090619
# I,0x000206E5,0xFF,0xFFFF0018,20091215
# I,0x000206E6,0x04,0x0000000D,20180515
# I,0x000206F0,0xFF,0x00000005,20100729
# I,0x000206F1,0xFF,0x00000008,20101013
# I,0x000206F2,0x05,0x0000003B,20180516
# I,0x00030650,0xFF,0x00000009,20120118
# I,0x00030651,0xFF,0x00000110,20131014
# I,0x00030660,0xFF,0x00000003,20101103
# I,0x00030661,0xFF,0x0000010F,20150721
# I,0x00030669,0xFF,0x0000010D,20130515
# I,0x00030671,0xFF,0x00000117,20130410
# I,0x00030672,0xFF,0x0000022E,20140401
# I,0x00030673,0xFF,0x83290100,20190916
# I,0x00030678,0x02,0x00000838,20190422
# I,0x00030678,0x0C,0x00000838,20190422
# I,0x00030679,0x0F,0x0000090D,20190710
# I,0x000306A0,0xFF,0x00000007,20110407
# I,0x000306A2,0xFF,0x0000000C,20110725
# I,0x000306A4,0xFF,0x00000007,20110908
# I,0x000306A5,0xFF,0x00000009,20111110
# I,0x000306A6,0xFF,0x00000004,20111114
# I,0x000306A8,0xFF,0x00000010,20120220
# I,0x000306A9,0x12,0x00000021,20190213
# I,0x000306C0,0xFF,0xFFFF0013,20111110
# I,0x000306C1,0xFF,0xFFFF0014,20120725
# I,0x000306C2,0xFF,0xFFFF0006,20121017
# I,0x000306C3,0x32,0x00000028,20191112
# I,0x000306D1,0xFF,0xFFFF0009,20131015
# I,0x000306D2,0xFF,0xFFFF0009,20131219
# I,0x000306D3,0xFF,0xE3121338,20140825
# I,0x000306D4,0xC0,0x0000002F,20191112
# I,0x000306E0,0xFF,0xE920080F,20121113
# I,0x000306E2,0xFF,0xE9220827,20130523
# I,0x000306E3,0xFF,0x00000308,20130321
# I,0x000306E4,0xED,0x0000042E,20190314
# I,0x000306E6,0xED,0x00000600,20130619
# I,0x000306E7,0xED,0x00000715,20190314
# I,0x000306F0,0xFF,0xFFFF0017,20130730
# I,0x000306F1,0xFF,0xD141D629,20140416
# I,0x000306F2,0x6F,0x00000049,20210811
# I,0x000306F3,0xFF,0x0000000D,20160211
# I,0x000306F4,0x80,0x0000001A,20210524
# I,0x00040650,0xFF,0xFFFF000B,20121206
# I,0x00040651,0x72,0x00000026,20191112
# I,0x00040660,0xFF,0xFFFF0011,20121012
# I,0x00040661,0x32,0x0000001C,20191112
# I,0x00040670,0xFF,0xFFFF0006,20140304
# I,0x00040671,0x22,0x00000022,20191112
# I,0x000406A0,0xFF,0x80124001,20130521
# I,0x000406A8,0xFF,0x0000081F,20140812
# I,0x000406A9,0xFF,0x0000081F,20140812
# I,0x000406C1,0xFF,0x0000010B,20140814
# I,0x000406C2,0xFF,0x00000221,20150218
# I,0x000406C3,0x01,0x00000368,20190423
# I,0x000406C4,0x01,0x00000411,20190423
# I,0x000406D0,0xFF,0x0000000E,20130612
# I,0x000406D8,0x01,0x0000012D,20190916
# I,0x000406E1,0xFF,0x00000020,20141111
# I,0x000406E2,0xFF,0x0000002C,20150521
# I,0x000406E3,0xC0,0x000000F0,20211112
# I,0x000406E8,0xFF,0x00000026,20160414
# I,0x000406F0,0xFF,0x00000014,20150702
# I,0x000406F1,0xFF,0x0B000040,20210519
# I,0x00050650,0xFF,0x8000002B,20160208
# I,0x00050651,0xFF,0x8000002B,20160208
# I,0x00050652,0xFF,0x80000037,20170502
# I,0x00050653,0x97,0x01000191,20230728
# I,0x00050654,0xB7,0x02007006,20230306
# I,0x00050655,0xB7,0x03000010,20181116
# I,0x00050656,0xBF,0x04003605,20230728
# I,0x00050657,0xBF,0x05003605,20230728
# I,0x0005065A,0xFF,0x86002302,20210416
# I,0x0005065B,0xBF,0x07002802,20230803
# I,0x00050661,0xFF,0xF1000008,20150130
# I,0x00050662,0x10,0x0000001C,20190617
# I,0x00050663,0x10,0x0700001C,20210612
# I,0x00050664,0x10,0x0F00001A,20210612
# I,0x00050665,0x10,0x0E000015,20230803
# I,0x00050670,0xFF,0xFFFF0030,20151113
# I,0x00050671,0xFF,0x000001B6,20180108
# I,0x000506A0,0xFF,0x00000038,20150112
# I,0x000506C0,0xFF,0x00000002,20140613
# I,0x000506C2,0x01,0x00000014,20180511
# I,0x000506C8,0xFF,0x90011010,20160323
# I,0x000506C9,0x03,0x00000048,20211116
# I,0x000506CA,0x03,0x00000028,20211116
# I,0x000506D1,0xFF,0x00000102,20150605
# I,0x000506E0,0xFF,0x00000018,20141119
# I,0x000506E1,0xFF,0x0000002A,20150602
# I,0x000506E2,0xFF,0x0000002E,20150815
# I,0x000506E3,0x36,0x000000F0,20211112
# I,0x000506E8,0xFF,0x00000034,20160710
# I,0x000506F0,0xFF,0x00000010,20160607
# I,0x000506F1,0x01,0x0000003E,20231005
# I,0x00060660,0xFF,0x0000000C,20160821
# I,0x00060661,0xFF,0x0000000E,20170128
# I,0x00060662,0xFF,0x00000022,20171129
# I,0x00060663,0x80,0x0000002A,20180417
# I,0x000606A0,0xFF,0x80000031,20200308
# I,0x000606A4,0xFF,0x0B000280,20200817
# I,0x000606A5,0x87,0x0C0002F0,20210308
# I,0x000606A6,0x87,0x0D0003D1,20230914
# I,0x000606C0,0xFF,0xFD000220,20210629
# I,0x000606C1,0x10,0x01000290,20231205
# I,0x000606E0,0xFF,0x0000000B,20161104
# I,0x000606E1,0xFF,0x00000108,20190423
# I,0x000606E4,0xFF,0x0000000C,20190124
# I,0x000706A0,0xFF,0x00000026,20170712
# I,0x000706A1,0x01,0x00000040,20230825
# I,0x000706A8,0x01,0x00000024,20230825
# I,0x000706E0,0xFF,0x0000002C,20180614
# I,0x000706E1,0xFF,0x00000042,20190420
# I,0x000706E2,0xFF,0x00000042,20190420
# I,0x000706E3,0xFF,0x81000008,20181002
# I,0x000706E4,0xFF,0x00000046,20190905
# I,0x000706E5,0x80,0x000000C4,20230914
# I,0x00080650,0xFF,0x00000018,20180108
# I,0x00080664,0xFF,0x4C000025,20230926
# I,0x00080665,0xFF,0x4C000025,20230926
# I,0x00080667,0xFF,0x4C000025,20230926
# I,0x000806A0,0xFF,0x00000010,20190507
# I,0x000806A1,0x10,0x00000033,20230113
# I,0x000806C0,0xFF,0x00000068,20200402
# I,0x000806C1,0x80,0x000000B6,20230913
# I,0x000806C2,0xC2,0x00000036,20230913
# I,0x000806D0,0xFF,0x00000054,20210507
# I,0x000806D1,0xC2,0x00000050,20230913
# I,0x000806E9,0x10,0x000000F4,20230223
# I,0x000806E9,0xC0,0x000000F4,20230222
# I,0x000806EA,0xC0,0x000000F4,20230223
# I,0x000806EB,0xD0,0x000000F4,20230223
# I,0x000806EC,0x94,0x000000FA,20230716
# I,0x000806F1,0xFF,0x800003C0,20220327
# I,0x000806F2,0xFF,0x8C0004E0,20211112
# I,0x000806F3,0xFF,0x8D000520,20220812
# I,0x000806F4,0x10,0x2C000390,20240205
# I,0x000806F4,0x87,0x2B0005C0,20240205
# I,0x000806F5,0x10,0x2C000390,20240205
# I,0x000806F5,0x87,0x2B0005C0,20240205
# I,0x000806F6,0x10,0x2C000390,20240205
# I,0x000806F6,0x87,0x2B0005C0,20240205
# I,0x000806F7,0x87,0x2B0005C0,20240205
# I,0x000806F8,0x10,0x2C000390,20240205
# I,0x000806F8,0x87,0x2B0005C0,20240205
# I,0x00090660,0xFF,0x00000009,20200617
# I,0x00090661,0x01,0x00000019,20230926
# I,0x00090670,0xFF,0x00000019,20201111
# I,0x00090671,0xFF,0x0000001C,20210614
# I,0x00090672,0x07,0x00000035,20231205
# I,0x00090674,0xFF,0x00000219,20210425
# I,0x00090675,0x07,0x00000035,20231205
# I,0x000906A0,0xFF,0x0000001C,20210614
# I,0x000906A1,0xFF,0x0000011F,20211104
# I,0x000906A2,0xFF,0x00000315,20220102
# I,0x000906A3,0x80,0x00000433,20231205
# I,0x000906A4,0x40,0x00000007,20231207
# I,0x000906A4,0x80,0x00000433,20231205
# I,0x000906C0,0x01,0x24000026,20230926
# I,0x000906E9,0x2A,0x000000F8,20230928
# I,0x000906EA,0x22,0x000000F6,20230726
# I,0x000906EB,0x02,0x000000F4,20230223
# I,0x000906EC,0x22,0x000000F6,20230726
# I,0x000906ED,0x22,0x000000FC,20230727
# I,0x000A0650,0xFF,0x000000BE,20191010
# I,0x000A0651,0xFF,0x000000C2,20191113
# I,0x000A0652,0x20,0x000000FA,20230716
# I,0x000A0653,0x22,0x000000FA,20230716
# I,0x000A0654,0xFF,0x000000C6,20200123
# I,0x000A0655,0x22,0x000000FA,20230716
# I,0x000A0660,0x80,0x000000FA,20230716
# I,0x000A0661,0x80,0x000000FA,20230716
# I,0x000A0670,0xFF,0x0000002C,20201124
# I,0x000A0671,0x02,0x0000005E,20230914
# I,0x000A0680,0xFF,0x80000002,20200121
# I,0x000A06A1,0xFF,0x00000017,20230518
# I,0x000A06A2,0xFF,0x00000011,20230627
# I,0x000A06A4,0xE6,0x0000001C,20240103
# I,0x000A06C0,0xFF,0x00000011,20230725
# I,0x000B0670,0xFF,0x0000000E,20220220
# I,0x000B0671,0x32,0x00000123,20240125
# I,0x000B06A2,0xE0,0x00004121,20231207
# I,0x000B06A3,0xE0,0x00004121,20231207
# I,0x000B06A8,0xE0,0x00004121,20231207
# I,0x000B06E0,0x11,0x00000017,20231207
# I,0x000B06F2,0x07,0x00000035,20231205
# I,0x000B06F5,0x07,0x00000035,20231205
# I,0x000C06F1,0x87,0x21000230,20240205
# I,0x000C06F2,0x87,0x21000230,20240205
# I,0x00FF0671,0xFF,0x00000104,20220419
# A,0x00000F00,0xFF,0x02000008,20070614
# A,0x00000F01,0xFF,0x0000001C,20021031
# A,0x00000F10,0xFF,0x00000003,20020325
# A,0x00000F11,0xFF,0x0000001F,20030220
# A,0x00000F48,0xFF,0x00000046,20040719
# A,0x00000F4A,0xFF,0x00000047,20040719
# A,0x00000F50,0xFF,0x00000024,20021212
# A,0x00000F51,0xFF,0x00000025,20030115
# A,0x00010F50,0xFF,0x00000041,20040225
# A,0x00020F10,0xFF,0x0000004D,20050428
# A,0x00040F01,0xFF,0xC0012102,20050916
# A,0x00040F0A,0xFF,0x00000068,20060920
# A,0x00040F13,0xFF,0x0000007A,20080508
# A,0x00040F14,0xFF,0x00000062,20060127
# A,0x00040F1B,0xFF,0x0000006D,20060920
# A,0x00040F33,0xFF,0x0000007B,20080514
# A,0x00060F80,0xFF,0x00000083,20060929
# A,0x000C0F1B,0xFF,0x0000006E,20060921
# A,0x000F0F00,0xFF,0x00000005,20020627
# A,0x000F0F01,0xFF,0x00000015,20020627
# A,0x00100F00,0xFF,0x01000020,20070326
# A,0x00100F20,0xFF,0x010000CA,20100331
# A,0x00100F22,0xFF,0x010000C9,20100331
# A,0x00100F2A,0xFF,0x01000084,20000101
# A,0x00100F40,0xFF,0x01000085,20080501
# A,0x00100F41,0xFF,0x010000DB,20111024
# A,0x00100F42,0xFF,0x01000092,20081021
# A,0x00100F43,0xFF,0x010000C8,20100311
# A,0x00100F52,0xFF,0x010000DB,20000101
# A,0x00100F53,0xFF,0x010000C8,20000101
# A,0x00100F62,0xFF,0x010000C7,20100311
# A,0x00100F80,0xFF,0x010000DA,20111024
# A,0x00100F81,0xFF,0x010000D9,20111012
# A,0x00100F91,0xFF,0x010000D9,20000101
# A,0x00100FA0,0xFF,0x010000DC,20111024
# A,0x00120F00,0xFF,0x03000002,20100324
# A,0x00200F30,0xFF,0x02000018,20070921
# A,0x00200F31,0xFF,0x02000057,20080502
# A,0x00200F32,0xFF,0x02000034,20080307
# A,0x00300F01,0xFF,0x0300000E,20101004
# A,0x00300F10,0xFF,0x03000027,20111209
# A,0x00500F00,0xFF,0x0500000B,20100601
# A,0x00500F01,0xFF,0x0500001A,20100908
# A,0x00500F10,0xFF,0x05000029,20130121
# A,0x00500F20,0xFF,0x05000119,20130118
# A,0x00580F00,0xFF,0x0500000B,20100601
# A,0x00580F01,0xFF,0x0500001A,20100908
# A,0x00580F10,0xFF,0x05000028,20101124
# A,0x00580F20,0xFF,0x05000103,20110526
# A,0x00600F00,0xFF,0x06000017,20101029
# A,0x00600F01,0xFF,0x0600011F,20110227
# A,0x00600F10,0xFF,0x06000425,20110408
# A,0x00600F11,0xFF,0x0600050D,20110627
# A,0x00600F12,0xFF,0x0600063E,20180207
# A,0x00600F20,0xFF,0x06000852,20180206
# A,0x00610F00,0xFF,0x0600100E,20111102
# A,0x00610F01,0xFF,0x0600111F,20180305
# A,0x00630F00,0xFF,0x0600301C,20130817
# A,0x00630F01,0xFF,0x06003109,20180227
# A,0x00660F00,0xFF,0x06006108,20150302
# A,0x00660F01,0xFF,0x0600611A,20180126
# A,0x00670F00,0xFF,0x06006705,20180220
# A,0x00680F00,0xFF,0x06000017,20101029
# A,0x00680F01,0xFF,0x0600011F,20110227
# A,0x00680F10,0xFF,0x06000410,20110314
# A,0x00690F00,0xFF,0x06001009,20110613
# A,0x00700F00,0xFF,0x0700002A,20121218
# A,0x00700F01,0xFF,0x07000110,20180209
# A,0x00730F00,0xFF,0x07030009,20131206
# A,0x00730F01,0xFF,0x07030106,20180209
# A,0x00800F00,0xFF,0x0800002A,20161006
# A,0x00800F10,0xFF,0x0800100C,20170131
# A,0x00800F11,0xFF,0x08001138,20190204
# A,0x00800F12,0xFF,0x0800126E,20211111
# A,0x00800F82,0xFF,0x0800820D,20190416
# A,0x00810F00,0xFF,0x08100004,20161120
# A,0x00810F10,0xFF,0x08101016,20190430
# A,0x00810F11,0xFF,0x08101103,20190417
# A,0x00810F80,0xFF,0x08108002,20180605
# A,0x00810F81,0xFF,0x08108109,20190417
# A,0x00820F00,0xFF,0x08200002,20180214
# A,0x00820F01,0xFF,0x08200103,20190417
# A,0x00830F00,0xFF,0x08300027,20190401
# A,0x00830F10,0xFF,0x0830107B,20230816
# A,0x00850F00,0xFF,0x08500004,20180212
# A,0x00860F00,0xFF,0x0860000E,20200127
# A,0x00860F01,0xFF,0x0860010C,20231007
# A,0x00860F81,0xFF,0x08608104,20220328
# A,0x00870F00,0xFF,0x08700004,20181206
# A,0x00870F10,0xFF,0x08701033,20231006
# A,0x00880F40,0xFF,0x08804005,20210312
# A,0x00890F00,0xFF,0x08900007,20200921
# A,0x00890F01,0xFF,0x08900103,20201105
# A,0x00890F02,0xFF,0x08900203,20230915
# A,0x00890F10,0xFF,0x08901003,20230919
# A,0x008A0F00,0xFF,0x08A00009,20230814
# A,0x00A00F00,0xFF,0x0A000033,20200413
# A,0x00A00F10,0xFF,0x0A001079,20230609
# A,0x00A00F11,0xFF,0x0A0011D3,20230823
# A,0x00A00F12,0xFF,0x0A001236,20230831
# A,0x00A00F80,0xFF,0x0A008005,20230707
# A,0x00A00F82,0xFF,0x0A008209,20230707
# A,0x00A10F00,0xFF,0x0A10004B,20220309
# A,0x00A10F01,0xFF,0x0A100104,20220207
# A,0x00A10F0B,0xFF,0x0A100B07,20220610
# A,0x00A10F10,0xFF,0x0A101020,20220913
# A,0x00A10F11,0xFF,0x0A101144,20230906
# A,0x00A10F12,0xFF,0x0A101244,20230911
# A,0x00A10F80,0xFF,0x0A108005,20230613
# A,0x00A10F81,0xFF,0x0A108105,20230711
# A,0x00A20F00,0xFF,0x0A200025,20200121
# A,0x00A20F10,0xFF,0x0A20102B,20230707
# A,0x00A20F12,0xFF,0x0A20120E,20230707
# A,0x00A40F00,0xFF,0x0A400016,20210330
# A,0x00A40F40,0xFF,0x0A404002,20210408
# A,0x00A40F41,0xFF,0x0A404105,20230707
# A,0x00A50F00,0xFF,0x0A50000F,20230707
# A,0x00A60F00,0xFF,0x0A600005,20211220
# A,0x00A60F11,0xFF,0x0A601119,20230613
# A,0x00A60F12,0xFF,0x0A601206,20230613
# A,0x00A70F00,0xFF,0x0A700003,20220517
# A,0x00A70F40,0xFF,0x0A704001,20220721
# A,0x00A70F41,0xFF,0x0A704104,20230713
# A,0x00A70F42,0xFF,0x0A704202,20230713
# A,0x00A70F52,0xFF,0x0A705205,20240112
# A,0x00A70F80,0xFF,0x0A708006,20240112
# A,0x00A70FC0,0xFF,0x0A70C002,20230713
# A,0x00AA0F00,0xFF,0x0AA00009,20221006
# A,0x00AA0F01,0xFF,0x0AA00116,20230619
# A,0x00AA0F02,0xFF,0x0AA00213,20230911
# A,0x00B40F00,0xFF,0x0B40002D,20231027
# A,0x00B40F40,0xFF,0x0B40400C,20240327
