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 | 09560fa | 2015-05-12 16:43:10 -0500 | [diff] [blame] | 20 | #include <rmodule.h> |
Aaron Durbin | 17200ad | 2015-05-01 16:48:54 -0500 | [diff] [blame] | 21 | #include <rules.h> |
| 22 | #include <string.h> |
| 23 | #include "misc.h" |
Furquan Shaikh | a6c5ddd | 2016-07-22 06:59:40 -0700 | [diff] [blame] | 24 | #include "../vboot_common.h" |
Aaron Durbin | 17200ad | 2015-05-01 16:48:54 -0500 | [diff] [blame] | 25 | #include "../symbols.h" |
| 26 | |
| 27 | /* The stage loading code is compiled and entered from multiple stages. The |
| 28 | * helper functions below attempt to provide more clarity on when certain |
| 29 | * code should be called. */ |
| 30 | |
| 31 | static int verification_should_run(void) |
| 32 | { |
| 33 | if (ENV_VERSTAGE && IS_ENABLED(CONFIG_SEPARATE_VERSTAGE)) |
| 34 | return 1; |
| 35 | |
| 36 | if (!IS_ENABLED(CONFIG_SEPARATE_VERSTAGE)) { |
| 37 | if (ENV_ROMSTAGE && |
| 38 | IS_ENABLED(CONFIG_VBOOT_STARTS_IN_ROMSTAGE)) |
| 39 | return 1; |
| 40 | if (ENV_BOOTBLOCK && |
| 41 | IS_ENABLED(CONFIG_VBOOT_STARTS_IN_BOOTBLOCK)) |
| 42 | return 1; |
| 43 | } |
| 44 | |
| 45 | return 0; |
| 46 | } |
| 47 | |
| 48 | static int verstage_should_load(void) |
| 49 | { |
| 50 | if (!IS_ENABLED(CONFIG_SEPARATE_VERSTAGE)) |
| 51 | return 0; |
| 52 | |
| 53 | if (ENV_ROMSTAGE && IS_ENABLED(CONFIG_VBOOT_STARTS_IN_ROMSTAGE)) |
| 54 | return 1; |
| 55 | |
| 56 | if (ENV_BOOTBLOCK && IS_ENABLED(CONFIG_VBOOT_STARTS_IN_BOOTBLOCK)) |
| 57 | return 1; |
| 58 | |
| 59 | return 0; |
| 60 | } |
| 61 | |
Aaron Durbin | 6d720f3 | 2015-12-08 17:00:23 -0600 | [diff] [blame] | 62 | static int vboot_executed CAR_GLOBAL; |
| 63 | |
Furquan Shaikh | a6c5ddd | 2016-07-22 06:59:40 -0700 | [diff] [blame] | 64 | int vb2_logic_executed(void) |
Aaron Durbin | 6d720f3 | 2015-12-08 17:00:23 -0600 | [diff] [blame] | 65 | { |
| 66 | /* If this stage is supposed to run the vboot logic ensure it has been |
| 67 | * executed. */ |
| 68 | if (verification_should_run() && car_get_var(vboot_executed)) |
| 69 | return 1; |
| 70 | |
| 71 | /* If this stage is supposed to load verstage and verstage is returning |
| 72 | * back to the calling stage check that it has been executed. */ |
| 73 | if (verstage_should_load() && IS_ENABLED(CONFIG_RETURN_FROM_VERSTAGE)) |
| 74 | if (car_get_var(vboot_executed)) |
| 75 | return 1; |
| 76 | |
| 77 | /* Handle all other stages post vboot execution. */ |
| 78 | if (!ENV_BOOTBLOCK) { |
| 79 | if (IS_ENABLED(CONFIG_VBOOT_STARTS_IN_BOOTBLOCK)) |
| 80 | return 1; |
| 81 | if (IS_ENABLED(CONFIG_VBOOT_STARTS_IN_ROMSTAGE) && |
| 82 | !ENV_ROMSTAGE) |
| 83 | return 1; |
| 84 | } |
| 85 | |
| 86 | return 0; |
| 87 | } |
| 88 | |
| 89 | static void vboot_prepare(void) |
Aaron Durbin | 17200ad | 2015-05-01 16:48:54 -0500 | [diff] [blame] | 90 | { |
Paul Kocialkowski | 1811768 | 2016-05-14 15:30:52 +0200 | [diff] [blame] | 91 | if (verification_should_run()) { |
Aaron Durbin | 17200ad | 2015-05-01 16:48:54 -0500 | [diff] [blame] | 92 | verstage_main(); |
Aaron Durbin | 6d720f3 | 2015-12-08 17:00:23 -0600 | [diff] [blame] | 93 | car_set_var(vboot_executed, 1); |
Aaron Durbin | 17200ad | 2015-05-01 16:48:54 -0500 | [diff] [blame] | 94 | } else if (verstage_should_load()) { |
Aaron Durbin | 37a5d15 | 2015-09-17 16:09:30 -0500 | [diff] [blame] | 95 | struct cbfsf file; |
Aaron Durbin | ac12c66c | 2015-05-20 12:08:55 -0500 | [diff] [blame] | 96 | struct prog verstage = |
Aaron Durbin | 7e7a4df | 2015-12-08 14:34:35 -0600 | [diff] [blame] | 97 | PROG_INIT(PROG_VERSTAGE, |
Aaron Durbin | ac12c66c | 2015-05-20 12:08:55 -0500 | [diff] [blame] | 98 | CONFIG_CBFS_PREFIX "/verstage"); |
Aaron Durbin | 17200ad | 2015-05-01 16:48:54 -0500 | [diff] [blame] | 99 | |
Aaron Durbin | ce2c50d | 2015-05-13 13:33:27 -0500 | [diff] [blame] | 100 | printk(BIOS_DEBUG, "VBOOT: Loading verstage.\n"); |
| 101 | |
Aaron Durbin | 17200ad | 2015-05-01 16:48:54 -0500 | [diff] [blame] | 102 | /* load verstage from RO */ |
Aaron Durbin | 37a5d15 | 2015-09-17 16:09:30 -0500 | [diff] [blame] | 103 | if (cbfs_boot_locate(&file, prog_name(&verstage), NULL)) |
| 104 | die("failed to load verstage"); |
| 105 | |
| 106 | cbfs_file_data(prog_rdev(&verstage), &file); |
| 107 | |
| 108 | if (cbfs_prog_stage_load(&verstage)) |
Aaron Durbin | 17200ad | 2015-05-01 16:48:54 -0500 | [diff] [blame] | 109 | die("failed to load verstage"); |
| 110 | |
| 111 | /* verify and select a slot */ |
| 112 | prog_run(&verstage); |
| 113 | |
| 114 | /* This is not actually possible to hit this condition at |
| 115 | * runtime, but this provides a hint to the compiler for dead |
| 116 | * code elimination below. */ |
| 117 | if (!IS_ENABLED(CONFIG_RETURN_FROM_VERSTAGE)) |
Aaron Durbin | 6d720f3 | 2015-12-08 17:00:23 -0600 | [diff] [blame] | 118 | return; |
| 119 | |
| 120 | car_set_var(vboot_executed, 1); |
Aaron Durbin | 17200ad | 2015-05-01 16:48:54 -0500 | [diff] [blame] | 121 | } |
| 122 | |
Aaron Durbin | b593366 | 2015-10-07 16:03:41 -0500 | [diff] [blame] | 123 | /* |
| 124 | * Fill in vboot cbmem objects before moving to ramstage so all |
| 125 | * downstream users have access to vboot results. This path only |
| 126 | * applies to platforms employing VBOOT_DYNAMIC_WORK_BUFFER because |
| 127 | * cbmem comes online prior to vboot verification taking place. For |
| 128 | * other platforms the vboot cbmem objects are initialized when |
| 129 | * cbmem comes online. |
| 130 | */ |
| 131 | if (ENV_ROMSTAGE && IS_ENABLED(CONFIG_VBOOT_DYNAMIC_WORK_BUFFER)) { |
| 132 | vb2_store_selected_region(); |
Aaron Durbin | 17200ad | 2015-05-01 16:48:54 -0500 | [diff] [blame] | 133 | vboot_fill_handoff(); |
Aaron Durbin | b593366 | 2015-10-07 16:03:41 -0500 | [diff] [blame] | 134 | } |
Aaron Durbin | 17200ad | 2015-05-01 16:48:54 -0500 | [diff] [blame] | 135 | } |
| 136 | |
Aaron Durbin | 6d720f3 | 2015-12-08 17:00:23 -0600 | [diff] [blame] | 137 | static int vboot_locate(struct cbfs_props *props) |
Aaron Durbin | 17200ad | 2015-05-01 16:48:54 -0500 | [diff] [blame] | 138 | { |
Aaron Durbin | 6d720f3 | 2015-12-08 17:00:23 -0600 | [diff] [blame] | 139 | struct region selected_region; |
Aaron Durbin | 899d13d | 2015-05-15 23:39:23 -0500 | [diff] [blame] | 140 | |
Aaron Durbin | 6d720f3 | 2015-12-08 17:00:23 -0600 | [diff] [blame] | 141 | /* Don't honor vboot results until the vboot logic has run. */ |
Furquan Shaikh | a6c5ddd | 2016-07-22 06:59:40 -0700 | [diff] [blame] | 142 | if (!vb2_logic_executed()) |
Aaron Durbin | b6981c0 | 2015-05-15 15:57:51 -0500 | [diff] [blame] | 143 | return -1; |
Aaron Durbin | 17200ad | 2015-05-01 16:48:54 -0500 | [diff] [blame] | 144 | |
Aaron Durbin | 6d720f3 | 2015-12-08 17:00:23 -0600 | [diff] [blame] | 145 | if (vb2_get_selected_region(&selected_region)) |
Aaron Durbin | 4e50cdd | 2015-05-15 23:25:46 -0500 | [diff] [blame] | 146 | return -1; |
Aaron Durbin | b6981c0 | 2015-05-15 15:57:51 -0500 | [diff] [blame] | 147 | |
Aaron Durbin | 6d720f3 | 2015-12-08 17:00:23 -0600 | [diff] [blame] | 148 | props->offset = region_offset(&selected_region); |
| 149 | props->size = region_sz(&selected_region); |
Aaron Durbin | 17200ad | 2015-05-01 16:48:54 -0500 | [diff] [blame] | 150 | |
Aaron Durbin | b6981c0 | 2015-05-15 15:57:51 -0500 | [diff] [blame] | 151 | return 0; |
Aaron Durbin | 17200ad | 2015-05-01 16:48:54 -0500 | [diff] [blame] | 152 | } |
| 153 | |
Aaron Durbin | 6d720f3 | 2015-12-08 17:00:23 -0600 | [diff] [blame] | 154 | const struct cbfs_locator vboot_locator = { |
Aaron Durbin | 17200ad | 2015-05-01 16:48:54 -0500 | [diff] [blame] | 155 | .name = "VBOOT", |
Aaron Durbin | 6d720f3 | 2015-12-08 17:00:23 -0600 | [diff] [blame] | 156 | .prepare = vboot_prepare, |
Aaron Durbin | 899d13d | 2015-05-15 23:39:23 -0500 | [diff] [blame] | 157 | .locate = vboot_locate, |
Aaron Durbin | 17200ad | 2015-05-01 16:48:54 -0500 | [diff] [blame] | 158 | }; |