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