xref: /aosp_15_r20/external/flashrom/cros_ec.c (revision 0d6140be3aa665ecc836e8907834fcd3e3b018fc)
1 /*
2  * This file is part of the flashrom project.
3  *
4  * Copyright (C) 2012 The Chromium OS Authors. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * Redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer.
12  *
13  * Redistributions in binary form must reproduce the above copyright
14  * notice, this list of conditions and the following disclaimer in the
15  * documentation and/or other materials provided with the distribution.
16  *
17  * Neither the name of Google or the names of contributors or
18  * licensors may be used to endorse or promote products derived from this
19  * software without specific prior written permission.
20  *
21  * This software is provided "AS IS," without a warranty of any kind.
22  * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
23  * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
24  * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
25  * GOOGLE INC AND ITS LICENSORS SHALL NOT BE LIABLE
26  * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
27  * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.  IN NO EVENT WILL
28  * GOOGLE OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
29  * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
30  * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
31  * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
32  * EVEN IF GOOGLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
33  */
34 
35 #include <assert.h>
36 #include <errno.h>
37 #include <fcntl.h>
38 #include <inttypes.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <unistd.h>
43 
44 #include <sys/ioctl.h>
45 #include <sys/stat.h>
46 #include <sys/types.h>
47 
48 #include <linux/ioctl.h>
49 #include <linux/types.h>
50 
51 #include "flashchips.h"
52 #include "flash.h"
53 #include "fmap.h"
54 #include "cros_ec_commands.h"
55 #include "programmer.h"
56 #include "spi.h"
57 
58 static bool g_cros_ec_detected = false;
59 static int g_cros_ec_fd;		/* File descriptor for kernel device */
60 
61 struct cros_ec_priv {
62 	enum ec_current_image current_image;
63 	struct ec_response_flash_region_info *region;
64 
65 	/*
66 	 * Some CrOS ECs support page write mode for their flash memory. This
67 	 * represents the ideal size of a data payload to write to flash.
68 	 */
69 	unsigned int ideal_write_size;
70 } cros_ec_dev_priv = {
71 	.current_image = EC_IMAGE_UNKNOWN,
72 	.region = NULL,
73 	.ideal_write_size = 0,
74 };
75 
76 
77 /* For region larger use async version for FLASH_ERASE */
78 #define FLASH_SMALL_REGION_THRESHOLD (16 * 1024)
79 
80 /* 1 if we want the flashrom to call erase_and_write_flash() again. */
81 static int need_2nd_pass = 0;
82 
83 /* true if cros_ec encounters spi_access denied during erasure. */
84 static bool spi_acc_issue = false;
85 
86 /* 1 if EC firmware has RWSIG enabled. */
87 static int rwsig_enabled = 0;
88 
89 /* The range of each firmware copy from the image file to update.
90  * But re-define the .flags as the valid flag to indicate the firmware is
91  * new or not (if flags = 1).
92  */
93 static struct fmap_area fwcopy[4];  // [0] is not used.
94 
95 /* The names of enum lpc_current_image to match in FMAP area names. */
96 static const char *sections[] = {
97 	"UNKNOWN SECTION",  // EC_IMAGE_UNKNOWN -- never matches
98 	"EC_RO",
99 	"EC_RW",
100 };
101 
102 static struct ec_response_flash_region_info regions[EC_FLASH_REGION_COUNT];
103 
104 /*
105  * Delay after reboot before EC can respond to host command.
106  * This value should be large enough for EC to initialize, but no larger than
107  * CONFIG_RWSIG_JUMP_TIMEOUT. This way for EC using RWSIG task, we will be
108  * able to abort RWSIG jump and stay in RO.
109  */
110 #define EC_INIT_DELAY 800000
111 
112 /*
113  * Delay after a cold reboot which allows RWSIG enabled EC to jump to EC_RW.
114  */
115 #define EC_RWSIG_JUMP_TO_RW_DELAY 3000000
116 
117 /* Given the range not able to update, mark the corresponding
118  * firmware as old.
119  */
cros_ec_invalidate_copy(unsigned int addr,unsigned int len)120 static void cros_ec_invalidate_copy(unsigned int addr, unsigned int len)
121 {
122 	for (unsigned int i = EC_IMAGE_RO; i < ARRAY_SIZE(fwcopy); i++) {
123 		struct fmap_area *fw = &fwcopy[i];
124 		if ((addr >= fw->offset && (addr < fw->offset + fw->size)) ||
125 		    (fw->offset >= addr && (fw->offset < addr + len))) {
126 			msg_pdbg(" OLD[%s]", sections[i]);
127 			fw->flags = 0;  // mark as old
128 		}
129 	}
130 }
131 
132 /* ugly singleton to work around cros layering violations in action_descriptor.c */
programming_ec(void)133 bool programming_ec(void)
134 {
135 	/* Programmer is EC so toggle ec-alias path detection on. */
136 	return g_cros_ec_detected;
137 }
138 
139 /*
140  * @version: Command version number (often 0)
141  * @command: Command to send (EC_CMD_...)
142  * @outsize: Outgoing length in bytes
143  * @insize: Max number of bytes to accept from EC
144  * @result: EC's response to the command (separate from communication failure)
145  * @data: Where to put the incoming data from EC and outgoing data to EC
146  */
147 struct cros_ec_command_v2 {
148 	uint32_t version;
149 	uint32_t command;
150 	uint32_t outsize;
151 	uint32_t insize;
152 	uint32_t result;
153 	uint8_t data[0];
154 };
155 
156 #define CROS_EC_DEV_IOC_V2	0xEC
157 #define CROS_EC_DEV_IOCXCMD_V2	_IOWR(CROS_EC_DEV_IOC_V2, 0, \
158 				      struct cros_ec_command_v2)
159 
160 #define CROS_EC_DEV_RETRY	3
161 #define CROS_EC_COMMAND_RETRIES	50
162 
163 /*
164  * ec device interface v2
165  * (used with upstream kernel as well as with Chrome OS v4.4 and later)
166  */
167 
command_wait_for_response_v2(int cros_ec_fd)168 static int command_wait_for_response_v2(int cros_ec_fd)
169 {
170 	uint8_t s_cmd_buf[sizeof(struct cros_ec_command_v2) +
171 			  sizeof(struct ec_response_get_comms_status)];
172 	struct cros_ec_command_v2 *s_cmd = (struct cros_ec_command_v2 *)s_cmd_buf;
173 	struct ec_response_get_comms_status *status = (struct ec_response_get_comms_status *)s_cmd->data;
174 	int ret;
175 
176 	s_cmd->version = 0;
177 	s_cmd->command = EC_CMD_GET_COMMS_STATUS;
178 	s_cmd->outsize = 0;
179 	s_cmd->insize = sizeof(*status);
180 
181 	/*
182 	 * FIXME: magic delay until we fix the underlying problem (probably in
183 	 * the kernel driver)
184 	 */
185 	usleep(10 * 1000);
186 	for (int i = 1; i <= CROS_EC_COMMAND_RETRIES; i++) {
187 		ret = ioctl(cros_ec_fd, CROS_EC_DEV_IOCXCMD_V2, s_cmd_buf);
188 		if (ret < 0) {
189 			msg_perr("%s(): CrOS EC command failed: %d, errno=%d\n",
190 				 __func__, ret, errno);
191 			ret = -EC_RES_ERROR;
192 			break;
193 		}
194 		if (s_cmd->result) {
195 			msg_perr("%s(): CrOS EC command failed: result=%d\n",
196 				 __func__, s_cmd->result);
197 			ret = -s_cmd->result;
198 			break;
199 		}
200 
201 		if (!(status->flags & EC_COMMS_STATUS_PROCESSING)) {
202 			ret = -EC_RES_SUCCESS;
203 			break;
204 		}
205 
206 		usleep(1000);
207 	}
208 
209 	return ret;
210 }
211 
__cros_ec_command_dev_v2(int cros_ec_fd,int command,int version,const void * outdata,int outsize,void * indata,int insize)212 static int __cros_ec_command_dev_v2(int cros_ec_fd, int command, int version,
213 			   const void *outdata, int outsize,
214 			   void *indata, int insize)
215 {
216 	const size_t size = sizeof(struct cros_ec_command_v2) + max(outsize, insize);
217 
218 	assert(outsize == 0 || outdata != NULL);
219 	assert(insize == 0 || indata != NULL);
220 
221 	struct cros_ec_command_v2 *s_cmd = malloc(size);
222 	if (s_cmd == NULL)
223 		return -EC_RES_ERROR;
224 
225 	s_cmd->command = command;
226 	s_cmd->version = version;
227 	s_cmd->result = 0xff;
228 	s_cmd->outsize = outsize;
229 	s_cmd->insize = insize;
230 	memcpy(s_cmd->data, outdata, outsize);
231 
232 	int ret = ioctl(cros_ec_fd, CROS_EC_DEV_IOCXCMD_V2, s_cmd, size);
233 	if (ret < 0 && errno == EAGAIN) {
234 		ret = command_wait_for_response_v2(cros_ec_fd);
235 		s_cmd->result = 0;
236 	}
237 	if (ret < 0) {
238 		msg_perr("%s(): Command 0x%04x failed: %d, errno=%d\n",
239 			__func__, command, ret, errno);
240 		free(s_cmd);
241 		return -EC_RES_ERROR;
242 	}
243 	if (s_cmd->result) {
244 		msg_pdbg("%s(): Command 0x%04x returned result: %d\n",
245 			 __func__, command, s_cmd->result);
246 		ret = -s_cmd->result;
247 		free(s_cmd);
248 		return ret;
249 	}
250 
251 	memcpy(indata, s_cmd->data, min(ret, insize));
252 	free(s_cmd);
253 	return min(ret, insize);
254 }
255 
256 /*
257  * cros_ec_command - Issue command to CROS_EC device with retry
258  *
259  * @command:	command code
260  * @outdata:	data to send to EC
261  * @outsize:	number of bytes in outbound payload
262  * @indata:	(unallocated) buffer to store data received from EC
263  * @insize:	number of bytes in inbound payload
264  *
265  * This uses the kernel Chrome OS EC driver to communicate with the EC.
266  *
267  * The outdata and indata buffers contain payload data (if any); command
268  * and response codes as well as checksum data are handled transparently by
269  * this function.
270  *
271  * Returns >=0 for success, or negative if other error.
272  */
cros_ec_command(int command,int version,const void * outdata,int outsize,void * indata,int insize)273 static int cros_ec_command(int command, int version,
274 			   const void *outdata, int outsize,
275 			   void *indata, int insize)
276 {
277 	int ret = EC_RES_ERROR;
278 	int attempt;
279 
280 	for (attempt = 0; attempt < CROS_EC_DEV_RETRY; attempt++) {
281 		ret = __cros_ec_command_dev_v2(g_cros_ec_fd, command, version, outdata,
282 					       outsize, indata, insize);
283 		if (ret >= 0)
284 			return ret;
285 	}
286 
287 	return ret;
288 }
289 
cros_ec_get_current_image(void)290 static int cros_ec_get_current_image(void)
291 {
292 	struct ec_response_get_version resp;
293 
294 	int rc = cros_ec_command(EC_CMD_GET_VERSION,
295 				0, NULL, 0, &resp, sizeof(resp));
296 	if (rc < 0) {
297 		msg_perr("CROS_EC cannot get the running copy: rc=%d\n", rc);
298 		return rc;
299 	}
300 	if (resp.current_image == EC_IMAGE_UNKNOWN) {
301 		msg_perr("CROS_EC gets unknown running copy\n");
302 		return -1;
303 	}
304 
305 	return resp.current_image;
306 }
307 
308 
cros_ec_get_region_info(enum ec_flash_region region,struct ec_response_flash_region_info * info)309 static int cros_ec_get_region_info(enum ec_flash_region region,
310 			       struct ec_response_flash_region_info *info)
311 {
312 	struct ec_params_flash_region_info req = { .region = region };
313 	struct ec_response_flash_region_info resp;
314 
315 	int rc = cros_ec_command(EC_CMD_FLASH_REGION_INFO,
316 			      EC_VER_FLASH_REGION_INFO, &req, sizeof(req),
317 			      &resp, sizeof(resp));
318 	if (rc < 0) {
319 		msg_perr("Cannot get the WP_RO region info: %d\n", rc);
320 		return rc;
321 	}
322 
323 	info->offset = resp.offset;
324 	info->size = resp.size;
325 	return 0;
326 }
327 
328 /**
329  * Check if a feature is supported by EC.
330  *
331  * @param feature	feature code
332  * @return < 0 if error, 0 not supported, > 0 supported
333  *
334  * NOTE: Once it successfully runs, the feature bits are cached. So, if you
335  *       want to query a feature that can be different per copy, you need to
336  *       cache features per image copy.
337  */
ec_check_features(int feature)338 static int ec_check_features(int feature)
339 {
340 	static struct ec_response_get_features r;
341 	int rc = 0;
342 
343 	if (feature < 0 || feature >= (int)sizeof(r.flags) * 8)
344 		return -1;
345 
346 	/* We don't cache return code. We retry regardless the return code. */
347 	if (r.flags[0] == 0)
348 		rc = cros_ec_command(EC_CMD_GET_FEATURES,
349 					      0, NULL, 0, &r, sizeof(r));
350 
351 	if (rc < 0)
352 		return rc;
353 
354 	return !!(r.flags[feature / 32] & (1 << (feature % 32)));
355 }
356 
357 /**
358  * Disable EC rwsig jump.
359  *
360  * @return 0 if success, <0 if error
361  */
ec_rwsig_abort()362 static int ec_rwsig_abort()
363 {
364 	struct ec_params_rwsig_action p = { .action = RWSIG_ACTION_ABORT };
365 	return cros_ec_command(EC_CMD_RWSIG_ACTION,
366 				0, &p, sizeof(p), NULL, 0);
367 }
368 
369 /**
370  * Get the versions of the command supported by the EC.
371  *
372  * @param cmd		Command
373  * @param pmask		Destination for version mask; will be set to 0 on
374  *			error.
375  * @return 0 if success, <0 if error
376  */
ec_get_cmd_versions(int cmd,uint32_t * pmask)377 static int ec_get_cmd_versions(int cmd, uint32_t *pmask)
378 {
379 	struct ec_params_get_cmd_versions pver = { .cmd = cmd };
380 	struct ec_response_get_cmd_versions rver;
381 
382 	*pmask = 0;
383 
384 	int rc = cros_ec_command(EC_CMD_GET_CMD_VERSIONS, 0,
385 			&pver, sizeof(pver), &rver, sizeof(rver));
386 	if (rc < 0)
387 		return rc;
388 
389 	*pmask = rver.version_mask;
390 	return rc;
391 }
392 
393 /* Perform a cold reboot.
394  *
395  * @param flags		flags to pass to EC_CMD_REBOOT_EC.
396  * @return 0 for success, < 0 for command failure.
397  */
cros_ec_cold_reboot(int flags)398 static int cros_ec_cold_reboot(int flags)
399 {
400 	struct ec_params_reboot_ec p = { .cmd = EC_REBOOT_COLD, .flags = flags };
401 	return cros_ec_command(EC_CMD_REBOOT_EC, 0, &p, sizeof(p),
402 					NULL, 0);
403 }
404 
405 /* Asks EC to jump to a firmware copy. If target is EC_IMAGE_UNKNOWN,
406  * then this functions picks a NEW firmware copy and jumps to it. Note that
407  * RO is preferred, then A, finally B.
408  *
409  * Returns 0 for success.
410  */
cros_ec_jump_copy(enum ec_current_image target)411 static int cros_ec_jump_copy(enum ec_current_image target)
412 {
413 	/* Since the EC may return EC_RES_SUCCESS twice if the EC doesn't
414 	 * jump to different firmware copy. The second EC_RES_SUCCESS would
415 	 * set the OBF=1 and the next command cannot be executed.
416 	 * Thus, we call EC to jump only if the target is different.
417 	 */
418 	const enum ec_current_image current_image = cros_ec_get_current_image();
419 	if (current_image < 0)
420 		return 1;
421 	if (current_image == target)
422 		return 0;
423 
424 	struct ec_params_reboot_ec p = {0};
425 
426 	/* Translate target --> EC reboot command parameter */
427 	switch (target) {
428 	case EC_IMAGE_RO:
429 		/*
430 		 * Do a cold reset instead of JUMP_RO so board enabling
431 		 * EC_FLASH_PROTECT_ALL_NOW at runtime can clear the WP flag.
432 		 * This is true for EC enabling RWSIG, where
433 		 * EC_FLASH_PROTECT_ALL_NOW is applied before jumping into RW.
434 		 */
435 		if (rwsig_enabled)
436 			p.cmd = EC_REBOOT_COLD;
437 		else
438 			p.cmd = EC_REBOOT_JUMP_RO;
439 		break;
440 	case EC_IMAGE_RW:
441 		p.cmd = EC_REBOOT_JUMP_RW;
442 		break;
443 	default:
444 		/*
445 		 * If target is unspecified, set EC reboot command to use
446 		 * a new image. Also set "target" so that it may be used
447 		 * to update the priv->current_image if jump is successful.
448 		 */
449 		if (fwcopy[EC_IMAGE_RO].flags) {
450 			p.cmd = EC_REBOOT_JUMP_RO;
451 			target = EC_IMAGE_RO;
452 		} else if (fwcopy[EC_IMAGE_RW].flags) {
453 			p.cmd = EC_REBOOT_JUMP_RW;
454 			target = EC_IMAGE_RW;
455 		} else {
456 			return 1;
457 		}
458 		break;
459 	}
460 
461 	if (p.cmd == EC_REBOOT_COLD)
462 		msg_pdbg("Doing a cold reboot instead of JUMP_RO/RW.\n");
463 	else
464 		msg_pdbg("CROS_EC is jumping to [%s]\n", sections[target]);
465 
466 	if (current_image == p.cmd) {
467 		msg_pdbg("CROS_EC is already in [%s]\n", sections[target]);
468 		cros_ec_dev_priv.current_image = target;
469 		return 0;
470 	}
471 
472 	int rc = cros_ec_command(EC_CMD_REBOOT_EC,
473 				      0, &p, sizeof(p), NULL, 0);
474 	if (rc < 0) {
475 		msg_perr("CROS_EC cannot jump/reboot to [%s]:%d\n",
476 			 sections[target], rc);
477 		return rc;
478 	}
479 
480 	/* Sleep until EC can respond to host command, but just before
481 	 * CONFIG_RWSIG_JUMP_TIMEOUT if EC is using RWSIG task. */
482 	usleep(EC_INIT_DELAY);
483 
484 	/* Abort RWSIG jump for EC that use it. Normal EC will ignore it. */
485 	if (target == EC_IMAGE_RO && rwsig_enabled) {
486 		msg_pdbg("Aborting RWSIG jump.\n");
487 		ec_rwsig_abort();
488 	}
489 
490 	msg_pdbg("CROS_EC jumped/rebooted to [%s]\n", sections[target]);
491 	cros_ec_dev_priv.current_image = target;
492 
493 	return EC_RES_SUCCESS;
494 }
495 
cros_ec_restore_wp(void * data)496 static int cros_ec_restore_wp(void *data)
497 {
498 	msg_pdbg("Restoring EC soft WP.\n");
499 
500 	struct flashctx *flash = data;
501 
502 	struct flashrom_wp_cfg *cfg = NULL;
503 	if (flashrom_wp_cfg_new(&cfg) != FLASHROM_WP_OK)
504 		return 1;
505 	flashrom_wp_set_mode(cfg, FLASHROM_WP_MODE_HARDWARE);
506 
507 	enum flashrom_wp_result ret = flashrom_wp_write_cfg(flash, cfg);
508 	flashrom_wp_cfg_release(cfg);
509 
510 	return (ret != FLASHROM_WP_OK);
511 }
512 
cros_ec_wp_is_enabled(void)513 static int cros_ec_wp_is_enabled(void)
514 {
515 	struct ec_params_flash_protect p = {0};
516 	struct ec_response_flash_protect r;
517 
518 	int rc = cros_ec_command(EC_CMD_FLASH_PROTECT,
519 			EC_VER_FLASH_PROTECT, &p, sizeof(p), &r, sizeof(r));
520 	if (rc < 0) {
521 		msg_perr("FAILED: Cannot get the write protection status: %d\n",
522 			 rc);
523 		return -1;
524 	} else if (rc < (int)sizeof(r)) {
525 		msg_perr("FAILED: Too little data returned (expected:%zd, "
526 			 "actual:%d)\n", sizeof(r), rc);
527 		return -1;
528 	}
529 
530 	if (r.flags & (EC_FLASH_PROTECT_RO_NOW | EC_FLASH_PROTECT_ALL_NOW))
531 		return 1;
532 
533 	return 0;
534 }
535 
536 /*
537  * If HW WP is disabled we may still need to disable write protection
538  * that is active on the EC. Otherwise the EC can reject erase/write
539  * commands.
540  *
541  * Failure is OK since HW WP might be enabled or the EC needs to be
542  * rebooted for the change to take effect. We can still update RW
543  * portions.
544  *
545  * If disabled here, EC WP will be restored at the end so that
546  * "--wp-enable" does not need to be run later. This greatly
547  * simplifies logic for developers and scripts.
548  */
disable_soft_wp_if_needed(struct flashctx * flash)549 static int disable_soft_wp_if_needed(struct flashctx *flash)
550 {
551 	const int wp_status = cros_ec_wp_is_enabled();
552 	if (wp_status < 0) {
553 		return 1;
554 	} else if (wp_status == 1) {
555 		msg_pdbg("Attempting to disable EC soft WP.\n");
556 
557 		struct flashrom_wp_cfg *cfg = NULL;
558 		enum flashrom_wp_result ret = flashrom_wp_cfg_new(&cfg);
559 
560 		if (ret == FLASHROM_WP_OK) {
561 			flashrom_wp_set_mode(cfg, FLASHROM_WP_MODE_DISABLED);
562 
563 			ret = flashrom_wp_write_cfg(flash, cfg);
564 			flashrom_wp_cfg_release(cfg);
565 		}
566 
567 		if (ret == FLASHROM_WP_OK) {
568 			msg_pdbg("EC soft WP disabled successfully.\n");
569 			if (register_shutdown(cros_ec_restore_wp, flash))
570 				return 1;
571 		} else {
572 			msg_pdbg("Failed. Hardware WP might in effect or EC "
573 				"needs to be rebooted first.\n");
574 		}
575 	} else {
576 		msg_pdbg("EC soft WP is already disabled.\n");
577 	}
578 	return 0;
579 }
580 
parse_fmap(const uint8_t * const image,uint32_t flash_size)581 static void parse_fmap(const uint8_t *const image, uint32_t flash_size)
582 {
583 	// Parse the fmap in the image file and cache the firmware ranges.
584 	struct fmap *fmap = NULL;
585 	if (fmap_read_from_buffer(&fmap, image, flash_size)) {
586 		return;
587 	}
588 
589 	// Lookup RO/A/B sections in FMAP.
590 	for (unsigned int i = 0; i < fmap->nareas; i++) {
591 		const struct fmap_area *fa = &fmap->areas[i];
592 
593 		for (unsigned int j = EC_IMAGE_RO; j < ARRAY_SIZE(sections); j++) {
594 			/* skip fmap sections unrelated to cros_ec sections. */
595 			if (strcmp(sections[j], (const char *) fa->name))
596 				continue;
597 
598 			msg_pdbg("Found '%s' in image.\n", fa->name);
599 			fwcopy[j] = *fa;
600 			fwcopy[j].flags = 1;  // mark as new
601 		}
602 	}
603 	free(fmap);
604 }
605 
606 /**
607  * iff layout region is one of the supported cros_ec
608  * sections then modify the region_type bit-feild.
609  * 00 - no RO or RW.
610  * 01 - RO found.
611  * 10 - RW found.
612  * 11 - RO+RW found.
613  */
parse_layout(const struct flashrom_layout * const layout)614 static enum ec_current_image parse_layout(const struct flashrom_layout *const layout)
615 {
616 	enum ec_current_image region_type = EC_IMAGE_UNKNOWN; /* no RO or RW found yet. */
617 	const struct romentry *entry = NULL;
618 
619 	while ((entry = layout_next_included(layout, entry))) {
620 		const struct flash_region *region = &entry->region;
621 		if (!strcmp("WP_RO", (const char *) region->name))
622 			region_type |= EC_IMAGE_RO;
623 		if (!strcmp(sections[EC_IMAGE_RW], (const char *) region->name))
624 			region_type |= EC_IMAGE_RW;
625 	}
626 	/* iff neither RO or RW was found in the layout then assume a full image of both. */
627 	return region_type == EC_IMAGE_UNKNOWN ? (EC_IMAGE_RO | EC_IMAGE_RW) : region_type;
628 }
629 
630 /*
631  * Prepare EC for update:
632  * - Disable soft WP if needed.
633  * - Parse flashmap.
634  * - Jump to RO firmware.
635  */
cros_ec_prepare(struct flashctx * flash,const uint8_t * const image,uint32_t flash_size)636 int cros_ec_prepare(struct flashctx *flash, const uint8_t *const image, uint32_t flash_size)
637 {
638 	if (!programming_ec())
639 		return 0;
640 
641 	if (ec_check_features(EC_FEATURE_RWSIG) > 0) {
642 		rwsig_enabled = 1;
643 		msg_pdbg("EC has RWSIG enabled.\n");
644 	}
645 
646 	if (disable_soft_wp_if_needed(flash))
647 		return 1;
648 
649 	parse_fmap(image, flash_size);
650 	/* check layout to determine what sysjumps we are required to do. */
651 	const struct flashrom_layout *const layout = get_layout(flash);
652 	const enum ec_current_image region_typ = parse_layout(layout);
653 
654 	if (ec_check_features(EC_FEATURE_EXEC_IN_RAM) <= 0) {
655 		/* Warning: before update, we jump the EC to RO copy. If you
656 		 * want to change this behavior, please also check the
657 		 * cros_ec_finish().
658 		 */
659 		msg_pwarn("EXEC_IN_RAM unsupported..");
660 
661 		if (!(region_typ & EC_IMAGE_RO) && cros_ec_get_current_image() == EC_IMAGE_RO) {
662 			msg_pwarn(" image contains RW and already in RO, skipping jump.\n");
663 			return 0;
664 		}
665 		if (!(region_typ & EC_IMAGE_RW) && cros_ec_get_current_image() == EC_IMAGE_RW) {
666 			msg_pwarn(" image contains RO and already in RW, skipping jump.\n");
667 			return 0;
668 		}
669 
670 		msg_pwarn(" unconditional jump to RO.\n");
671 		return cros_ec_jump_copy(EC_IMAGE_RO);
672 	}
673 	msg_pwarn("EXEC_IN_RAM supported - skip jumping to RO\n");
674 
675 	return 0;
676 }
677 
678 
679 /* Returns >0 if we need 2nd pass of erase_and_write_flash().
680  *         <0 if we cannot jump to any firmware copy.
681  *        ==0 if no more pass is needed.
682  *
683  * This function also jumps to new-updated firmware copy before return >0.
684  */
cros_ec_need_2nd_pass(void)685 int cros_ec_need_2nd_pass(void)
686 {
687 	if (!programming_ec())
688 		return 0;
689 
690 	if (!need_2nd_pass)
691 		return 0;
692 
693 	if (ec_check_features(EC_FEATURE_EXEC_IN_RAM) > 0)
694 		/* EC_RES_ACCESS_DENIED is returned when the block is either
695 		 * protected or unsafe. Thus, theoretically, we shouldn't reach
696 		 * here because everywhere is safe for EXEC_IN_RAM chips and
697 		 * WP is disabled before erase/write cycle starts.
698 		 * We can still let the 2nd pass run (and it will probably
699 		 * fail again).
700 		 */
701 		return 1;
702 
703 	if (cros_ec_jump_copy(EC_IMAGE_UNKNOWN))
704 		return -1;
705 
706 	return 1;
707 }
708 
cros_ec_erasure_failed(void)709 bool cros_ec_erasure_failed(void)
710 {
711 	return spi_acc_issue;
712 }
713 
714 /**
715  * Returns 0 for success.
716  * Try latest firmware: B > A > RO
717  */
cros_ec_finish(void)718 int cros_ec_finish(void)
719 {
720 	if (!programming_ec())
721           return 0;
722 
723 	/*
724 	 * Check that the EC had jumped to RO at cros_ec_prepare() so that
725 	 * the fwcopy[RO].flags is old (0) and A/B are new otherwise return.
726 	 */
727 	if (cros_ec_get_current_image() != EC_IMAGE_RO)
728 		return 0;
729 
730 	/* For EC with RWSIG enabled. We need a cold reboot to enable
731 	 * EC_FLASH_PROTECT_ALL_NOW and make sure RWSIG check is performed.
732 	 */
733 	if (rwsig_enabled) {
734 		msg_pdbg("RWSIG enabled: doing a cold reboot to enable WP.\n");
735 		int rc = cros_ec_cold_reboot(0);
736 		usleep(EC_RWSIG_JUMP_TO_RW_DELAY);
737 		return rc;
738 	}
739 
740 	return 0;
741 }
742 
cros_ec_read(struct flashctx * flash,uint8_t * readarr,unsigned int blockaddr,unsigned int readcnt)743 static int cros_ec_read(struct flashctx *flash, uint8_t *readarr,
744              unsigned int blockaddr, unsigned int readcnt)
745 {
746 	int rc = 0;
747 	struct ec_params_flash_read p;
748 	const int maxlen = flash->mst->opaque.max_data_read;
749 	uint8_t buf[maxlen];
750 	unsigned offset = 0, count;
751 
752 	while (offset < readcnt) {
753 		count = min(maxlen, readcnt - offset);
754 		p.offset = blockaddr + offset;
755 		p.size = count;
756 		rc = cros_ec_command(EC_CMD_FLASH_READ,
757 					0, &p, sizeof(p), buf, count);
758 		if (rc < 0) {
759 			msg_perr("CROS_EC: Flash read error at offset 0x%x\n",
760 			         blockaddr + offset);
761 			return rc;
762 		} else {
763 			rc = EC_RES_SUCCESS;
764 		}
765 
766 		memcpy(readarr + offset, buf, count);
767 		offset += count;
768 	}
769 
770 	return rc;
771 }
772 
773 /*
774  * returns 0 to indicate area does not overlap current EC image
775  * returns 1 to indicate area overlaps current EC image or error
776  *
777  * We can't get rid of this. The ECs should know what region is safe to erase
778  * or write. We should let them decide (and return EC_RES_ACCESS_DENIED).
779  * Not all existing EC firmware can do so.
780  */
in_current_image(unsigned int addr,unsigned int len)781 static int in_current_image(unsigned int addr, unsigned int len)
782 {
783 	const enum ec_current_image image = cros_ec_dev_priv.current_image;
784 	const uint32_t region_offset = cros_ec_dev_priv.region[image].offset;
785 	const uint32_t region_size = cros_ec_dev_priv.region[image].size;
786 
787 	if ((addr + len - 1 < region_offset) ||
788 		(addr > region_offset + region_size - 1)) {
789 		return 0;
790 	}
791 	return 1;
792 }
793 
794 
cros_ec_block_erase(struct flashctx * flash,unsigned int blockaddr,unsigned int len)795 int cros_ec_block_erase(struct flashctx *flash, unsigned int blockaddr,
796                         unsigned int len)
797 {
798 	spi_acc_issue = false; /* reset SPI access workaround singleton */
799 
800 	if (ec_check_features(EC_FEATURE_EXEC_IN_RAM) <= 0 &&
801 			in_current_image(blockaddr, len)) {
802 		cros_ec_invalidate_copy(blockaddr, len);
803 		need_2nd_pass = 1;
804 		spi_acc_issue = true;
805 		return 0; /* ignore SPI access denied, check spi_acc_issue. */
806 	}
807 
808 	struct ec_params_flash_erase_v1 erase;
809 	erase.params.offset = blockaddr;
810 	erase.params.size = len;
811 	uint32_t mask;
812 	int rc = ec_get_cmd_versions(EC_CMD_FLASH_ERASE, &mask);
813 	if (rc < 0) {
814 		msg_perr("Cannot determine erase command version\n");
815 		return 0;
816 	}
817 	int cmd_version = 31 - __builtin_clz(mask);
818 
819 	if (cmd_version == 0) {
820 		rc = cros_ec_command(EC_CMD_FLASH_ERASE, 0,
821 				&erase.params,
822 				sizeof(struct ec_params_flash_erase), NULL, 0);
823 		if (rc == -EC_RES_ACCESS_DENIED) {
824 			// this is active image.
825 			cros_ec_invalidate_copy(blockaddr, len);
826 			need_2nd_pass = 1;
827 			spi_acc_issue = true;
828 			return 0; /* ignore SPI access denied, check spi_acc_issue. */
829 		}
830 		if (rc < 0) {
831 			msg_perr("CROS_EC: Flash erase error at address 0x%x, rc=%d\n",
832 					blockaddr, rc);
833 			return rc;
834 		}
835 		goto end_flash_erase;
836 	}
837 
838 	if (len >= FLASH_SMALL_REGION_THRESHOLD) {
839 		erase.cmd = FLASH_ERASE_SECTOR_ASYNC;
840 	} else {
841 		erase.cmd = FLASH_ERASE_SECTOR;
842 	}
843 	rc = cros_ec_command(EC_CMD_FLASH_ERASE, cmd_version,
844 			      &erase, sizeof(erase), NULL, 0);
845 	switch (rc) {
846 	case 0:
847 		break;
848 	case -EC_RES_ACCESS_DENIED:
849 		// this is active image.
850 		cros_ec_invalidate_copy(blockaddr, len);
851 		need_2nd_pass = 1;
852 		spi_acc_issue = true;
853 		return 0; /* ignore SPI access denied, check spi_acc_issue. */
854 	case -EC_RES_BUSY:
855 		msg_perr("CROS_EC: Flash erase command "
856 				" already in progress\n");
857 		return rc;
858 	default:
859 		return rc;
860 	}
861 	if (len < FLASH_SMALL_REGION_THRESHOLD)
862 		goto end_flash_erase;
863 
864 	/* Wait for the erase command to complete */
865 	rc = -EC_RES_BUSY;
866 
867 /* wait up to 10s to erase a flash sector */
868 #define CROS_EC_ERASE_ASYNC_TIMEOUT 10000000
869 /* wait .5 second between queries. */
870 #define CROS_EC_ERASE_ASYNC_WAIT 500000
871 
872 	int timeout = 0;
873 	while (rc < 0 && timeout < CROS_EC_ERASE_ASYNC_TIMEOUT) {
874 		usleep(CROS_EC_ERASE_ASYNC_WAIT);
875 		timeout += CROS_EC_ERASE_ASYNC_WAIT;
876 		erase.cmd = FLASH_ERASE_GET_RESULT;
877 		rc = cros_ec_command(EC_CMD_FLASH_ERASE, cmd_version,
878 				&erase, sizeof(erase), NULL, 0);
879 	}
880 	if (rc < 0) {
881 		msg_perr("CROS_EC: Flash erase error at address 0x%x, rc=%d\n",
882 		         blockaddr, rc);
883 		return rc;
884 	}
885 
886 end_flash_erase:
887 	if (rc > 0) {
888 		/*
889 		 * Can happen if the command with retried with
890 		 * EC_CMD_GET_COMMS_STATUS
891 		 */
892 		rc = -EC_RES_SUCCESS;
893 	}
894 	return rc;
895 }
896 
897 
cros_ec_write(struct flashctx * flash,const uint8_t * buf,unsigned int addr,unsigned int nbytes)898 static int cros_ec_write(struct flashctx *flash, const uint8_t *buf, unsigned int addr,
899                   unsigned int nbytes)
900 {
901 	int rc = 0;
902 	unsigned int written = 0, real_write_size;
903 	struct ec_params_flash_write p;
904 
905 	/*
906 	 * For b:35542013, to workaround the undersized
907 	 * outdata buffer issue in kernel.
908 	 * chunk size should exclude the packet header ec_params_flash_write.
909 	 */
910 	real_write_size = min(flash->mst->opaque.max_data_write - sizeof(p),
911 			      cros_ec_dev_priv.ideal_write_size);
912 	assert(real_write_size > 0);
913 
914 	uint8_t *packet = malloc(sizeof(p) + real_write_size);
915 	if (!packet)
916 		return -1;
917 
918 	for (unsigned int i = 0; i < nbytes; i += written) {
919 		written = min(nbytes - i, real_write_size);
920 		p.offset = addr + i;
921 		p.size = written;
922 
923 		if (ec_check_features(EC_FEATURE_EXEC_IN_RAM) <= 0 &&
924 				in_current_image(p.offset, p.size)) {
925 			need_2nd_pass = 1;
926 			cros_ec_invalidate_copy(addr, nbytes);
927 			free(packet);
928 			return 0; /* SPI access denied is ignored. */
929 		}
930 
931 		memcpy(packet, &p, sizeof(p));
932 		memcpy(packet + sizeof(p), &buf[i], written);
933 		rc = cros_ec_command(EC_CMD_FLASH_WRITE,
934 				0, packet, sizeof(p) + p.size, NULL, 0);
935 		if (rc == -EC_RES_ACCESS_DENIED) {
936 			need_2nd_pass = 1; /* this is a active image. */
937 			cros_ec_invalidate_copy(addr, nbytes);
938 			free(packet);
939 			return 0; /* SPI access denied is ignored. */
940 		}
941 
942 		if (rc < 0) break;
943 		rc = EC_RES_SUCCESS;
944 	}
945 
946 	free(packet);
947 	return rc;
948 }
949 
cros_ec_probe_size(struct flashctx * flash)950 static int cros_ec_probe_size(struct flashctx *flash)
951 {
952 	int rc = cros_ec_get_current_image();
953 	if (rc < 0) {
954 		msg_perr("%s(): Failed to probe (no current image): %d\n",
955 			 __func__, rc);
956 		return 0;
957 	}
958 	cros_ec_dev_priv.current_image = rc;
959 	cros_ec_dev_priv.region = &regions[0];
960 
961 	uint32_t mask;
962 	rc = ec_get_cmd_versions(EC_CMD_FLASH_INFO, &mask);
963 	if (rc < 0) {
964 		msg_perr("Cannot determine write command version\n");
965 		return 0;
966 	}
967 	int cmd_version = 31 - __builtin_clz(mask);
968 
969 	struct block_eraser *eraser = &flash->chip->block_erasers[0];
970 	flash->chip->page_size = flash->mst->opaque.max_data_read;
971 
972 	if (cmd_version < 2) {
973 		struct ec_response_flash_info_1 info;
974 		/* Request general information about flash (v1 or below). */
975 		rc = cros_ec_command(EC_CMD_FLASH_INFO, cmd_version,
976 				NULL, 0, &info,
977 				(cmd_version > 0 ? sizeof(info) :
978 				 sizeof(struct ec_response_flash_info)));
979 		if (rc < 0) {
980 			msg_perr("%s(): FLASH_INFO v%d returns %d.\n", __func__,
981 					cmd_version, rc);
982 			return 0;
983 		}
984 		if (cmd_version == 0) {
985 			cros_ec_dev_priv.ideal_write_size =
986 				EC_FLASH_WRITE_VER0_SIZE;
987 		} else {
988 			cros_ec_dev_priv.ideal_write_size = info.write_ideal_size;
989 			if (info.flags & EC_FLASH_INFO_ERASE_TO_0)
990 				flash->chip->feature_bits |=
991 					FEATURE_ERASED_ZERO;
992 		}
993 		flash->chip->total_size = info.flash_size / 1024;
994 
995 		eraser->eraseblocks[0].size = info.erase_block_size;
996 		eraser->eraseblocks[0].count = info.flash_size /
997 			eraser->eraseblocks[0].size;
998 	} else {
999 		struct ec_response_flash_info_2 info_2;
1000 		struct ec_params_flash_info_2 params_2;
1001 		struct ec_response_flash_info_2 *info_2_p = &info_2;
1002 		int size_info_v2 = sizeof(info_2), i;
1003 
1004 		params_2.num_banks_desc = 0;
1005 		/*
1006 		 * Call FLASH_INFO twice, second time with all banks
1007 		 * information.
1008 		 */
1009 		for (i = 0; i < 2; i++) {
1010 			rc = cros_ec_command(EC_CMD_FLASH_INFO,
1011 					cmd_version, &params_2,
1012 					sizeof(params_2),
1013 					info_2_p, size_info_v2);
1014 			if (rc < 0) {
1015 				msg_perr("%s(): FLASH_INFO(%d) v%d returns %d.\n",
1016 						__func__,
1017 						params_2.num_banks_desc,
1018 						cmd_version, rc);
1019 				if (info_2_p != &info_2)
1020 					free(info_2_p);
1021 				return 0;
1022 			} else if (i > 0) {
1023 				break;
1024 			}
1025 			params_2.num_banks_desc = info_2_p->num_banks_total;
1026 			size_info_v2 += info_2_p->num_banks_total *
1027 				sizeof(struct ec_flash_bank);
1028 
1029 			info_2_p = malloc(size_info_v2);
1030 			if (!info_2_p) {
1031 				msg_perr("%s(): malloc of %d banks failed\n",
1032 					 __func__, params_2.num_banks_desc);
1033 				return 0;
1034 			}
1035 		}
1036 		flash->chip->total_size = info_2_p->flash_size / 1024;
1037 		for (i = 0; i < info_2_p->num_banks_desc; i++) {
1038 			/* Allow overriding the erase block size in case EC is incorrect */
1039 			eraser->eraseblocks[i].size =
1040 				 (unsigned) 1 << info_2_p->banks[i].erase_size_exp;
1041 			eraser->eraseblocks[i].count =
1042 				info_2_p->banks[i].count <<
1043 				(info_2_p->banks[i].size_exp -
1044 				 info_2_p->banks[i].erase_size_exp);
1045 		}
1046 		cros_ec_dev_priv.ideal_write_size = info_2_p->write_ideal_size;
1047 #if 0
1048 		/*
1049 		 * TODO(b/38506987)Comment out, as some firmware were not
1050 		 * setting this flag properly.
1051 		 */
1052 		if (info_2_p->flags & EC_FLASH_INFO_ERASE_TO_0)
1053 			flash->chip->feature_bits |= FEATURE_ERASED_ZERO;
1054 #endif
1055 		free(info_2_p);
1056 	}
1057 	eraser->block_erase = CROS_EC_BLOCK_ERASE;
1058 	/*
1059 	 * Some STM32 variants erase bits to 0. For now, assume that this
1060 	 * applies to STM32L parts.
1061 	 *
1062 	 * FIXME: This info will eventually be exposed via some EC command.
1063 	 * See chrome-os-partner:20973.
1064 	 */
1065 	struct ec_response_get_chip_info chip_info;
1066 	rc = cros_ec_command(EC_CMD_GET_CHIP_INFO,
1067 			0, NULL, 0, &chip_info, sizeof(chip_info));
1068 	if (rc < 0) {
1069 		msg_perr("%s(): CHIP_INFO returned %d.\n", __func__, rc);
1070 		return 0;
1071 	}
1072 	if (!strncmp(chip_info.name, "stm32l1", 7))
1073 		flash->chip->feature_bits |= FEATURE_ERASED_ZERO;
1074 
1075 
1076 
1077 	struct ec_response_flash_spi_info spi_info;
1078 	rc = cros_ec_command(EC_CMD_FLASH_SPI_INFO,
1079 				0, NULL, 0, &spi_info, sizeof(spi_info));
1080 	if (rc < 0) {
1081 		static char chip_vendor[32];
1082 		static char chip_name[32];
1083 
1084 		memcpy(chip_vendor, chip_info.vendor, sizeof(chip_vendor));
1085 		memcpy(chip_name, chip_info.name, sizeof(chip_name));
1086 		flash->chip->vendor = chip_vendor;
1087 		flash->chip->name = chip_name;
1088 		flash->chip->tested = TEST_OK_PREWB;
1089 	} else {
1090 		const struct flashchip *f;
1091 		uint32_t mfg = spi_info.jedec[0];
1092 		uint32_t model = (spi_info.jedec[1] << 8) | spi_info.jedec[2];
1093 
1094 		for (f = flashchips; f && f->name; f++) {
1095 			if (f->bustype != BUS_SPI)
1096 				continue;
1097 			if ((f->manufacture_id == mfg) &&
1098 				f->model_id == model) {
1099 				flash->chip->vendor = f->vendor;
1100 				flash->chip->name = f->name;
1101 				flash->chip->tested = f->tested;
1102 				break;
1103 			}
1104 		}
1105 	}
1106 
1107 	/* FIXME: EC_IMAGE_* is ordered differently from EC_FLASH_REGION_*,
1108 	 * so we need to be careful about using these enums as array indices */
1109 	rc = cros_ec_get_region_info(EC_FLASH_REGION_RO,
1110 				 &cros_ec_dev_priv.region[EC_IMAGE_RO]);
1111 	if (rc) {
1112 		msg_perr("%s(): Failed to probe (cannot find RO region): %d\n",
1113 			 __func__, rc);
1114 		return 0;
1115 	}
1116 
1117 	rc = cros_ec_get_region_info(EC_FLASH_REGION_RW,
1118 				 &cros_ec_dev_priv.region[EC_IMAGE_RW]);
1119 	if (rc) {
1120 		msg_perr("%s(): Failed to probe (cannot find RW region): %d\n",
1121 			 __func__, rc);
1122 		return 0;
1123 	}
1124 
1125 	return 1;
1126 };
1127 
1128 /* perform basic "hello" test to see if we can talk to the EC */
cros_ec_test(void)1129 static int cros_ec_test(void)
1130 {
1131 	struct ec_params_hello request;
1132 	struct ec_response_hello response;
1133 
1134 	/* Say hello to EC. */
1135 	request.in_data = 0xf0e0d0c0;  /* Expect EC will add on 0x01020304. */
1136 	msg_pdbg("%s: sending HELLO request with 0x%08x\n",
1137 	         __func__, request.in_data);
1138 	int rc = cros_ec_command(EC_CMD_HELLO, 0, &request,
1139 			     sizeof(request), &response, sizeof(response));
1140 	msg_pdbg("%s: response: 0x%08x\n", __func__, response.out_data);
1141 
1142 	if (rc < 0 || response.out_data != 0xf1e2d3c4) {
1143 		msg_pdbg("response.out_data is not 0xf1e2d3c4.\n"
1144 		         "rc=%d, request=0x%x response=0x%x\n",
1145 		         rc, request.in_data, response.out_data);
1146 		return 1;
1147 	}
1148 
1149 	return 0;
1150 }
1151 
cros_ec_set_max_size(struct opaque_master * op)1152 static void cros_ec_set_max_size(struct opaque_master *op)
1153 {
1154 	struct ec_response_get_protocol_info info;
1155 
1156 	msg_pdbg("%s: sending protoinfo command\n", __func__);
1157 	int rc = cros_ec_command(EC_CMD_GET_PROTOCOL_INFO, 0, NULL, 0,
1158 			      &info, sizeof(info));
1159 	msg_pdbg("%s: rc:%d\n", __func__, rc);
1160 
1161 	/*
1162 	 * Use V3 large size only if v2 protocol is not supported.
1163 	 * When v2 is supported, we may be using a kernel without v3 support,
1164 	 * leading to sending larger commands the kernel can support.
1165 	 */
1166 	if (rc == sizeof(info) && ((info.protocol_versions & (1<<2)) == 0)) {
1167 
1168 		op->max_data_write = info.max_request_packet_size -
1169 			sizeof(struct ec_host_request);
1170 		op->max_data_read = info.max_response_packet_size -
1171 			sizeof(struct ec_host_response);
1172 		/*
1173 		 * Due to a bug in NPCX SPI code (chromium:725580),
1174 		 * The EC may responds 163 when it meant 160; it should not
1175 		 * have included header and footer.
1176 		 */
1177 		op->max_data_read &= ~3;
1178 		msg_pdbg("%s: max_write:%d max_read:%d\n", __func__,
1179 			 op->max_data_write, op->max_data_read);
1180 	}
1181 }
1182 
cros_ec_wp_read_cfg(struct flashrom_wp_cfg * cfg,struct flashctx * flash)1183 static enum flashrom_wp_result cros_ec_wp_read_cfg(struct flashrom_wp_cfg *cfg, struct flashctx *flash)
1184 {
1185 	struct ec_params_flash_protect p;
1186 	struct ec_response_flash_protect r;
1187 
1188 	memset(&p, 0, sizeof(p));
1189 	int rc = cros_ec_command(EC_CMD_FLASH_PROTECT,
1190 			EC_VER_FLASH_PROTECT, &p, sizeof(p), &r, sizeof(r));
1191 
1192 	if (rc < (int)sizeof(r)) {
1193 		msg_perr("FAILED: Too little data returned (expected:%zd, "
1194 			 "actual:%d)\n", sizeof(r), rc);
1195 		return FLASHROM_WP_ERR_READ_FAILED;
1196 	}
1197 
1198 	if (r.flags & EC_FLASH_PROTECT_RO_AT_BOOT) {
1199 		struct ec_response_flash_region_info info;
1200 
1201 		rc = cros_ec_get_region_info(EC_FLASH_REGION_WP_RO, &info);
1202 		if (rc < 0) {
1203 			msg_perr("FAILED: Cannot get the WP_RO region info: "
1204 				 "%d\n", rc);
1205 			return FLASHROM_WP_ERR_READ_FAILED;
1206 		}
1207 
1208 		cfg->range.start = info.offset;
1209 		cfg->range.len = info.size;
1210 		cfg->mode = FLASHROM_WP_MODE_HARDWARE;
1211 	} else {
1212 		cfg->range.start = 0;
1213 		cfg->range.len = 0;
1214 		cfg->mode = FLASHROM_WP_MODE_DISABLED;
1215 	}
1216 
1217 	/*
1218 	 * If neither RO_NOW or ALL_NOW is set, it means write protect is
1219 	 * NOT active now.
1220 	 */
1221 	if (!(r.flags & (EC_FLASH_PROTECT_RO_NOW | EC_FLASH_PROTECT_ALL_NOW))) {
1222 		cfg->range.start = 0;
1223 		cfg->range.len = 0;
1224 	}
1225 
1226 	return FLASHROM_WP_OK;
1227 }
1228 
cros_ec_wp_write_cfg(struct flashctx * flash,const struct flashrom_wp_cfg * cfg)1229 static enum flashrom_wp_result cros_ec_wp_write_cfg(struct flashctx *flash, const struct flashrom_wp_cfg *cfg)
1230 {
1231 	bool enable = cfg->mode == FLASHROM_WP_MODE_HARDWARE;
1232 
1233 	struct ec_params_flash_protect p;
1234 	struct ec_response_flash_protect r;
1235 	const int ro_at_boot_flag = EC_FLASH_PROTECT_RO_AT_BOOT;
1236 	const int ro_now_flag = EC_FLASH_PROTECT_RO_NOW;
1237 	int need_an_ec_cold_reset = 0;
1238 	int rc;
1239 
1240 	/* Try to set RO_AT_BOOT and RO_NOW first */
1241 	memset(&p, 0, sizeof(p));
1242 	p.mask = (ro_at_boot_flag | ro_now_flag);
1243 	p.flags = enable ? (ro_at_boot_flag | ro_now_flag) : 0;
1244 	rc = cros_ec_command(EC_CMD_FLASH_PROTECT,
1245 			EC_VER_FLASH_PROTECT, &p, sizeof(p), &r, sizeof(r));
1246 	if (rc < 0) {
1247 		msg_perr("FAILED: Cannot set the RO_AT_BOOT and RO_NOW: %d\n",
1248 			 rc);
1249 		return FLASHROM_WP_ERR_WRITE_FAILED;
1250 	}
1251 
1252 	/* Read back */
1253 	memset(&p, 0, sizeof(p));
1254 	rc = cros_ec_command(EC_CMD_FLASH_PROTECT,
1255 			EC_VER_FLASH_PROTECT, &p, sizeof(p), &r, sizeof(r));
1256 	if (rc < 0) {
1257 		msg_perr("FAILED: Cannot get RO_AT_BOOT and RO_NOW: %d\n",
1258 			 rc);
1259 		return FLASHROM_WP_ERR_WRITE_FAILED;
1260 	}
1261 
1262 	if (!enable) {
1263 		/* The disable case is easier to check. */
1264 		if (r.flags & ro_at_boot_flag) {
1265 			msg_perr("FAILED: RO_AT_BOOT is not clear.\n");
1266 			return FLASHROM_WP_ERR_WRITE_FAILED;
1267 		} else if (r.flags & ro_now_flag) {
1268 			msg_perr("FAILED: RO_NOW is asserted unexpectedly.\n");
1269 			need_an_ec_cold_reset = 1;
1270 			goto exit;
1271 		}
1272 
1273 		msg_pdbg("INFO: RO_AT_BOOT is clear.\n");
1274 		return FLASHROM_WP_OK;
1275 	}
1276 
1277 	/* Check if RO_AT_BOOT is set. If not, fail in anyway. */
1278 	if (r.flags & ro_at_boot_flag) {
1279 		msg_pdbg("INFO: RO_AT_BOOT has been set.\n");
1280 	} else {
1281 		msg_perr("FAILED: RO_AT_BOOT is not set.\n");
1282 		return FLASHROM_WP_ERR_WRITE_FAILED;
1283 	}
1284 
1285 	/* Then, we check if the protection has been activated. */
1286 	if (r.flags & ro_now_flag) {
1287 		/* Good, RO_NOW is set. */
1288 		msg_pdbg("INFO: RO_NOW is set. WP is active now.\n");
1289 	} else if (r.writable_flags & EC_FLASH_PROTECT_ALL_NOW) {
1290 		msg_pdbg("WARN: RO_NOW is not set. Trying ALL_NOW.\n");
1291 
1292 		memset(&p, 0, sizeof(p));
1293 		p.mask = EC_FLASH_PROTECT_ALL_NOW;
1294 		p.flags = EC_FLASH_PROTECT_ALL_NOW;
1295 		rc = cros_ec_command(EC_CMD_FLASH_PROTECT,
1296 				      EC_VER_FLASH_PROTECT,
1297 				      &p, sizeof(p), &r, sizeof(r));
1298 		if (rc < 0) {
1299 			msg_perr("FAILED: Cannot set ALL_NOW: %d\n", rc);
1300 			return FLASHROM_WP_ERR_WRITE_FAILED;
1301 		}
1302 
1303 		/* Read back */
1304 		memset(&p, 0, sizeof(p));
1305 		rc = cros_ec_command(EC_CMD_FLASH_PROTECT,
1306 				      EC_VER_FLASH_PROTECT,
1307 				      &p, sizeof(p), &r, sizeof(r));
1308 		if (rc < 0) {
1309 			msg_perr("FAILED:Cannot get ALL_NOW: %d\n", rc);
1310 			return FLASHROM_WP_ERR_WRITE_FAILED;
1311 		}
1312 
1313 		if (!(r.flags & EC_FLASH_PROTECT_ALL_NOW)) {
1314 			msg_perr("FAILED: ALL_NOW is not set.\n");
1315 			need_an_ec_cold_reset = 1;
1316 			goto exit;
1317 		}
1318 
1319 		msg_pdbg("INFO: ALL_NOW has been set. WP is active now.\n");
1320 
1321 		/*
1322 		 * Our goal is to protect the RO ASAP. The entire protection
1323 		 * is just a workaround for platform not supporting RO_NOW.
1324 		 * It has side-effect that the RW is also protected and leads
1325 		 * the RW update failed. So, we arrange an EC code reset to
1326 		 * unlock RW ASAP.
1327 		 */
1328 		rc = cros_ec_cold_reboot(EC_REBOOT_FLAG_ON_AP_SHUTDOWN);
1329 		if (rc < 0) {
1330 			msg_perr("WARN: Cannot arrange a cold reset at next "
1331 				 "shutdown to unlock entire protect.\n");
1332 			msg_perr("      But you can do it manually.\n");
1333 		} else {
1334 			msg_pdbg("INFO: A cold reset is arranged at next "
1335 				 "shutdown.\n");
1336 		}
1337 
1338 	} else {
1339 		msg_perr("FAILED: RO_NOW is not set.\n");
1340 		msg_perr("FAILED: The PROTECT_RO_AT_BOOT is set, but cannot "
1341 			 "make write protection active now.\n");
1342 		need_an_ec_cold_reset = 1;
1343 	}
1344 
1345 exit:
1346 	if (need_an_ec_cold_reset) {
1347 		msg_perr("FAILED: You may need a reboot to take effect of "
1348 			 "PROTECT_RO_AT_BOOT.\n");
1349 		return FLASHROM_WP_ERR_WRITE_FAILED;
1350 	}
1351 
1352 	return FLASHROM_WP_OK;
1353 }
1354 
cros_ec_wp_get_available_ranges(struct flashrom_wp_ranges ** list,struct flashctx * flash)1355 static enum flashrom_wp_result cros_ec_wp_get_available_ranges(struct flashrom_wp_ranges **list, struct flashctx *flash)
1356 {
1357 	/* Allocate output buffer */
1358 	*list = calloc(1, sizeof(struct flashrom_wp_ranges));
1359 	if (!*list)
1360 		return FLASHROM_WP_ERR_OTHER;
1361 
1362 	(*list)->ranges = calloc(2, sizeof(struct wp_range));
1363 	if (!(*list)->ranges) {
1364 		free(*list);
1365 		return FLASHROM_WP_ERR_OTHER;
1366 	}
1367 
1368 	/* Read the size of the EC's only protection region */
1369 	struct ec_response_flash_region_info info;
1370 	if (cros_ec_get_region_info(EC_FLASH_REGION_WP_RO, &info) < 0)
1371 		return FLASHROM_WP_ERR_OTHER;
1372 
1373 	/* WP disabled */
1374 	(*list)->ranges[0].start = 0;
1375 	(*list)->ranges[0].len = 0;
1376 
1377 	/* WP enabled */
1378 	(*list)->ranges[1].start = info.offset;
1379 	(*list)->ranges[1].len = info.size;
1380 
1381 	(*list)->count = 2;
1382 
1383 	return FLASHROM_WP_OK;
1384 }
1385 
1386 static struct opaque_master opaque_master_cros_ec_dev = {
1387 	.max_data_read	= 128,
1388 	.max_data_write	= 128,
1389 	.probe		= cros_ec_probe_size,
1390 	.read		= cros_ec_read,
1391 	.write		= cros_ec_write,
1392 	.erase		= cros_ec_block_erase,
1393 	.wp_read_cfg    = cros_ec_wp_read_cfg,
1394 	.wp_write_cfg   = cros_ec_wp_write_cfg,
1395 	.wp_get_ranges  = cros_ec_wp_get_available_ranges,
1396 	.data 		= NULL
1397 };
1398 
cros_ec_dev_shutdown(void * data)1399 static int cros_ec_dev_shutdown(void *data)
1400 {
1401 	close(g_cros_ec_fd);
1402 	return 0;
1403 }
1404 
cros_ec_init(const struct programmer_cfg * cfg)1405 static int cros_ec_init(const struct programmer_cfg *cfg)
1406 {
1407 	const char *dev_path = "/dev/cros_ec";
1408 	msg_pdbg("%s: probing for CROS_EC at %s\n", __func__, dev_path);
1409 	g_cros_ec_fd = open(dev_path, O_RDWR);
1410 	if (g_cros_ec_fd < 0)
1411 		return g_cros_ec_fd;
1412 
1413 	if (cros_ec_test())
1414 		return 1;
1415 
1416 	cros_ec_set_max_size(&opaque_master_cros_ec_dev);
1417 
1418 	msg_pdbg("CROS_EC detected at %s\n", dev_path);
1419 	register_opaque_master(&opaque_master_cros_ec_dev, NULL);
1420 	register_shutdown(cros_ec_dev_shutdown, NULL);
1421 	g_cros_ec_detected = true;
1422 
1423 	return 0;
1424 }
1425 
1426 const struct programmer_entry programmer_cros_ec = {
1427 	.name			= "ec",
1428 	.type			= OTHER,
1429 	.devs.note		= "Google EC.\n",
1430 	.init			= cros_ec_init,
1431 };
1432