Aaron Durbin | 17200ad | 2015-05-01 16:48:54 -0500 | [diff] [blame] | 1 | /* |
| 2 | * This file is part of the coreboot project. |
| 3 | * |
| 4 | * Copyright 2015 Google, Inc. |
| 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify |
| 7 | * it under the terms of the GNU General Public License as published by |
| 8 | * the Free Software Foundation; version 2 of the License. |
| 9 | * |
| 10 | * This program is distributed in the hope that it will be useful, |
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 13 | * GNU General Public License for more details. |
Aaron Durbin | 17200ad | 2015-05-01 16:48:54 -0500 | [diff] [blame] | 14 | */ |
| 15 | |
Aaron Durbin | 6d720f3 | 2015-12-08 17:00:23 -0600 | [diff] [blame] | 16 | #include <arch/early_variables.h> |
Aaron Durbin | 17200ad | 2015-05-01 16:48:54 -0500 | [diff] [blame] | 17 | #include <cbfs.h> |
Aaron Durbin | 09560fa | 2015-05-12 16:43:10 -0500 | [diff] [blame] | 18 | #include <cbmem.h> |
Aaron Durbin | 17200ad | 2015-05-01 16:48:54 -0500 | [diff] [blame] | 19 | #include <console/console.h> |
Aaron Durbin | f7ce40b | 2016-08-24 14:58:12 -0500 | [diff] [blame] | 20 | #include <ec/google/chromeec/ec.h> |
Aaron Durbin | 09560fa | 2015-05-12 16:43:10 -0500 | [diff] [blame] | 21 | #include <rmodule.h> |
Aaron Durbin | 17200ad | 2015-05-01 16:48:54 -0500 | [diff] [blame] | 22 | #include <rules.h> |
| 23 | #include <string.h> |
Furquan Shaikh | 2a12e2e | 2016-07-25 11:48:03 -0700 | [diff] [blame] | 24 | #include <vboot/misc.h> |
| 25 | #include <vboot/symbols.h> |
| 26 | #include <vboot/vboot_common.h> |
Aaron Durbin | 17200ad | 2015-05-01 16:48:54 -0500 | [diff] [blame] | 27 | |
| 28 | /* The stage loading code is compiled and entered from multiple stages. The |
| 29 | * helper functions below attempt to provide more clarity on when certain |
| 30 | * code should be called. */ |
| 31 | |
| 32 | static int verification_should_run(void) |
| 33 | { |
| 34 | if (ENV_VERSTAGE && IS_ENABLED(CONFIG_SEPARATE_VERSTAGE)) |
| 35 | return 1; |
| 36 | |
| 37 | if (!IS_ENABLED(CONFIG_SEPARATE_VERSTAGE)) { |
| 38 | if (ENV_ROMSTAGE && |
| 39 | IS_ENABLED(CONFIG_VBOOT_STARTS_IN_ROMSTAGE)) |
| 40 | return 1; |
| 41 | if (ENV_BOOTBLOCK && |
| 42 | IS_ENABLED(CONFIG_VBOOT_STARTS_IN_BOOTBLOCK)) |
| 43 | return 1; |
| 44 | } |
| 45 | |
| 46 | return 0; |
| 47 | } |
| 48 | |
| 49 | static int verstage_should_load(void) |
| 50 | { |
| 51 | if (!IS_ENABLED(CONFIG_SEPARATE_VERSTAGE)) |
| 52 | return 0; |
| 53 | |
| 54 | if (ENV_ROMSTAGE && IS_ENABLED(CONFIG_VBOOT_STARTS_IN_ROMSTAGE)) |
| 55 | return 1; |
| 56 | |
| 57 | if (ENV_BOOTBLOCK && IS_ENABLED(CONFIG_VBOOT_STARTS_IN_BOOTBLOCK)) |
| 58 | return 1; |
| 59 | |
| 60 | return 0; |
| 61 | } |
| 62 | |
Aaron Durbin | 6d720f3 | 2015-12-08 17:00:23 -0600 | [diff] [blame] | 63 | static int vboot_executed CAR_GLOBAL; |
| 64 | |
Furquan Shaikh | a6c5ddd | 2016-07-22 06:59:40 -0700 | [diff] [blame] | 65 | int vb2_logic_executed(void) |
Aaron Durbin | 6d720f3 | 2015-12-08 17:00:23 -0600 | [diff] [blame] | 66 | { |
| 67 | /* If this stage is supposed to run the vboot logic ensure it has been |
| 68 | * executed. */ |
| 69 | if (verification_should_run() && car_get_var(vboot_executed)) |
| 70 | return 1; |
| 71 | |
| 72 | /* If this stage is supposed to load verstage and verstage is returning |
| 73 | * back to the calling stage check that it has been executed. */ |
| 74 | if (verstage_should_load() && IS_ENABLED(CONFIG_RETURN_FROM_VERSTAGE)) |
| 75 | if (car_get_var(vboot_executed)) |
| 76 | return 1; |
| 77 | |
| 78 | /* Handle all other stages post vboot execution. */ |
| 79 | if (!ENV_BOOTBLOCK) { |
| 80 | if (IS_ENABLED(CONFIG_VBOOT_STARTS_IN_BOOTBLOCK)) |
| 81 | return 1; |
| 82 | if (IS_ENABLED(CONFIG_VBOOT_STARTS_IN_ROMSTAGE) && |
| 83 | !ENV_ROMSTAGE) |
| 84 | return 1; |
| 85 | } |
| 86 | |
| 87 | return 0; |
| 88 | } |
| 89 | |
| 90 | static void vboot_prepare(void) |
Aaron Durbin | 17200ad | 2015-05-01 16:48:54 -0500 | [diff] [blame] | 91 | { |
Paul Kocialkowski | 1811768 | 2016-05-14 15:30:52 +0200 | [diff] [blame] | 92 | if (verification_should_run()) { |
Aaron Durbin | f7ce40b | 2016-08-24 14:58:12 -0500 | [diff] [blame] | 93 | /* |
| 94 | * Note that this path isn't taken when |
| 95 | * CONFIG_RETURN_FROM_VERSTAGE is employed. |
| 96 | */ |
Aaron Durbin | 17200ad | 2015-05-01 16:48:54 -0500 | [diff] [blame] | 97 | verstage_main(); |
Aaron Durbin | 6d720f3 | 2015-12-08 17:00:23 -0600 | [diff] [blame] | 98 | car_set_var(vboot_executed, 1); |
Furquan Shaikh | 85aa135 | 2016-07-22 08:56:43 -0700 | [diff] [blame] | 99 | vb2_save_recovery_reason_vbnv(); |
Aaron Durbin | f7ce40b | 2016-08-24 14:58:12 -0500 | [diff] [blame] | 100 | |
| 101 | /* |
| 102 | * Avoid double memory retrain when the EC is running RW code |
| 103 | * and a recovery request came in through an EC host event. The |
| 104 | * double retrain happens because the EC won't be rebooted |
| 105 | * until kernel verification notices the EC isn't running RO |
| 106 | * code which is after memory training. Therefore, reboot the |
| 107 | * EC after we've saved the potential recovery request so it's |
| 108 | * not lost. Lastly, only perform this sequence on x86 |
| 109 | * platforms since those are the ones that currently do a |
| 110 | * costly memory training in recovery mode. |
| 111 | */ |
| 112 | if (IS_ENABLED(CONFIG_EC_GOOGLE_CHROMEEC) && |
| 113 | IS_ENABLED(CONFIG_ARCH_X86)) |
| 114 | google_chromeec_early_init(); |
| 115 | |
Aaron Durbin | 17200ad | 2015-05-01 16:48:54 -0500 | [diff] [blame] | 116 | } else if (verstage_should_load()) { |
Aaron Durbin | 37a5d15 | 2015-09-17 16:09:30 -0500 | [diff] [blame] | 117 | struct cbfsf file; |
Aaron Durbin | ac12c66c | 2015-05-20 12:08:55 -0500 | [diff] [blame] | 118 | struct prog verstage = |
Aaron Durbin | 7e7a4df | 2015-12-08 14:34:35 -0600 | [diff] [blame] | 119 | PROG_INIT(PROG_VERSTAGE, |
Aaron Durbin | ac12c66c | 2015-05-20 12:08:55 -0500 | [diff] [blame] | 120 | CONFIG_CBFS_PREFIX "/verstage"); |
Aaron Durbin | 17200ad | 2015-05-01 16:48:54 -0500 | [diff] [blame] | 121 | |
Aaron Durbin | ce2c50d | 2015-05-13 13:33:27 -0500 | [diff] [blame] | 122 | printk(BIOS_DEBUG, "VBOOT: Loading verstage.\n"); |
| 123 | |
Aaron Durbin | 17200ad | 2015-05-01 16:48:54 -0500 | [diff] [blame] | 124 | /* load verstage from RO */ |
Aaron Durbin | 37a5d15 | 2015-09-17 16:09:30 -0500 | [diff] [blame] | 125 | if (cbfs_boot_locate(&file, prog_name(&verstage), NULL)) |
| 126 | die("failed to load verstage"); |
| 127 | |
| 128 | cbfs_file_data(prog_rdev(&verstage), &file); |
| 129 | |
| 130 | if (cbfs_prog_stage_load(&verstage)) |
Aaron Durbin | 17200ad | 2015-05-01 16:48:54 -0500 | [diff] [blame] | 131 | die("failed to load verstage"); |
| 132 | |
| 133 | /* verify and select a slot */ |
| 134 | prog_run(&verstage); |
| 135 | |
| 136 | /* This is not actually possible to hit this condition at |
| 137 | * runtime, but this provides a hint to the compiler for dead |
| 138 | * code elimination below. */ |
| 139 | if (!IS_ENABLED(CONFIG_RETURN_FROM_VERSTAGE)) |
Aaron Durbin | 6d720f3 | 2015-12-08 17:00:23 -0600 | [diff] [blame] | 140 | return; |
| 141 | |
| 142 | car_set_var(vboot_executed, 1); |
Aaron Durbin | 17200ad | 2015-05-01 16:48:54 -0500 | [diff] [blame] | 143 | } |
| 144 | |
Aaron Durbin | b593366 | 2015-10-07 16:03:41 -0500 | [diff] [blame] | 145 | /* |
| 146 | * Fill in vboot cbmem objects before moving to ramstage so all |
| 147 | * downstream users have access to vboot results. This path only |
| 148 | * applies to platforms employing VBOOT_DYNAMIC_WORK_BUFFER because |
| 149 | * cbmem comes online prior to vboot verification taking place. For |
| 150 | * other platforms the vboot cbmem objects are initialized when |
| 151 | * cbmem comes online. |
| 152 | */ |
| 153 | if (ENV_ROMSTAGE && IS_ENABLED(CONFIG_VBOOT_DYNAMIC_WORK_BUFFER)) { |
| 154 | vb2_store_selected_region(); |
Aaron Durbin | 17200ad | 2015-05-01 16:48:54 -0500 | [diff] [blame] | 155 | vboot_fill_handoff(); |
Aaron Durbin | b593366 | 2015-10-07 16:03:41 -0500 | [diff] [blame] | 156 | } |
Aaron Durbin | 17200ad | 2015-05-01 16:48:54 -0500 | [diff] [blame] | 157 | } |
| 158 | |
Aaron Durbin | 6d720f3 | 2015-12-08 17:00:23 -0600 | [diff] [blame] | 159 | static int vboot_locate(struct cbfs_props *props) |
Aaron Durbin | 17200ad | 2015-05-01 16:48:54 -0500 | [diff] [blame] | 160 | { |
Aaron Durbin | 6d720f3 | 2015-12-08 17:00:23 -0600 | [diff] [blame] | 161 | struct region selected_region; |
Aaron Durbin | 899d13d | 2015-05-15 23:39:23 -0500 | [diff] [blame] | 162 | |
Aaron Durbin | 6d720f3 | 2015-12-08 17:00:23 -0600 | [diff] [blame] | 163 | /* Don't honor vboot results until the vboot logic has run. */ |
Furquan Shaikh | a6c5ddd | 2016-07-22 06:59:40 -0700 | [diff] [blame] | 164 | if (!vb2_logic_executed()) |
Aaron Durbin | b6981c0 | 2015-05-15 15:57:51 -0500 | [diff] [blame] | 165 | return -1; |
Aaron Durbin | 17200ad | 2015-05-01 16:48:54 -0500 | [diff] [blame] | 166 | |
Aaron Durbin | 6d720f3 | 2015-12-08 17:00:23 -0600 | [diff] [blame] | 167 | if (vb2_get_selected_region(&selected_region)) |
Aaron Durbin | 4e50cdd | 2015-05-15 23:25:46 -0500 | [diff] [blame] | 168 | return -1; |
Aaron Durbin | b6981c0 | 2015-05-15 15:57:51 -0500 | [diff] [blame] | 169 | |
Aaron Durbin | 6d720f3 | 2015-12-08 17:00:23 -0600 | [diff] [blame] | 170 | props->offset = region_offset(&selected_region); |
| 171 | props->size = region_sz(&selected_region); |
Aaron Durbin | 17200ad | 2015-05-01 16:48:54 -0500 | [diff] [blame] | 172 | |
Aaron Durbin | b6981c0 | 2015-05-15 15:57:51 -0500 | [diff] [blame] | 173 | return 0; |
Aaron Durbin | 17200ad | 2015-05-01 16:48:54 -0500 | [diff] [blame] | 174 | } |
| 175 | |
Aaron Durbin | 6d720f3 | 2015-12-08 17:00:23 -0600 | [diff] [blame] | 176 | const struct cbfs_locator vboot_locator = { |
Aaron Durbin | 17200ad | 2015-05-01 16:48:54 -0500 | [diff] [blame] | 177 | .name = "VBOOT", |
Aaron Durbin | 6d720f3 | 2015-12-08 17:00:23 -0600 | [diff] [blame] | 178 | .prepare = vboot_prepare, |
Aaron Durbin | 899d13d | 2015-05-15 23:39:23 -0500 | [diff] [blame] | 179 | .locate = vboot_locate, |
Aaron Durbin | 17200ad | 2015-05-01 16:48:54 -0500 | [diff] [blame] | 180 | }; |