blob: 4e2da04cd3d5b217005272e6d340c7986180f0dd [file] [log] [blame]
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/win/hardware_check.h"
#include <windows.h>
#include <winternl.h>
#include <tbs.h>
#include <string_view>
#include "base/cpu.h"
#include "base/files/file_path.h"
#include "base/path_service.h"
#include "base/scoped_native_library.h"
#include "base/strings/string_util.h"
#include "base/system/sys_info.h"
#include "base/win/registry.h"
#include "base/win/windows_version.h"
#include "build/build_config.h"
namespace base::win {
namespace {
// ntstatus.h conflicts with windows.h so define this locally.
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
#define SystemSecureBootInformation 0x91
struct SYSTEM_SECUREBOOT_INFORMATION {
BOOLEAN SecureBootEnabled;
BOOLEAN SecureBootCapable;
};
bool IsWin11SupportedProcessor(const CPU& cpu_info,
std::string_view vendor_name) {
#if defined(ARCH_CPU_X86_FAMILY)
if (vendor_name == "GenuineIntel") {
// Windows 11 is supported on Intel 8th Gen and higher models
// CPU model ID's can be referenced from the following file in
// the kernel source: arch/x86/include/asm/intel-family.h
if (cpu_info.family() != 0x06 || cpu_info.model() <= 0x5F ||
(cpu_info.model() == 0x8E &&
(cpu_info.stepping() < 9 || cpu_info.stepping() > 12)) ||
(cpu_info.model() == 0x9E &&
(cpu_info.stepping() < 10 || cpu_info.stepping() > 13))) {
return false;
}
return true;
}
if (vendor_name == "AuthenticAMD") {
// Windows 11 is supported on AMD Zen+ and higher models
if (cpu_info.family() < 0x17 ||
(cpu_info.family() == 0x17 &&
(cpu_info.model() == 0x1 || cpu_info.model() == 0x11))) {
return false;
}
return true;
}
#elif defined(ARCH_CPU_ARM_FAMILY)
if (vendor_name == "Qualcomm Technologies Inc") {
// Windows 11 is supported on all Qualcomm models with the exception
// of 1st Gen Compute Platforms due to lack of TPM 2.0
return true;
}
#else
#error Unsupported CPU architecture
#endif
return false;
}
bool IsUEFISecureBootCapable() {
SYSTEM_SECUREBOOT_INFORMATION secure_boot_info{};
if (::NtQuerySystemInformation(
static_cast<SYSTEM_INFORMATION_CLASS>(SystemSecureBootInformation),
&secure_boot_info, sizeof(SYSTEM_SECUREBOOT_INFORMATION),
nullptr) != STATUS_SUCCESS) {
return false;
}
return !!secure_boot_info.SecureBootCapable;
}
bool IsTPM20Supported() {
// Using dynamic loading instead of using linker support for delay
// loading to prevent failed loads being treated as a fatal failure which
// can happen in rare cases due to missing or corrupted DLL file.
ScopedNativeLibrary tbs_library(LoadSystemLibrary(L"tbs.dll"));
if (!tbs_library.is_valid()) {
return false;
}
decltype(Tbsi_GetDeviceInfo)* tbsi_get_device_info_proc =
reinterpret_cast<decltype(Tbsi_GetDeviceInfo)*>(
tbs_library.GetFunctionPointer("Tbsi_GetDeviceInfo"));
if (!tbsi_get_device_info_proc) {
return false;
}
TPM_DEVICE_INFO tpm_info{};
TBS_RESULT result = tbsi_get_device_info_proc(sizeof(tpm_info), &tpm_info);
return result == TBS_SUCCESS && tpm_info.tpmVersion >= TPM_VERSION_20;
}
} // namespace
bool HardwareEvaluationResult::IsEligible() const {
return this->cpu && this->memory && this->disk && this->firmware && this->tpm;
}
HardwareEvaluationResult EvaluateWin11HardwareRequirements() {
static constexpr int64_t kMinTotalDiskSpace = 64 * 1024 * 1024;
static constexpr uint64_t kMinTotalPhysicalMemory = 4 * 1024 * 1024;
static const HardwareEvaluationResult evaluate_win11_upgrade_eligibility =
[] {
HardwareEvaluationResult result;
result.cpu = IsWin11SupportedProcessor(
CPU(), OSInfo::GetInstance()->processor_vendor_name());
result.memory =
SysInfo::AmountOfPhysicalMemory() >= kMinTotalPhysicalMemory;
FilePath system_path;
result.disk =
PathService::Get(DIR_SYSTEM, &system_path) &&
SysInfo::AmountOfTotalDiskSpace(
FilePath(system_path.GetComponents()[0])) >= kMinTotalDiskSpace;
result.firmware = IsUEFISecureBootCapable();
result.tpm = IsTPM20Supported();
return result;
}();
return evaluate_win11_upgrade_eligibility;
}
} // namespace base::win