1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
|
// 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
|