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