1 /* Copyright (c) 2014 The Chromium OS Authors. All rights reserved. 2 * Use of this source code is governed by a BSD-style license that can be 3 * found in the LICENSE file. 4 */ 5 6 /* Non-volatile storage routines */ 7 8 #include "2sysincludes.h" 9 #include "2common.h" 10 #include "2crc8.h" 11 #include "2misc.h" 12 #include "2nvstorage.h" 13 #include "2nvstorage_fields.h" 14 15 static void vb2_nv_regen_crc(struct vb2_context *ctx) 16 { 17 ctx->nvdata[VB2_NV_OFFS_CRC] = vb2_crc8(ctx->nvdata, VB2_NV_OFFS_CRC); 18 ctx->flags |= VB2_CONTEXT_NVDATA_CHANGED; 19 } 20 21 /** 22 * Check the CRC of the non-volatile storage context. 23 * 24 * Use this if reading from non-volatile storage may be flaky, and you want to 25 * retry reading it several times. 26 * 27 * This may be called before vb2_context_init(). 28 * 29 * @param ctx Context pointer 30 * @return VB2_SUCCESS, or non-zero error code if error. 31 */ 32 int vb2_nv_check_crc(const struct vb2_context *ctx) 33 { 34 const uint8_t *p = ctx->nvdata; 35 36 /* Check header */ 37 if (VB2_NV_HEADER_SIGNATURE != 38 (p[VB2_NV_OFFS_HEADER] & VB2_NV_HEADER_MASK)) 39 return VB2_ERROR_NV_HEADER; 40 41 /* Check CRC */ 42 if (vb2_crc8(p, VB2_NV_OFFS_CRC) != p[VB2_NV_OFFS_CRC]) 43 return VB2_ERROR_NV_CRC; 44 45 return VB2_SUCCESS; 46 } 47 48 void vb2_nv_init(struct vb2_context *ctx) 49 { 50 struct vb2_shared_data *sd = vb2_get_sd(ctx); 51 uint8_t *p = ctx->nvdata; 52 53 /* Check data for consistency */ 54 if (vb2_nv_check_crc(ctx) != VB2_SUCCESS) { 55 /* Data is inconsistent (bad CRC or header); reset defaults */ 56 memset(p, 0, VB2_NVDATA_SIZE); 57 p[VB2_NV_OFFS_HEADER] = (VB2_NV_HEADER_SIGNATURE | 58 VB2_NV_HEADER_FW_SETTINGS_RESET | 59 VB2_NV_HEADER_KERNEL_SETTINGS_RESET); 60 61 /* Regenerate CRC */ 62 vb2_nv_regen_crc(ctx); 63 64 /* Set status flag */ 65 sd->status |= VB2_SD_STATUS_NV_REINIT; 66 // TODO: unit test for status flag being set 67 } 68 69 sd->status |= VB2_SD_STATUS_NV_INIT; 70 } 71 72 /* Macro for vb2_nv_get() single-bit settings to reduce duplicate code. */ 73 #define GETBIT(offs, mask) (p[offs] & mask ? 1 : 0) 74 75 uint32_t vb2_nv_get(struct vb2_context *ctx, enum vb2_nv_param param) 76 { 77 const uint8_t *p = ctx->nvdata; 78 79 /* 80 * TODO: We could reduce the binary size for this code by #ifdef'ing 81 * out the params not used by firmware verification. 82 */ 83 switch (param) { 84 case VB2_NV_FIRMWARE_SETTINGS_RESET: 85 return GETBIT(VB2_NV_OFFS_HEADER, 86 VB2_NV_HEADER_FW_SETTINGS_RESET); 87 88 case VB2_NV_KERNEL_SETTINGS_RESET: 89 return GETBIT(VB2_NV_OFFS_HEADER, 90 VB2_NV_HEADER_KERNEL_SETTINGS_RESET); 91 92 case VB2_NV_DEBUG_RESET_MODE: 93 return GETBIT(VB2_NV_OFFS_BOOT, VB2_NV_BOOT_DEBUG_RESET); 94 95 case VB2_NV_TRY_NEXT: 96 return GETBIT(VB2_NV_OFFS_BOOT2, VB2_NV_BOOT2_TRY_NEXT); 97 98 case VB2_NV_TRY_COUNT: 99 return p[VB2_NV_OFFS_BOOT] & VB2_NV_BOOT_TRY_COUNT_MASK; 100 101 case VB2_NV_FW_TRIED: 102 return GETBIT(VB2_NV_OFFS_BOOT2, VB2_NV_BOOT2_TRIED); 103 104 case VB2_NV_FW_RESULT: 105 return p[VB2_NV_OFFS_BOOT2] & VB2_NV_BOOT2_RESULT_MASK; 106 107 case VB2_NV_FW_PREV_TRIED: 108 return GETBIT(VB2_NV_OFFS_BOOT2, VB2_NV_BOOT2_PREV_TRIED); 109 110 case VB2_NV_FW_PREV_RESULT: 111 return (p[VB2_NV_OFFS_BOOT2] & VB2_NV_BOOT2_PREV_RESULT_MASK) 112 >> VB2_NV_BOOT2_PREV_RESULT_SHIFT; 113 114 case VB2_NV_RECOVERY_REQUEST: 115 return p[VB2_NV_OFFS_RECOVERY]; 116 117 case VB2_NV_RECOVERY_SUBCODE: 118 return p[VB2_NV_OFFS_RECOVERY_SUBCODE]; 119 120 case VB2_NV_LOCALIZATION_INDEX: 121 return p[VB2_NV_OFFS_LOCALIZATION]; 122 123 case VB2_NV_KERNEL_FIELD: 124 return (p[VB2_NV_OFFS_KERNEL] 125 | (p[VB2_NV_OFFS_KERNEL + 1] << 8) 126 | (p[VB2_NV_OFFS_KERNEL + 2] << 16) 127 | (p[VB2_NV_OFFS_KERNEL + 3] << 24)); 128 129 case VB2_NV_DEV_BOOT_USB: 130 return GETBIT(VB2_NV_OFFS_DEV, VB2_NV_DEV_FLAG_USB); 131 132 case VB2_NV_DEV_BOOT_LEGACY: 133 return GETBIT(VB2_NV_OFFS_DEV, VB2_NV_DEV_FLAG_LEGACY); 134 135 case VB2_NV_DEV_BOOT_SIGNED_ONLY: 136 return GETBIT(VB2_NV_OFFS_DEV, VB2_NV_DEV_FLAG_SIGNED_ONLY); 137 138 case VB2_NV_DISABLE_DEV_REQUEST: 139 return GETBIT(VB2_NV_OFFS_BOOT, VB2_NV_BOOT_DISABLE_DEV); 140 141 case VB2_NV_OPROM_NEEDED: 142 return GETBIT(VB2_NV_OFFS_BOOT, VB2_NV_BOOT_OPROM_NEEDED); 143 144 case VB2_NV_BACKUP_NVRAM_REQUEST: 145 return GETBIT(VB2_NV_OFFS_BOOT, VB2_NV_BOOT_BACKUP_NVRAM); 146 147 case VB2_NV_CLEAR_TPM_OWNER_REQUEST: 148 return GETBIT(VB2_NV_OFFS_TPM, VB2_NV_TPM_CLEAR_OWNER_REQUEST); 149 150 case VB2_NV_CLEAR_TPM_OWNER_DONE: 151 return GETBIT(VB2_NV_OFFS_TPM, VB2_NV_TPM_CLEAR_OWNER_DONE); 152 } 153 154 /* 155 * Put default return outside the switch() instead of in default:, so 156 * that adding a new param will cause a compiler warning. 157 */ 158 return 0; 159 } 160 161 #undef GETBIT 162 163 /* Macro for vb2_nv_set() single-bit settings to reduce duplicate code. */ 164 #define SETBIT(offs, mask) \ 165 { if (value) p[offs] |= mask; else p[offs] &= ~mask; } 166 167 void vb2_nv_set(struct vb2_context *ctx, 168 enum vb2_nv_param param, 169 uint32_t value) 170 { 171 uint8_t *p = ctx->nvdata; 172 173 /* If not changing the value, don't regenerate the CRC. */ 174 if (vb2_nv_get(ctx, param) == value) 175 return; 176 177 /* 178 * TODO: We could reduce the binary size for this code by #ifdef'ing 179 * out the params not used by firmware verification. 180 */ 181 switch (param) { 182 case VB2_NV_FIRMWARE_SETTINGS_RESET: 183 SETBIT(VB2_NV_OFFS_HEADER, VB2_NV_HEADER_FW_SETTINGS_RESET); 184 break; 185 186 case VB2_NV_KERNEL_SETTINGS_RESET: 187 SETBIT(VB2_NV_OFFS_HEADER, VB2_NV_HEADER_KERNEL_SETTINGS_RESET); 188 break; 189 190 case VB2_NV_DEBUG_RESET_MODE: 191 SETBIT(VB2_NV_OFFS_BOOT, VB2_NV_BOOT_DEBUG_RESET); 192 break; 193 194 case VB2_NV_TRY_NEXT: 195 SETBIT(VB2_NV_OFFS_BOOT2, VB2_NV_BOOT2_TRY_NEXT); 196 break; 197 198 case VB2_NV_TRY_COUNT: 199 /* Clip to valid range. */ 200 if (value > VB2_NV_BOOT_TRY_COUNT_MASK) 201 value = VB2_NV_BOOT_TRY_COUNT_MASK; 202 203 p[VB2_NV_OFFS_BOOT] &= ~VB2_NV_BOOT_TRY_COUNT_MASK; 204 p[VB2_NV_OFFS_BOOT] |= (uint8_t)value; 205 break; 206 207 case VB2_NV_FW_TRIED: 208 SETBIT(VB2_NV_OFFS_BOOT2, VB2_NV_BOOT2_TRIED); 209 break; 210 211 case VB2_NV_FW_RESULT: 212 /* Map out of range values to unknown */ 213 if (value > VB2_NV_BOOT2_RESULT_MASK) 214 value = VB2_FW_RESULT_UNKNOWN; 215 216 p[VB2_NV_OFFS_BOOT2] &= ~VB2_NV_BOOT2_RESULT_MASK; 217 p[VB2_NV_OFFS_BOOT2] |= (uint8_t)value; 218 break; 219 220 case VB2_NV_FW_PREV_TRIED: 221 SETBIT(VB2_NV_OFFS_BOOT2, VB2_NV_BOOT2_PREV_TRIED); 222 break; 223 224 case VB2_NV_FW_PREV_RESULT: 225 /* Map out of range values to unknown */ 226 if (value > VB2_NV_BOOT2_RESULT_MASK) 227 value = VB2_FW_RESULT_UNKNOWN; 228 229 p[VB2_NV_OFFS_BOOT2] &= ~VB2_NV_BOOT2_PREV_RESULT_MASK; 230 p[VB2_NV_OFFS_BOOT2] |= 231 (uint8_t)(value << VB2_NV_BOOT2_PREV_RESULT_SHIFT); 232 break; 233 234 case VB2_NV_RECOVERY_REQUEST: 235 /* 236 * Map values outside the valid range to the legacy reason, 237 * since we can't determine if we're called from kernel or user 238 * mode. 239 */ 240 if (value > 0xff) 241 value = VB2_RECOVERY_LEGACY; 242 p[VB2_NV_OFFS_RECOVERY] = (uint8_t)value; 243 break; 244 245 case VB2_NV_RECOVERY_SUBCODE: 246 p[VB2_NV_OFFS_RECOVERY_SUBCODE] = (uint8_t)value; 247 break; 248 249 case VB2_NV_LOCALIZATION_INDEX: 250 /* Map values outside the valid range to the default index. */ 251 if (value > 0xFF) 252 value = 0; 253 p[VB2_NV_OFFS_LOCALIZATION] = (uint8_t)value; 254 break; 255 256 case VB2_NV_KERNEL_FIELD: 257 p[VB2_NV_OFFS_KERNEL] = (uint8_t)(value); 258 p[VB2_NV_OFFS_KERNEL + 1] = (uint8_t)(value >> 8); 259 p[VB2_NV_OFFS_KERNEL + 2] = (uint8_t)(value >> 16); 260 p[VB2_NV_OFFS_KERNEL + 3] = (uint8_t)(value >> 24); 261 break; 262 263 case VB2_NV_DEV_BOOT_USB: 264 SETBIT(VB2_NV_OFFS_DEV, VB2_NV_DEV_FLAG_USB); 265 break; 266 267 case VB2_NV_DEV_BOOT_LEGACY: 268 SETBIT(VB2_NV_OFFS_DEV, VB2_NV_DEV_FLAG_LEGACY); 269 break; 270 271 case VB2_NV_DEV_BOOT_SIGNED_ONLY: 272 SETBIT(VB2_NV_OFFS_DEV, VB2_NV_DEV_FLAG_SIGNED_ONLY); 273 break; 274 275 case VB2_NV_DISABLE_DEV_REQUEST: 276 SETBIT(VB2_NV_OFFS_BOOT, VB2_NV_BOOT_DISABLE_DEV); 277 break; 278 279 case VB2_NV_OPROM_NEEDED: 280 SETBIT(VB2_NV_OFFS_BOOT, VB2_NV_BOOT_OPROM_NEEDED); 281 break; 282 283 case VB2_NV_BACKUP_NVRAM_REQUEST: 284 SETBIT(VB2_NV_OFFS_BOOT, VB2_NV_BOOT_BACKUP_NVRAM); 285 break; 286 287 case VB2_NV_CLEAR_TPM_OWNER_REQUEST: 288 SETBIT(VB2_NV_OFFS_TPM, VB2_NV_TPM_CLEAR_OWNER_REQUEST); 289 break; 290 291 case VB2_NV_CLEAR_TPM_OWNER_DONE: 292 SETBIT(VB2_NV_OFFS_TPM, VB2_NV_TPM_CLEAR_OWNER_DONE); 293 break; 294 } 295 296 /* 297 * Note there is no default case. This causes a compiler warning if 298 * a new param is added to the enum without adding support here. 299 */ 300 301 /* Need to regenerate CRC, since the value changed. */ 302 vb2_nv_regen_crc(ctx); 303 } 304 305 #undef SETBIT 306