Angel Pons | 6c49f40 | 2020-08-28 02:02:00 +0200 | [diff] [blame] | 1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
| 2 | |
Felix Held | b0e1150 | 2021-09-16 22:07:42 +0200 | [diff] [blame] | 3 | #include <arch/cpu.h> |
Angel Pons | 6c49f40 | 2020-08-28 02:02:00 +0200 | [diff] [blame] | 4 | #include <console/console.h> |
| 5 | #include <cpu/intel/common/common.h> |
Michał Żygowski | 257094a | 2021-11-21 13:13:15 +0100 | [diff] [blame] | 6 | #include <cpu/x86/cr.h> |
Elyes Haouas | 8823ba1 | 2022-12-05 08:48:50 +0100 | [diff] [blame] | 7 | #include <device/mmio.h> |
Angel Pons | 6c49f40 | 2020-08-28 02:02:00 +0200 | [diff] [blame] | 8 | #include <southbridge/intel/common/pmbase.h> |
Angel Pons | 6c49f40 | 2020-08-28 02:02:00 +0200 | [diff] [blame] | 9 | #include <types.h> |
| 10 | |
Angel Pons | 6c49f40 | 2020-08-28 02:02:00 +0200 | [diff] [blame] | 11 | #include "txt.h" |
Subrata Banik | 6a2495d | 2022-12-31 14:36:54 +0530 | [diff] [blame] | 12 | #include "txtlib.h" |
Angel Pons | 6c49f40 | 2020-08-28 02:02:00 +0200 | [diff] [blame] | 13 | #include "txt_register.h" |
| 14 | #include "txt_getsec.h" |
| 15 | |
Angel Pons | 6c49f40 | 2020-08-28 02:02:00 +0200 | [diff] [blame] | 16 | static bool is_txt_chipset(void) |
| 17 | { |
| 18 | uint32_t eax; |
| 19 | |
| 20 | const bool success = getsec_capabilities(&eax); |
| 21 | |
| 22 | return success && eax & 1; |
| 23 | } |
| 24 | |
| 25 | /* Print the bad news */ |
| 26 | static void print_memory_is_locked(void) |
| 27 | { |
| 28 | if (!CONFIG(INTEL_TXT_LOGGING)) |
| 29 | return; |
| 30 | |
| 31 | printk(BIOS_EMERG, "FATAL: Cannot run SCLEAN. Memory will remain locked.\n"); |
| 32 | printk(BIOS_EMERG, "\n"); |
| 33 | printk(BIOS_EMERG, "If you still want to boot, your options are:\n"); |
| 34 | printk(BIOS_EMERG, "\n"); |
| 35 | printk(BIOS_EMERG, " 1. Flash a coreboot image with a valid BIOS ACM.\n"); |
| 36 | printk(BIOS_EMERG, " Then, try again and hope it works this time.\n"); |
| 37 | printk(BIOS_EMERG, "\n"); |
| 38 | printk(BIOS_EMERG, " 2. If possible, remove the TPM from the system.\n"); |
| 39 | printk(BIOS_EMERG, " Reinstalling the TPM might lock memory again.\n"); |
| 40 | printk(BIOS_EMERG, "\n"); |
| 41 | printk(BIOS_EMERG, " 3. Disconnect all power sources, and RTC battery.\n"); |
| 42 | printk(BIOS_EMERG, " This may not work on all TXT-enabled platforms.\n"); |
| 43 | printk(BIOS_EMERG, "\n"); |
| 44 | } |
| 45 | |
| 46 | void intel_txt_romstage_init(void) |
| 47 | { |
| 48 | /* Bail early if the CPU doesn't support TXT */ |
Michał Żygowski | 257094a | 2021-11-21 13:13:15 +0100 | [diff] [blame] | 49 | if (!is_txt_cpu()) { |
| 50 | printk(BIOS_ERR, "TEE-TXT: CPU not TXT capable.\n"); |
Angel Pons | 6c49f40 | 2020-08-28 02:02:00 +0200 | [diff] [blame] | 51 | return; |
Michał Żygowski | 257094a | 2021-11-21 13:13:15 +0100 | [diff] [blame] | 52 | } |
Angel Pons | 6c49f40 | 2020-08-28 02:02:00 +0200 | [diff] [blame] | 53 | |
Michał Żygowski | 257094a | 2021-11-21 13:13:15 +0100 | [diff] [blame] | 54 | /* |
| 55 | * We need to use GETSEC here, so enable it. |
| 56 | * CR4_SMXE is all we need to be able to call GETSEC[CAPABILITIES] |
| 57 | * or GETSEC[ENTERACCS] for SCLEAN. |
| 58 | */ |
| 59 | write_cr4(read_cr4() | CR4_SMXE); |
Angel Pons | 6c49f40 | 2020-08-28 02:02:00 +0200 | [diff] [blame] | 60 | |
Michał Żygowski | 257094a | 2021-11-21 13:13:15 +0100 | [diff] [blame] | 61 | if (!is_txt_chipset()) { |
| 62 | printk(BIOS_ERR, "TEE-TXT: Chipset not TXT capable.\n"); |
Angel Pons | 6c49f40 | 2020-08-28 02:02:00 +0200 | [diff] [blame] | 63 | return; |
Michał Żygowski | 257094a | 2021-11-21 13:13:15 +0100 | [diff] [blame] | 64 | } |
Angel Pons | 6c49f40 | 2020-08-28 02:02:00 +0200 | [diff] [blame] | 65 | |
| 66 | const uint8_t txt_ests = read8((void *)TXT_ESTS); |
| 67 | |
| 68 | const bool establishment = is_establishment_bit_asserted(); |
| 69 | const bool is_wake_error = !!(txt_ests & TXT_ESTS_WAKE_ERROR_STS); |
| 70 | |
| 71 | if (CONFIG(INTEL_TXT_LOGGING)) { |
| 72 | |
| 73 | printk(BIOS_INFO, "TEE-TXT: TPM established: %s\n", |
| 74 | establishment ? "true" : "false"); |
| 75 | } |
| 76 | |
| 77 | if (establishment && is_wake_error) { |
| 78 | |
| 79 | printk(BIOS_ERR, "TEE-TXT: Secrets remain in memory. SCLEAN is required.\n"); |
| 80 | |
| 81 | if (txt_ests & TXT_ESTS_TXT_RESET_STS) { |
Michał Żygowski | 1e3b48c | 2021-11-24 23:32:15 +0100 | [diff] [blame] | 82 | printk(BIOS_ERR, "TEE-TXT: TXT_RESET bit set, doing global reset!\n"); |
| 83 | txt_reset_platform(); |
Angel Pons | 6c49f40 | 2020-08-28 02:02:00 +0200 | [diff] [blame] | 84 | } |
| 85 | |
| 86 | /* FIXME: Clear SLP_TYP# */ |
| 87 | write_pmbase32(4, read_pmbase32(4) & ~(0x7 << 10)); |
| 88 | |
| 89 | intel_txt_run_sclean(); |
| 90 | |
| 91 | /* If running the BIOS ACM is impossible, manual intervention is required */ |
| 92 | print_memory_is_locked(); |
| 93 | |
| 94 | /* FIXME: vboot A/B could be used to recover, but has not been tested */ |
| 95 | die("Could not execute BIOS ACM to unlock the memory.\n"); |
| 96 | } |
| 97 | } |