blob: e7b64b23985d9542271f8ad67ab07a00ce465827 [file] [log] [blame]
Tim Wawrzynczakd6fc5572019-10-25 14:58:15 -06001/*
2 * This file is part of the coreboot project.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
14#include <assert.h>
15#include <cbfs.h>
16#include <console/console.h>
17#include <delay.h>
18#include <ec/google/chromeec/ec.h>
Tim Wawrzynczak14dd0732019-12-06 09:28:29 -070019#include <halt.h>
Tim Wawrzynczakd6fc5572019-10-25 14:58:15 -060020#include <security/vboot/misc.h>
21#include <security/vboot/vbnv.h>
22#include <security/vboot/vboot_common.h>
23#include <timer.h>
Tim Wawrzynczakf9e74992019-10-25 14:59:43 -060024#include <timestamp.h>
Tim Wawrzynczakd6fc5572019-10-25 14:58:15 -060025#include <vb2_api.h>
Joel Kitchinga6531a32020-02-20 17:50:25 +080026#include <vboot_api.h> /* for VbExDisplayScreen() and VbScreenData */
Tim Wawrzynczakd6fc5572019-10-25 14:58:15 -060027
28#define _EC_FILENAME(select, suffix) \
29 (select == VB_SELECT_FIRMWARE_READONLY ? "ecro" suffix : "ecrw" suffix)
30#define EC_IMAGE_FILENAME(select) _EC_FILENAME(select, "")
31#define EC_HASH_FILENAME(select) _EC_FILENAME(select, ".hash")
32
33/* Wait 10 ms between attempts to check if EC's hash is ready */
34#define CROS_EC_HASH_CHECK_DELAY_MS 10
35/* Give the EC 2 seconds to finish calculating its hash */
36#define CROS_EC_HASH_TIMEOUT_MS 2000
37
38/* Wait 3 seconds after software sync for EC to clear the limit power flag. */
39#define LIMIT_POWER_WAIT_TIMEOUT_MS 3000
40/* Check the limit power flag every 10 ms while waiting. */
41#define LIMIT_POWER_POLL_SLEEP_MS 10
42
43/* Wait 3 seconds for EC to sysjump to RW */
44#define CROS_EC_SYSJUMP_TIMEOUT_MS 3000
45
46/*
47 * The external API for EC software sync. This function calls into
48 * vboot, which kicks off the process. Vboot runs the verified boot
49 * logic, and requires the client program to provide callbacks which
50 * perform the work.
51 */
52void vboot_sync_ec(void)
53{
54 vb2_error_t retval = VB2_SUCCESS;
55 struct vb2_context *ctx;
56
Tim Wawrzynczakf9e74992019-10-25 14:59:43 -060057 timestamp_add_now(TS_START_EC_SYNC);
58
Tim Wawrzynczakd6fc5572019-10-25 14:58:15 -060059 ctx = vboot_get_context();
60 ctx->flags |= VB2_CONTEXT_EC_SYNC_SUPPORTED;
61
62 retval = vb2api_ec_sync(ctx);
63 vboot_save_nvdata_only(ctx);
64
Tim Wawrzynczak14dd0732019-12-06 09:28:29 -070065 switch (retval) {
66 case VB2_SUCCESS:
67 break;
68
69 case VBERROR_EC_REBOOT_TO_RO_REQUIRED:
70 printk(BIOS_INFO, "EC Reboot requested. Doing cold reboot\n");
71 if (google_chromeec_reboot(0, EC_REBOOT_COLD, 0))
72 printk(BIOS_EMERG, "Failed to get EC to cold reboot\n");
73
74 halt();
75 break;
76
77 /* Only for EC-EFS */
78 case VBERROR_EC_REBOOT_TO_SWITCH_RW:
79 printk(BIOS_INFO, "Switch EC slot requested. Doing cold reboot\n");
80 if (google_chromeec_reboot(0, EC_REBOOT_COLD,
81 EC_REBOOT_FLAG_SWITCH_RW_SLOT))
82 printk(BIOS_EMERG, "Failed to get EC to cold reboot\n");
83
84 halt();
85 break;
86
87 case VBERROR_REBOOT_REQUIRED:
88 printk(BIOS_INFO, "Reboot requested. Doing warm reboot\n");
Tim Wawrzynczakd6fc5572019-10-25 14:58:15 -060089 vboot_reboot();
Tim Wawrzynczak14dd0732019-12-06 09:28:29 -070090 break;
91
92 default:
93 printk(BIOS_ERR, "EC software sync failed (%#x),"
94 " rebooting\n", retval);
95 vboot_reboot();
96 break;
Tim Wawrzynczakd6fc5572019-10-25 14:58:15 -060097 }
Tim Wawrzynczakf9e74992019-10-25 14:59:43 -060098
99 timestamp_add_now(TS_END_EC_SYNC);
Tim Wawrzynczakd6fc5572019-10-25 14:58:15 -0600100}
101
102/* Convert firmware image type into a flash offset */
103static uint32_t get_vboot_hash_offset(enum vb2_firmware_selection select)
104{
105 switch (select) {
106 case VB_SELECT_FIRMWARE_READONLY:
107 return EC_VBOOT_HASH_OFFSET_RO;
108 case VB_SELECT_FIRMWARE_EC_UPDATE:
109 return EC_VBOOT_HASH_OFFSET_UPDATE;
110 default:
111 return EC_VBOOT_HASH_OFFSET_ACTIVE;
112 }
113}
114
115/*
116 * Asks the EC to calculate a hash of the specified firmware image, and
117 * returns the information in **hash and *hash_size.
118 */
119static vb2_error_t ec_hash_image(enum vb2_firmware_selection select,
120 const uint8_t **hash, int *hash_size)
121{
122 static struct ec_response_vboot_hash resp;
123 uint32_t hash_offset;
124 int recalc_requested = 0;
125 struct stopwatch sw;
126
127 hash_offset = get_vboot_hash_offset(select);
128
129 stopwatch_init_msecs_expire(&sw, CROS_EC_HASH_TIMEOUT_MS);
130 do {
131 if (google_chromeec_get_vboot_hash(hash_offset, &resp))
132 return VB2_ERROR_UNKNOWN;
133
134 switch (resp.status) {
135 case EC_VBOOT_HASH_STATUS_NONE:
136 /*
137 * There is no hash available right now.
138 * Request a recalc if it hasn't been done yet.
139 */
140 if (recalc_requested)
141 break;
142
143 printk(BIOS_WARNING,
144 "%s: No valid hash (status=%d size=%d). "
145 "Computing...\n", __func__, resp.status,
146 resp.size);
147
148 if (google_chromeec_start_vboot_hash(
149 EC_VBOOT_HASH_TYPE_SHA256, hash_offset, &resp))
150 return VB2_ERROR_UNKNOWN;
151
152 recalc_requested = 1;
153
154 /*
155 * Expect status to be busy since we just sent
156 * a recalc request.
157 */
158 resp.status = EC_VBOOT_HASH_STATUS_BUSY;
159
160 /* Hash just started calculating, let it go for a bit */
161 mdelay(CROS_EC_HASH_CHECK_DELAY_MS);
162 break;
163
164 case EC_VBOOT_HASH_STATUS_BUSY:
165 /* Hash is still calculating. */
166 mdelay(CROS_EC_HASH_CHECK_DELAY_MS);
167 break;
168
169 case EC_VBOOT_HASH_STATUS_DONE: /* intentional fallthrough */
170 default:
171 /* Hash is ready! */
172 break;
173 }
174 } while (resp.status == EC_VBOOT_HASH_STATUS_BUSY &&
175 !stopwatch_expired(&sw));
176
Tim Wawrzynczakf9e74992019-10-25 14:59:43 -0600177 timestamp_add_now(TS_EC_HASH_READY);
178
Tim Wawrzynczakd6fc5572019-10-25 14:58:15 -0600179 if (resp.status != EC_VBOOT_HASH_STATUS_DONE) {
180 printk(BIOS_ERR, "%s: Hash status not done: %d\n", __func__,
181 resp.status);
182 return VB2_ERROR_UNKNOWN;
183 }
184 if (resp.hash_type != EC_VBOOT_HASH_TYPE_SHA256) {
185 printk(BIOS_ERR, "EC hash was the wrong type.\n");
186 return VB2_ERROR_UNKNOWN;
187 }
188
189 printk(BIOS_INFO, "EC took %luus to calculate image hash\n",
190 stopwatch_duration_usecs(&sw));
191
192 *hash = resp.hash_digest;
193 *hash_size = resp.digest_size;
194
195 return VB2_SUCCESS;
196}
197
198/*
199 * Asks the EC to protect or unprotect the specified flash region.
200 */
201static vb2_error_t ec_protect_flash(enum vb2_firmware_selection select, int enable)
202{
203 struct ec_response_flash_protect resp;
204 uint32_t protected_region = EC_FLASH_PROTECT_ALL_NOW;
205 const uint32_t mask = EC_FLASH_PROTECT_ALL_NOW | EC_FLASH_PROTECT_ALL_AT_BOOT;
206
207 if (select == VB_SELECT_FIRMWARE_READONLY)
208 protected_region = EC_FLASH_PROTECT_RO_NOW;
209
210 if (google_chromeec_flash_protect(mask, enable ? mask : 0, &resp) != 0)
211 return VB2_ERROR_UNKNOWN;
212
213 if (!enable) {
214 /* If protection is still enabled, need reboot */
215 if (resp.flags & protected_region)
216 return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
217
218 return VB2_SUCCESS;
219 }
220
221 /*
222 * If write protect and ro-at-boot aren't both asserted, don't expect
223 * protection enabled.
224 */
225 if ((~resp.flags) & (EC_FLASH_PROTECT_GPIO_ASSERTED |
226 EC_FLASH_PROTECT_RO_AT_BOOT))
227 return VB2_SUCCESS;
228
229 /* If flash is protected now, success */
230 if (resp.flags & EC_FLASH_PROTECT_ALL_NOW)
231 return VB2_SUCCESS;
232
233 /* If RW will be protected at boot but not now, need a reboot */
234 if (resp.flags & EC_FLASH_PROTECT_ALL_AT_BOOT)
235 return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
236
237 /* Otherwise, it's an error */
238 return VB2_ERROR_UNKNOWN;
239}
240
241/* Convert a firmware image type to an EC flash region */
242static enum ec_flash_region vboot_to_ec_region(enum vb2_firmware_selection select)
243{
244 switch (select) {
245 case VB_SELECT_FIRMWARE_READONLY:
246 return EC_FLASH_REGION_WP_RO;
247 case VB_SELECT_FIRMWARE_EC_UPDATE:
248 return EC_FLASH_REGION_UPDATE;
249 default:
250 return EC_FLASH_REGION_ACTIVE;
251 }
252}
253
254/*
255 * Read the EC's burst size bytes at a time from CBFS, and then send
256 * the chunk to the EC for it to write into its flash.
257 */
258static vb2_error_t ec_flash_write(struct region_device *image_region,
259 uint32_t region_offset, int image_size)
260{
261 struct ec_response_get_protocol_info resp_proto;
262 struct ec_response_flash_info resp_flash;
263 ssize_t pdata_max_size;
264 ssize_t burst;
265 uint8_t *file_buf;
266 struct ec_params_flash_write *params;
267 uint32_t end, off;
268
269 /*
270 * Get EC's protocol information, so that we can figure out how much
271 * data can be sent in one message.
272 */
273 if (google_chromeec_get_protocol_info(&resp_proto)) {
274 printk(BIOS_ERR, "Failed to get EC protocol information; "
275 "skipping flash write\n");
276 return VB2_ERROR_UNKNOWN;
277 }
278
279 /*
280 * Determine burst size. This must be a multiple of the write block
281 * size, and must also fit into the host parameter buffer.
282 */
283 if (google_chromeec_flash_info(&resp_flash)) {
284 printk(BIOS_ERR, "Failed to get EC flash information; "
285 "skipping flash write\n");
286 return VB2_ERROR_UNKNOWN;
287 }
288
289 /* Limit the potential buffer stack allocation to 1K */
290 pdata_max_size = MIN(1024, resp_proto.max_request_packet_size -
291 sizeof(struct ec_host_request));
292
293 /* Round burst to a multiple of the flash write block size */
294 burst = pdata_max_size - sizeof(*params);
295 burst = (burst / resp_flash.write_block_size) *
296 resp_flash.write_block_size;
297
298 /* Buffer too small */
299 if (burst <= 0) {
300 printk(BIOS_ERR, "Flash write buffer too small! skipping "
301 "flash write\n");
302 return VB2_ERROR_UNKNOWN;
303 }
304
305 /* Allocate buffer on the stack */
306 params = alloca(burst + sizeof(*params));
307
308 /* Fill up the buffer */
309 end = region_offset + image_size;
310 for (off = region_offset; off < end; off += burst) {
311 uint32_t todo = MIN(end - off, burst);
312 uint32_t xfer_size = todo + sizeof(*params);
313
314 /* Map 'todo' bytes into memory */
315 file_buf = rdev_mmap(image_region, off - region_offset, todo);
316 if (file_buf == NULL)
317 return VB2_ERROR_UNKNOWN;
318
319 params->offset = off;
320 params->size = todo;
321
322 /* Read todo bytes into the buffer */
323 memcpy(params + 1, file_buf, todo);
324
325 if (rdev_munmap(image_region, file_buf))
326 return VB2_ERROR_UNKNOWN;
327
328 /* Make sure to add back in the size of the parameters */
329 if (google_chromeec_flash_write_block(
330 (const uint8_t *)params, xfer_size)) {
331 printk(BIOS_ERR, "EC failed flash write command, "
332 "relative offset %u!\n", off - region_offset);
333 return VB2_ERROR_UNKNOWN;
334 }
335 }
336
337 return VB2_SUCCESS;
338}
339
340/*
341 * The logic for updating an EC firmware image.
342 */
343static vb2_error_t ec_update_image(enum vb2_firmware_selection select)
344{
345 uint32_t region_offset, region_size;
346 enum ec_flash_region region;
347 vb2_error_t rv;
348 size_t image_size;
349 struct cbfsf fh;
350 const char *filename;
351 struct region_device image_region;
352
353 /* Un-protect the flash region */
354 rv = ec_protect_flash(select, 0);
355 if (rv != VB2_SUCCESS)
356 return rv;
357
358 /* Convert vboot region into an EC region */
359 region = vboot_to_ec_region(select);
360
361 /* Get information about the flash region */
362 if (google_chromeec_flash_region_info(region, &region_offset,
363 &region_size))
364 return VB2_ERROR_UNKNOWN;
365
366 /* Locate the CBFS file */
367 filename = EC_IMAGE_FILENAME(select);
368 if (cbfs_boot_locate(&fh, filename, NULL))
369 return VB2_ERROR_UNKNOWN;
370
371 /* Get the file size and the region struct */
372 image_size = region_device_sz(&fh.data);
373 cbfs_file_data(&image_region, &fh);
374
375 /* Bail if the image is too large */
376 if (image_size > region_size)
377 return VB2_ERROR_INVALID_PARAMETER;
378
379 /* Erase the region */
380 if (google_chromeec_flash_erase(region_offset, region_size))
381 return VB2_ERROR_UNKNOWN;
382
383 /* Write the image into the region */
384 if (ec_flash_write(&image_region, region_offset, image_size))
385 return VB2_ERROR_UNKNOWN;
386
387 /* Verify the image */
388 if (google_chromeec_efs_verify(region))
389 return VB2_ERROR_UNKNOWN;
390
391 return VB2_SUCCESS;
392}
393
394static vb2_error_t ec_get_expected_hash(enum vb2_firmware_selection select,
395 const uint8_t **hash,
396 int *hash_size)
397{
398 size_t size;
399 const char *filename = EC_HASH_FILENAME(select);
400 const uint8_t *file = cbfs_boot_map_with_leak(filename, CBFS_TYPE_RAW, &size);
401
402 if (file == NULL)
403 return VB2_ERROR_UNKNOWN;
404
405 *hash = file;
406 *hash_size = (int)size;
407
408 return VB2_SUCCESS;
409}
410
411/***********************************************************************
412 * Vboot Callbacks
413 ***********************************************************************/
414
415/*
416 * Unsupported.
417 *
418 * coreboot does not support the graphics initialization needed to
419 * display the vboot "wait" screens, etc., because the use case for
420 * supporting software sync early in the boot flow is to be able to
421 * quickly update the EC and/or sysjump to RW earlier so that USB-PD
422 * power (> 15 W) can be negotiated for earlier.
423 */
424vb2_error_t VbExDisplayScreen(uint32_t screen_type, uint32_t locale,
425 const VbScreenData *data)
426{
427 return VB2_ERROR_UNKNOWN;
428}
429
430/*
431 * Write opaque data into NV storage region.
432 */
Joel Kitching1debc0c2019-11-27 14:25:16 +0800433vb2_error_t vb2ex_commit_data(struct vb2_context *ctx)
Tim Wawrzynczakd6fc5572019-10-25 14:58:15 -0600434{
Joel Kitching1debc0c2019-11-27 14:25:16 +0800435 save_vbnv(ctx->nvdata);
Tim Wawrzynczakd6fc5572019-10-25 14:58:15 -0600436 return VB2_SUCCESS;
437}
438
439/*
440 * Report whether the EC is in RW or not.
441 */
442vb2_error_t vb2ex_ec_running_rw(int *in_rw)
443{
444 *in_rw = !google_ec_running_ro();
445 return VB2_SUCCESS;
446}
447
448/*
449 * Callback for when Vboot is finished.
450 */
451vb2_error_t vb2ex_ec_vboot_done(struct vb2_context *ctx)
452{
453 int limit_power = 0;
454 bool message_printed = false;
455 struct stopwatch sw;
Tim Wawrzynczakd6fc5572019-10-25 14:58:15 -0600456 int in_recovery = !!(ctx->flags & VB2_CONTEXT_RECOVERY_MODE);
457
458 /*
459 * Do not wait for the limit power flag to be cleared in
460 * recovery mode since we didn't just sysjump.
461 */
462 if (in_recovery)
463 return VB2_SUCCESS;
464
Tim Wawrzynczakf9e74992019-10-25 14:59:43 -0600465 timestamp_add_now(TS_EC_POWER_LIMIT_WAIT);
466
Tim Wawrzynczakd6fc5572019-10-25 14:58:15 -0600467 stopwatch_init_msecs_expire(&sw, LIMIT_POWER_WAIT_TIMEOUT_MS);
468
Tim Wawrzynczakf9e74992019-10-25 14:59:43 -0600469 /* Ensure we have enough power to continue booting. */
Tim Wawrzynczakd6fc5572019-10-25 14:58:15 -0600470 while (1) {
471 if (google_chromeec_read_limit_power_request(&limit_power)) {
472 printk(BIOS_ERR, "Failed to check EC limit power"
473 "flag.\n");
Tim Wawrzynczakf9e74992019-10-25 14:59:43 -0600474 return VB2_ERROR_UNKNOWN;
Tim Wawrzynczakd6fc5572019-10-25 14:58:15 -0600475 }
476
477 if (!limit_power || stopwatch_expired(&sw))
478 break;
479
480 if (!message_printed) {
481 printk(BIOS_SPEW,
482 "Waiting for EC to clear limit power flag.\n");
483 message_printed = true;
484 }
485
486 mdelay(LIMIT_POWER_POLL_SLEEP_MS);
487 }
488
489 if (limit_power) {
490 printk(BIOS_INFO,
491 "EC requests limited power usage. Request shutdown.\n");
Tim Wawrzynczakf9e74992019-10-25 14:59:43 -0600492 return VBERROR_SHUTDOWN_REQUESTED;
Tim Wawrzynczakd6fc5572019-10-25 14:58:15 -0600493 } else {
494 printk(BIOS_INFO, "Waited %luus to clear limit power flag.\n",
495 stopwatch_duration_usecs(&sw));
496 }
497
Tim Wawrzynczakf9e74992019-10-25 14:59:43 -0600498 return VB2_SUCCESS;
Tim Wawrzynczakd6fc5572019-10-25 14:58:15 -0600499}
500
501/*
502 * Support battery cutoff if required.
503 */
504vb2_error_t vb2ex_ec_battery_cutoff(void)
505{
506 if (google_chromeec_battery_cutoff(EC_BATTERY_CUTOFF_FLAG_AT_SHUTDOWN))
507 return VB2_ERROR_UNKNOWN;
508
509 return VB2_SUCCESS;
510}
511
512/*
513 * Vboot callback for calculating an EC image's hash.
514 */
515vb2_error_t vb2ex_ec_hash_image(enum vb2_firmware_selection select,
516 const uint8_t **hash, int *hash_size)
517{
518 return ec_hash_image(select, hash, hash_size);
519}
520
521/*
522 * Vboot callback for EC flash protection.
523 */
524vb2_error_t vb2ex_ec_protect(enum vb2_firmware_selection select)
525{
526 return ec_protect_flash(select, 1);
527}
528
529/*
530 * Get hash for image.
531 */
532vb2_error_t vb2ex_ec_get_expected_image_hash(enum vb2_firmware_selection select,
533 const uint8_t **hash,
534 int *hash_size)
535{
536 return ec_get_expected_hash(select, hash, hash_size);
537}
538
539/*
540 * Disable further sysjumps (i.e., stay in RW until next reboot)
541 */
542vb2_error_t vb2ex_ec_disable_jump(void)
543{
544 if (google_chromeec_reboot(0, EC_REBOOT_DISABLE_JUMP, 0))
545 return VB2_ERROR_UNKNOWN;
546
547 return VB2_SUCCESS;
548}
549
550/*
551 * Update EC image.
552 */
553vb2_error_t vb2ex_ec_update_image(enum vb2_firmware_selection select)
554{
555 return ec_update_image(select);
556}
557
558/*
559 * Vboot callback for commanding EC to sysjump to RW.
560 */
561vb2_error_t vb2ex_ec_jump_to_rw(void)
562{
563 struct stopwatch sw;
564
565 if (google_chromeec_reboot(0, EC_REBOOT_JUMP_RW, 0))
566 return VB2_ERROR_UNKNOWN;
567
568 /* Give the EC 3 seconds to sysjump */
569 stopwatch_init_msecs_expire(&sw, CROS_EC_SYSJUMP_TIMEOUT_MS);
570
571 /* Default delay to wait after EC reboot */
572 mdelay(50);
573 while (google_chromeec_hello()) {
574 if (stopwatch_expired(&sw)) {
575 printk(BIOS_ERR, "EC did not return from reboot after %luus\n",
576 stopwatch_duration_usecs(&sw));
577 return VB2_ERROR_UNKNOWN;
578 }
579
580 mdelay(5);
581 }
582
583 printk(BIOS_INFO, "\nEC returned from reboot after %luus\n",
584 stopwatch_duration_usecs(&sw));
585
586 return VB2_SUCCESS;
587}