blob: 1fd7e7590b826ced7afd6e4fcc2c0bb7afd0cff3 [file] [log] [blame]
Angel Pons986d50e2020-04-02 23:48:53 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Tim Wawrzynczakd6fc5572019-10-25 14:58:15 -06002
3#include <assert.h>
4#include <cbfs.h>
5#include <console/console.h>
6#include <delay.h>
7#include <ec/google/chromeec/ec.h>
Tim Wawrzynczak14dd0732019-12-06 09:28:29 -07008#include <halt.h>
Tim Wawrzynczakd6fc5572019-10-25 14:58:15 -06009#include <security/vboot/misc.h>
10#include <security/vboot/vbnv.h>
11#include <security/vboot/vboot_common.h>
12#include <timer.h>
Tim Wawrzynczakf9e74992019-10-25 14:59:43 -060013#include <timestamp.h>
Tim Wawrzynczakd6fc5572019-10-25 14:58:15 -060014#include <vb2_api.h>
15
16#define _EC_FILENAME(select, suffix) \
17 (select == VB_SELECT_FIRMWARE_READONLY ? "ecro" suffix : "ecrw" suffix)
18#define EC_IMAGE_FILENAME(select) _EC_FILENAME(select, "")
19#define EC_HASH_FILENAME(select) _EC_FILENAME(select, ".hash")
20
21/* Wait 10 ms between attempts to check if EC's hash is ready */
22#define CROS_EC_HASH_CHECK_DELAY_MS 10
23/* Give the EC 2 seconds to finish calculating its hash */
24#define CROS_EC_HASH_TIMEOUT_MS 2000
25
26/* Wait 3 seconds after software sync for EC to clear the limit power flag. */
27#define LIMIT_POWER_WAIT_TIMEOUT_MS 3000
28/* Check the limit power flag every 10 ms while waiting. */
29#define LIMIT_POWER_POLL_SLEEP_MS 10
30
31/* Wait 3 seconds for EC to sysjump to RW */
32#define CROS_EC_SYSJUMP_TIMEOUT_MS 3000
33
34/*
35 * The external API for EC software sync. This function calls into
36 * vboot, which kicks off the process. Vboot runs the verified boot
37 * logic, and requires the client program to provide callbacks which
38 * perform the work.
39 */
40void vboot_sync_ec(void)
41{
42 vb2_error_t retval = VB2_SUCCESS;
43 struct vb2_context *ctx;
44
Tim Wawrzynczakf9e74992019-10-25 14:59:43 -060045 timestamp_add_now(TS_START_EC_SYNC);
46
Tim Wawrzynczakd6fc5572019-10-25 14:58:15 -060047 ctx = vboot_get_context();
48 ctx->flags |= VB2_CONTEXT_EC_SYNC_SUPPORTED;
49
50 retval = vb2api_ec_sync(ctx);
dnojiridff56a02020-04-03 10:56:43 -070051 vboot_save_data(ctx);
Tim Wawrzynczakd6fc5572019-10-25 14:58:15 -060052
Tim Wawrzynczak14dd0732019-12-06 09:28:29 -070053 switch (retval) {
54 case VB2_SUCCESS:
55 break;
56
Yu-Ping Wu30322782020-04-17 18:39:01 +080057 case VB2_REQUEST_REBOOT_EC_TO_RO:
Tim Wawrzynczak14dd0732019-12-06 09:28:29 -070058 printk(BIOS_INFO, "EC Reboot requested. Doing cold reboot\n");
59 if (google_chromeec_reboot(0, EC_REBOOT_COLD, 0))
60 printk(BIOS_EMERG, "Failed to get EC to cold reboot\n");
61
62 halt();
63 break;
64
65 /* Only for EC-EFS */
Yu-Ping Wu30322782020-04-17 18:39:01 +080066 case VB2_REQUEST_REBOOT_EC_SWITCH_RW:
Tim Wawrzynczak14dd0732019-12-06 09:28:29 -070067 printk(BIOS_INFO, "Switch EC slot requested. Doing cold reboot\n");
68 if (google_chromeec_reboot(0, EC_REBOOT_COLD,
69 EC_REBOOT_FLAG_SWITCH_RW_SLOT))
70 printk(BIOS_EMERG, "Failed to get EC to cold reboot\n");
71
72 halt();
73 break;
74
Yu-Ping Wu30322782020-04-17 18:39:01 +080075 case VB2_REQUEST_REBOOT:
Tim Wawrzynczak14dd0732019-12-06 09:28:29 -070076 printk(BIOS_INFO, "Reboot requested. Doing warm reboot\n");
Tim Wawrzynczakd6fc5572019-10-25 14:58:15 -060077 vboot_reboot();
Tim Wawrzynczak14dd0732019-12-06 09:28:29 -070078 break;
79
80 default:
81 printk(BIOS_ERR, "EC software sync failed (%#x),"
82 " rebooting\n", retval);
83 vboot_reboot();
84 break;
Tim Wawrzynczakd6fc5572019-10-25 14:58:15 -060085 }
Tim Wawrzynczakf9e74992019-10-25 14:59:43 -060086
87 timestamp_add_now(TS_END_EC_SYNC);
Tim Wawrzynczakd6fc5572019-10-25 14:58:15 -060088}
89
90/* Convert firmware image type into a flash offset */
91static uint32_t get_vboot_hash_offset(enum vb2_firmware_selection select)
92{
93 switch (select) {
94 case VB_SELECT_FIRMWARE_READONLY:
95 return EC_VBOOT_HASH_OFFSET_RO;
96 case VB_SELECT_FIRMWARE_EC_UPDATE:
97 return EC_VBOOT_HASH_OFFSET_UPDATE;
98 default:
99 return EC_VBOOT_HASH_OFFSET_ACTIVE;
100 }
101}
102
103/*
104 * Asks the EC to calculate a hash of the specified firmware image, and
105 * returns the information in **hash and *hash_size.
106 */
107static vb2_error_t ec_hash_image(enum vb2_firmware_selection select,
108 const uint8_t **hash, int *hash_size)
109{
110 static struct ec_response_vboot_hash resp;
111 uint32_t hash_offset;
112 int recalc_requested = 0;
113 struct stopwatch sw;
114
115 hash_offset = get_vboot_hash_offset(select);
116
117 stopwatch_init_msecs_expire(&sw, CROS_EC_HASH_TIMEOUT_MS);
118 do {
119 if (google_chromeec_get_vboot_hash(hash_offset, &resp))
120 return VB2_ERROR_UNKNOWN;
121
122 switch (resp.status) {
123 case EC_VBOOT_HASH_STATUS_NONE:
124 /*
125 * There is no hash available right now.
126 * Request a recalc if it hasn't been done yet.
127 */
128 if (recalc_requested)
129 break;
130
131 printk(BIOS_WARNING,
132 "%s: No valid hash (status=%d size=%d). "
133 "Computing...\n", __func__, resp.status,
134 resp.size);
135
136 if (google_chromeec_start_vboot_hash(
137 EC_VBOOT_HASH_TYPE_SHA256, hash_offset, &resp))
138 return VB2_ERROR_UNKNOWN;
139
140 recalc_requested = 1;
141
142 /*
143 * Expect status to be busy since we just sent
144 * a recalc request.
145 */
146 resp.status = EC_VBOOT_HASH_STATUS_BUSY;
147
148 /* Hash just started calculating, let it go for a bit */
149 mdelay(CROS_EC_HASH_CHECK_DELAY_MS);
150 break;
151
152 case EC_VBOOT_HASH_STATUS_BUSY:
153 /* Hash is still calculating. */
154 mdelay(CROS_EC_HASH_CHECK_DELAY_MS);
155 break;
156
157 case EC_VBOOT_HASH_STATUS_DONE: /* intentional fallthrough */
158 default:
159 /* Hash is ready! */
160 break;
161 }
162 } while (resp.status == EC_VBOOT_HASH_STATUS_BUSY &&
163 !stopwatch_expired(&sw));
164
Tim Wawrzynczakf9e74992019-10-25 14:59:43 -0600165 timestamp_add_now(TS_EC_HASH_READY);
166
Tim Wawrzynczakd6fc5572019-10-25 14:58:15 -0600167 if (resp.status != EC_VBOOT_HASH_STATUS_DONE) {
168 printk(BIOS_ERR, "%s: Hash status not done: %d\n", __func__,
169 resp.status);
170 return VB2_ERROR_UNKNOWN;
171 }
172 if (resp.hash_type != EC_VBOOT_HASH_TYPE_SHA256) {
173 printk(BIOS_ERR, "EC hash was the wrong type.\n");
174 return VB2_ERROR_UNKNOWN;
175 }
176
177 printk(BIOS_INFO, "EC took %luus to calculate image hash\n",
178 stopwatch_duration_usecs(&sw));
179
180 *hash = resp.hash_digest;
181 *hash_size = resp.digest_size;
182
183 return VB2_SUCCESS;
184}
185
186/*
187 * Asks the EC to protect or unprotect the specified flash region.
188 */
189static vb2_error_t ec_protect_flash(enum vb2_firmware_selection select, int enable)
190{
191 struct ec_response_flash_protect resp;
192 uint32_t protected_region = EC_FLASH_PROTECT_ALL_NOW;
193 const uint32_t mask = EC_FLASH_PROTECT_ALL_NOW | EC_FLASH_PROTECT_ALL_AT_BOOT;
194
195 if (select == VB_SELECT_FIRMWARE_READONLY)
196 protected_region = EC_FLASH_PROTECT_RO_NOW;
197
198 if (google_chromeec_flash_protect(mask, enable ? mask : 0, &resp) != 0)
199 return VB2_ERROR_UNKNOWN;
200
201 if (!enable) {
202 /* If protection is still enabled, need reboot */
203 if (resp.flags & protected_region)
Yu-Ping Wu30322782020-04-17 18:39:01 +0800204 return VB2_REQUEST_REBOOT_EC_TO_RO;
Tim Wawrzynczakd6fc5572019-10-25 14:58:15 -0600205
206 return VB2_SUCCESS;
207 }
208
209 /*
210 * If write protect and ro-at-boot aren't both asserted, don't expect
211 * protection enabled.
212 */
213 if ((~resp.flags) & (EC_FLASH_PROTECT_GPIO_ASSERTED |
214 EC_FLASH_PROTECT_RO_AT_BOOT))
215 return VB2_SUCCESS;
216
217 /* If flash is protected now, success */
218 if (resp.flags & EC_FLASH_PROTECT_ALL_NOW)
219 return VB2_SUCCESS;
220
221 /* If RW will be protected at boot but not now, need a reboot */
222 if (resp.flags & EC_FLASH_PROTECT_ALL_AT_BOOT)
Yu-Ping Wu30322782020-04-17 18:39:01 +0800223 return VB2_REQUEST_REBOOT_EC_TO_RO;
Tim Wawrzynczakd6fc5572019-10-25 14:58:15 -0600224
225 /* Otherwise, it's an error */
226 return VB2_ERROR_UNKNOWN;
227}
228
229/* Convert a firmware image type to an EC flash region */
230static enum ec_flash_region vboot_to_ec_region(enum vb2_firmware_selection select)
231{
232 switch (select) {
233 case VB_SELECT_FIRMWARE_READONLY:
234 return EC_FLASH_REGION_WP_RO;
235 case VB_SELECT_FIRMWARE_EC_UPDATE:
236 return EC_FLASH_REGION_UPDATE;
237 default:
238 return EC_FLASH_REGION_ACTIVE;
239 }
240}
241
242/*
243 * Read the EC's burst size bytes at a time from CBFS, and then send
244 * the chunk to the EC for it to write into its flash.
245 */
246static vb2_error_t ec_flash_write(struct region_device *image_region,
247 uint32_t region_offset, int image_size)
248{
249 struct ec_response_get_protocol_info resp_proto;
250 struct ec_response_flash_info resp_flash;
251 ssize_t pdata_max_size;
252 ssize_t burst;
253 uint8_t *file_buf;
254 struct ec_params_flash_write *params;
255 uint32_t end, off;
256
257 /*
258 * Get EC's protocol information, so that we can figure out how much
259 * data can be sent in one message.
260 */
261 if (google_chromeec_get_protocol_info(&resp_proto)) {
262 printk(BIOS_ERR, "Failed to get EC protocol information; "
263 "skipping flash write\n");
264 return VB2_ERROR_UNKNOWN;
265 }
266
267 /*
268 * Determine burst size. This must be a multiple of the write block
269 * size, and must also fit into the host parameter buffer.
270 */
271 if (google_chromeec_flash_info(&resp_flash)) {
272 printk(BIOS_ERR, "Failed to get EC flash information; "
273 "skipping flash write\n");
274 return VB2_ERROR_UNKNOWN;
275 }
276
277 /* Limit the potential buffer stack allocation to 1K */
278 pdata_max_size = MIN(1024, resp_proto.max_request_packet_size -
279 sizeof(struct ec_host_request));
280
281 /* Round burst to a multiple of the flash write block size */
282 burst = pdata_max_size - sizeof(*params);
283 burst = (burst / resp_flash.write_block_size) *
284 resp_flash.write_block_size;
285
286 /* Buffer too small */
287 if (burst <= 0) {
288 printk(BIOS_ERR, "Flash write buffer too small! skipping "
289 "flash write\n");
290 return VB2_ERROR_UNKNOWN;
291 }
292
293 /* Allocate buffer on the stack */
294 params = alloca(burst + sizeof(*params));
295
296 /* Fill up the buffer */
297 end = region_offset + image_size;
298 for (off = region_offset; off < end; off += burst) {
299 uint32_t todo = MIN(end - off, burst);
300 uint32_t xfer_size = todo + sizeof(*params);
301
302 /* Map 'todo' bytes into memory */
303 file_buf = rdev_mmap(image_region, off - region_offset, todo);
304 if (file_buf == NULL)
305 return VB2_ERROR_UNKNOWN;
306
307 params->offset = off;
308 params->size = todo;
309
310 /* Read todo bytes into the buffer */
311 memcpy(params + 1, file_buf, todo);
312
313 if (rdev_munmap(image_region, file_buf))
314 return VB2_ERROR_UNKNOWN;
315
316 /* Make sure to add back in the size of the parameters */
317 if (google_chromeec_flash_write_block(
318 (const uint8_t *)params, xfer_size)) {
319 printk(BIOS_ERR, "EC failed flash write command, "
320 "relative offset %u!\n", off - region_offset);
321 return VB2_ERROR_UNKNOWN;
322 }
323 }
324
325 return VB2_SUCCESS;
326}
327
328/*
329 * The logic for updating an EC firmware image.
330 */
331static vb2_error_t ec_update_image(enum vb2_firmware_selection select)
332{
333 uint32_t region_offset, region_size;
334 enum ec_flash_region region;
335 vb2_error_t rv;
336 size_t image_size;
337 struct cbfsf fh;
338 const char *filename;
339 struct region_device image_region;
340
341 /* Un-protect the flash region */
342 rv = ec_protect_flash(select, 0);
343 if (rv != VB2_SUCCESS)
344 return rv;
345
346 /* Convert vboot region into an EC region */
347 region = vboot_to_ec_region(select);
348
349 /* Get information about the flash region */
350 if (google_chromeec_flash_region_info(region, &region_offset,
351 &region_size))
352 return VB2_ERROR_UNKNOWN;
353
354 /* Locate the CBFS file */
355 filename = EC_IMAGE_FILENAME(select);
356 if (cbfs_boot_locate(&fh, filename, NULL))
357 return VB2_ERROR_UNKNOWN;
358
359 /* Get the file size and the region struct */
360 image_size = region_device_sz(&fh.data);
361 cbfs_file_data(&image_region, &fh);
362
363 /* Bail if the image is too large */
364 if (image_size > region_size)
365 return VB2_ERROR_INVALID_PARAMETER;
366
367 /* Erase the region */
368 if (google_chromeec_flash_erase(region_offset, region_size))
369 return VB2_ERROR_UNKNOWN;
370
371 /* Write the image into the region */
372 if (ec_flash_write(&image_region, region_offset, image_size))
373 return VB2_ERROR_UNKNOWN;
374
375 /* Verify the image */
376 if (google_chromeec_efs_verify(region))
377 return VB2_ERROR_UNKNOWN;
378
379 return VB2_SUCCESS;
380}
381
382static vb2_error_t ec_get_expected_hash(enum vb2_firmware_selection select,
383 const uint8_t **hash,
384 int *hash_size)
385{
386 size_t size;
387 const char *filename = EC_HASH_FILENAME(select);
388 const uint8_t *file = cbfs_boot_map_with_leak(filename, CBFS_TYPE_RAW, &size);
389
390 if (file == NULL)
391 return VB2_ERROR_UNKNOWN;
392
393 *hash = file;
394 *hash_size = (int)size;
395
396 return VB2_SUCCESS;
397}
398
399/***********************************************************************
400 * Vboot Callbacks
401 ***********************************************************************/
402
403/*
Tim Wawrzynczakd6fc5572019-10-25 14:58:15 -0600404 * Write opaque data into NV storage region.
405 */
Joel Kitching1debc0c2019-11-27 14:25:16 +0800406vb2_error_t vb2ex_commit_data(struct vb2_context *ctx)
Tim Wawrzynczakd6fc5572019-10-25 14:58:15 -0600407{
Joel Kitching1debc0c2019-11-27 14:25:16 +0800408 save_vbnv(ctx->nvdata);
Tim Wawrzynczakd6fc5572019-10-25 14:58:15 -0600409 return VB2_SUCCESS;
410}
411
412/*
413 * Report whether the EC is in RW or not.
414 */
415vb2_error_t vb2ex_ec_running_rw(int *in_rw)
416{
417 *in_rw = !google_ec_running_ro();
418 return VB2_SUCCESS;
419}
420
421/*
422 * Callback for when Vboot is finished.
423 */
424vb2_error_t vb2ex_ec_vboot_done(struct vb2_context *ctx)
425{
426 int limit_power = 0;
427 bool message_printed = false;
428 struct stopwatch sw;
Tim Wawrzynczakd6fc5572019-10-25 14:58:15 -0600429 int in_recovery = !!(ctx->flags & VB2_CONTEXT_RECOVERY_MODE);
430
431 /*
432 * Do not wait for the limit power flag to be cleared in
433 * recovery mode since we didn't just sysjump.
434 */
435 if (in_recovery)
436 return VB2_SUCCESS;
437
Tim Wawrzynczakf9e74992019-10-25 14:59:43 -0600438 timestamp_add_now(TS_EC_POWER_LIMIT_WAIT);
439
Tim Wawrzynczakd6fc5572019-10-25 14:58:15 -0600440 stopwatch_init_msecs_expire(&sw, LIMIT_POWER_WAIT_TIMEOUT_MS);
441
Tim Wawrzynczakf9e74992019-10-25 14:59:43 -0600442 /* Ensure we have enough power to continue booting. */
Tim Wawrzynczakd6fc5572019-10-25 14:58:15 -0600443 while (1) {
444 if (google_chromeec_read_limit_power_request(&limit_power)) {
445 printk(BIOS_ERR, "Failed to check EC limit power"
446 "flag.\n");
Tim Wawrzynczakf9e74992019-10-25 14:59:43 -0600447 return VB2_ERROR_UNKNOWN;
Tim Wawrzynczakd6fc5572019-10-25 14:58:15 -0600448 }
449
450 if (!limit_power || stopwatch_expired(&sw))
451 break;
452
453 if (!message_printed) {
454 printk(BIOS_SPEW,
455 "Waiting for EC to clear limit power flag.\n");
456 message_printed = true;
457 }
458
459 mdelay(LIMIT_POWER_POLL_SLEEP_MS);
460 }
461
462 if (limit_power) {
463 printk(BIOS_INFO,
464 "EC requests limited power usage. Request shutdown.\n");
Yu-Ping Wu30322782020-04-17 18:39:01 +0800465 return VB2_REQUEST_SHUTDOWN;
Tim Wawrzynczakd6fc5572019-10-25 14:58:15 -0600466 } else {
467 printk(BIOS_INFO, "Waited %luus to clear limit power flag.\n",
468 stopwatch_duration_usecs(&sw));
469 }
470
Tim Wawrzynczakf9e74992019-10-25 14:59:43 -0600471 return VB2_SUCCESS;
Tim Wawrzynczakd6fc5572019-10-25 14:58:15 -0600472}
473
474/*
475 * Support battery cutoff if required.
476 */
477vb2_error_t vb2ex_ec_battery_cutoff(void)
478{
479 if (google_chromeec_battery_cutoff(EC_BATTERY_CUTOFF_FLAG_AT_SHUTDOWN))
480 return VB2_ERROR_UNKNOWN;
481
482 return VB2_SUCCESS;
483}
484
485/*
486 * Vboot callback for calculating an EC image's hash.
487 */
488vb2_error_t vb2ex_ec_hash_image(enum vb2_firmware_selection select,
489 const uint8_t **hash, int *hash_size)
490{
491 return ec_hash_image(select, hash, hash_size);
492}
493
494/*
495 * Vboot callback for EC flash protection.
496 */
497vb2_error_t vb2ex_ec_protect(enum vb2_firmware_selection select)
498{
499 return ec_protect_flash(select, 1);
500}
501
502/*
503 * Get hash for image.
504 */
505vb2_error_t vb2ex_ec_get_expected_image_hash(enum vb2_firmware_selection select,
506 const uint8_t **hash,
507 int *hash_size)
508{
509 return ec_get_expected_hash(select, hash, hash_size);
510}
511
512/*
513 * Disable further sysjumps (i.e., stay in RW until next reboot)
514 */
515vb2_error_t vb2ex_ec_disable_jump(void)
516{
517 if (google_chromeec_reboot(0, EC_REBOOT_DISABLE_JUMP, 0))
518 return VB2_ERROR_UNKNOWN;
519
520 return VB2_SUCCESS;
521}
522
523/*
524 * Update EC image.
525 */
526vb2_error_t vb2ex_ec_update_image(enum vb2_firmware_selection select)
527{
528 return ec_update_image(select);
529}
530
531/*
532 * Vboot callback for commanding EC to sysjump to RW.
533 */
534vb2_error_t vb2ex_ec_jump_to_rw(void)
535{
536 struct stopwatch sw;
537
538 if (google_chromeec_reboot(0, EC_REBOOT_JUMP_RW, 0))
539 return VB2_ERROR_UNKNOWN;
540
541 /* Give the EC 3 seconds to sysjump */
542 stopwatch_init_msecs_expire(&sw, CROS_EC_SYSJUMP_TIMEOUT_MS);
543
544 /* Default delay to wait after EC reboot */
545 mdelay(50);
546 while (google_chromeec_hello()) {
547 if (stopwatch_expired(&sw)) {
548 printk(BIOS_ERR, "EC did not return from reboot after %luus\n",
549 stopwatch_duration_usecs(&sw));
550 return VB2_ERROR_UNKNOWN;
551 }
552
553 mdelay(5);
554 }
555
556 printk(BIOS_INFO, "\nEC returned from reboot after %luus\n",
557 stopwatch_duration_usecs(&sw));
558
559 return VB2_SUCCESS;
560}