1 /* 2 * Chromium OS cros_ec driver - sandbox emulation 3 * 4 * Copyright (c) 2013 The Chromium OS Authors. 5 * 6 * SPDX-License-Identifier: GPL-2.0+ 7 */ 8 9 #include <common.h> 10 #include <cros_ec.h> 11 #include <dm.h> 12 #include <ec_commands.h> 13 #include <errno.h> 14 #include <hash.h> 15 #include <malloc.h> 16 #include <os.h> 17 #include <u-boot/sha256.h> 18 #include <spi.h> 19 #include <asm/state.h> 20 #include <asm/sdl.h> 21 #include <linux/input.h> 22 23 /* 24 * Ultimately it shold be possible to connect an Chrome OS EC emulation 25 * to U-Boot and remove all of this code. But this provides a test 26 * environment for bringing up chromeos_sandbox and demonstrating its 27 * utility. 28 * 29 * This emulation includes the following: 30 * 31 * 1. Emulation of the keyboard, by converting keypresses received from SDL 32 * into key scan data, passed back from the EC as key scan messages. The 33 * key layout is read from the device tree. 34 * 35 * 2. Emulation of vboot context - so this can be read/written as required. 36 * 37 * 3. Save/restore of EC state, so that the vboot context, flash memory 38 * contents and current image can be preserved across boots. This is important 39 * since the EC is supposed to continue running even if the AP resets. 40 * 41 * 4. Some event support, in particular allowing Escape to be pressed on boot 42 * to enter recovery mode. The EC passes this to U-Boot through the normal 43 * event message. 44 * 45 * 5. Flash read/write/erase support, so that software sync works. The 46 * protect messages are supported but no protection is implemented. 47 * 48 * 6. Hashing of the EC image, again to support software sync. 49 * 50 * Other features can be added, although a better path is probably to link 51 * the EC image in with U-Boot (Vic has demonstrated a prototype for this). 52 */ 53 54 #define KEYBOARD_ROWS 8 55 #define KEYBOARD_COLS 13 56 57 /* A single entry of the key matrix */ 58 struct ec_keymatrix_entry { 59 int row; /* key matrix row */ 60 int col; /* key matrix column */ 61 int keycode; /* corresponding linux key code */ 62 }; 63 64 /** 65 * struct ec_state - Information about the EC state 66 * 67 * @vbnv_context: Vboot context data stored by EC 68 * @ec_config: FDT config information about the EC (e.g. flashmap) 69 * @flash_data: Contents of flash memory 70 * @flash_data_len: Size of flash memory 71 * @current_image: Current image the EC is running 72 * @matrix_count: Number of keys to decode in matrix 73 * @matrix: Information about keyboard matrix 74 * @keyscan: Current keyscan information (bit set for each row/column pressed) 75 * @recovery_req: Keyboard recovery requested 76 */ 77 struct ec_state { 78 uint8_t vbnv_context[EC_VBNV_BLOCK_SIZE]; 79 struct fdt_cros_ec ec_config; 80 uint8_t *flash_data; 81 int flash_data_len; 82 enum ec_current_image current_image; 83 int matrix_count; 84 struct ec_keymatrix_entry *matrix; /* the key matrix info */ 85 uint8_t keyscan[KEYBOARD_COLS]; 86 bool recovery_req; 87 } s_state, *g_state; 88 89 /** 90 * cros_ec_read_state() - read the sandbox EC state from the state file 91 * 92 * If data is available, then blob and node will provide access to it. If 93 * not this function sets up an empty EC. 94 * 95 * @param blob: Pointer to device tree blob, or NULL if no data to read 96 * @param node: Node offset to read from 97 */ 98 static int cros_ec_read_state(const void *blob, int node) 99 { 100 struct ec_state *ec = &s_state; 101 const char *prop; 102 int len; 103 104 /* Set everything to defaults */ 105 ec->current_image = EC_IMAGE_RO; 106 if (!blob) 107 return 0; 108 109 /* Read the data if available */ 110 ec->current_image = fdtdec_get_int(blob, node, "current-image", 111 EC_IMAGE_RO); 112 prop = fdt_getprop(blob, node, "vbnv-context", &len); 113 if (prop && len == sizeof(ec->vbnv_context)) 114 memcpy(ec->vbnv_context, prop, len); 115 116 prop = fdt_getprop(blob, node, "flash-data", &len); 117 if (prop) { 118 ec->flash_data_len = len; 119 ec->flash_data = os_malloc(len); 120 if (!ec->flash_data) 121 return -ENOMEM; 122 memcpy(ec->flash_data, prop, len); 123 debug("%s: Loaded EC flash data size %#x\n", __func__, len); 124 } 125 126 return 0; 127 } 128 129 /** 130 * cros_ec_write_state() - Write out our state to the state file 131 * 132 * The caller will ensure that there is a node ready for the state. The node 133 * may already contain the old state, in which case it is overridden. 134 * 135 * @param blob: Device tree blob holding state 136 * @param node: Node to write our state into 137 */ 138 static int cros_ec_write_state(void *blob, int node) 139 { 140 struct ec_state *ec = g_state; 141 142 /* We are guaranteed enough space to write basic properties */ 143 fdt_setprop_u32(blob, node, "current-image", ec->current_image); 144 fdt_setprop(blob, node, "vbnv-context", ec->vbnv_context, 145 sizeof(ec->vbnv_context)); 146 return state_setprop(node, "flash-data", ec->flash_data, 147 ec->ec_config.flash.length); 148 } 149 150 SANDBOX_STATE_IO(cros_ec, "google,cros-ec", cros_ec_read_state, 151 cros_ec_write_state); 152 153 /** 154 * Return the number of bytes used in the specified image. 155 * 156 * This is the actual size of code+data in the image, as opposed to the 157 * amount of space reserved in flash for that image. This code is similar to 158 * that used by the real EC code base. 159 * 160 * @param ec Current emulated EC state 161 * @param entry Flash map entry containing the image to check 162 * @return actual image size in bytes, 0 if the image contains no content or 163 * error. 164 */ 165 static int get_image_used(struct ec_state *ec, struct fmap_entry *entry) 166 { 167 int size; 168 169 /* 170 * Scan backwards looking for 0xea byte, which is by definition the 171 * last byte of the image. See ec.lds.S for how this is inserted at 172 * the end of the image. 173 */ 174 for (size = entry->length - 1; 175 size > 0 && ec->flash_data[entry->offset + size] != 0xea; 176 size--) 177 ; 178 179 return size ? size + 1 : 0; /* 0xea byte IS part of the image */ 180 } 181 182 /** 183 * Read the key matrix from the device tree 184 * 185 * Keymap entries in the fdt take the form of 0xRRCCKKKK where 186 * RR=Row CC=Column KKKK=Key Code 187 * 188 * @param ec Current emulated EC state 189 * @param node Keyboard node of device tree containing keyscan information 190 * @return 0 if ok, -1 on error 191 */ 192 static int keyscan_read_fdt_matrix(struct ec_state *ec, ofnode node) 193 { 194 const u32 *cell; 195 int upto; 196 int len; 197 198 cell = ofnode_get_property(node, "linux,keymap", &len); 199 ec->matrix_count = len / 4; 200 ec->matrix = calloc(ec->matrix_count, sizeof(*ec->matrix)); 201 if (!ec->matrix) { 202 debug("%s: Out of memory for key matrix\n", __func__); 203 return -1; 204 } 205 206 /* Now read the data */ 207 for (upto = 0; upto < ec->matrix_count; upto++) { 208 struct ec_keymatrix_entry *matrix = &ec->matrix[upto]; 209 u32 word; 210 211 word = fdt32_to_cpu(*cell++); 212 matrix->row = word >> 24; 213 matrix->col = (word >> 16) & 0xff; 214 matrix->keycode = word & 0xffff; 215 216 /* Hard-code some sanity limits for now */ 217 if (matrix->row >= KEYBOARD_ROWS || 218 matrix->col >= KEYBOARD_COLS) { 219 debug("%s: Matrix pos out of range (%d,%d)\n", 220 __func__, matrix->row, matrix->col); 221 return -1; 222 } 223 } 224 225 if (upto != ec->matrix_count) { 226 debug("%s: Read mismatch from key matrix\n", __func__); 227 return -1; 228 } 229 230 return 0; 231 } 232 233 /** 234 * Return the next keyscan message contents 235 * 236 * @param ec Current emulated EC state 237 * @param scan Place to put keyscan bytes for the keyscan message (must hold 238 * enough space for a full keyscan) 239 * @return number of bytes of valid scan data 240 */ 241 static int cros_ec_keyscan(struct ec_state *ec, uint8_t *scan) 242 { 243 const struct ec_keymatrix_entry *matrix; 244 int bytes = KEYBOARD_COLS; 245 int key[8]; /* allow up to 8 keys to be pressed at once */ 246 int count; 247 int i; 248 249 memset(ec->keyscan, '\0', bytes); 250 count = sandbox_sdl_scan_keys(key, ARRAY_SIZE(key)); 251 252 /* Look up keycode in matrix */ 253 for (i = 0, matrix = ec->matrix; i < ec->matrix_count; i++, matrix++) { 254 bool found; 255 int j; 256 257 for (found = false, j = 0; j < count; j++) { 258 if (matrix->keycode == key[j]) 259 found = true; 260 } 261 262 if (found) { 263 debug("%d: %d,%d\n", matrix->keycode, matrix->row, 264 matrix->col); 265 ec->keyscan[matrix->col] |= 1 << matrix->row; 266 } 267 } 268 269 memcpy(scan, ec->keyscan, bytes); 270 return bytes; 271 } 272 273 /** 274 * Process an emulated EC command 275 * 276 * @param ec Current emulated EC state 277 * @param req_hdr Pointer to request header 278 * @param req_data Pointer to body of request 279 * @param resp_hdr Pointer to place to put response header 280 * @param resp_data Pointer to place to put response data, if any 281 * @return length of response data, or 0 for no response data, or -1 on error 282 */ 283 static int process_cmd(struct ec_state *ec, 284 struct ec_host_request *req_hdr, const void *req_data, 285 struct ec_host_response *resp_hdr, void *resp_data) 286 { 287 int len; 288 289 /* TODO(sjg@chromium.org): Check checksums */ 290 debug("EC command %#0x\n", req_hdr->command); 291 292 switch (req_hdr->command) { 293 case EC_CMD_HELLO: { 294 const struct ec_params_hello *req = req_data; 295 struct ec_response_hello *resp = resp_data; 296 297 resp->out_data = req->in_data + 0x01020304; 298 len = sizeof(*resp); 299 break; 300 } 301 case EC_CMD_GET_VERSION: { 302 struct ec_response_get_version *resp = resp_data; 303 304 strcpy(resp->version_string_ro, "sandbox_ro"); 305 strcpy(resp->version_string_rw, "sandbox_rw"); 306 resp->current_image = ec->current_image; 307 debug("Current image %d\n", resp->current_image); 308 len = sizeof(*resp); 309 break; 310 } 311 case EC_CMD_VBNV_CONTEXT: { 312 const struct ec_params_vbnvcontext *req = req_data; 313 struct ec_response_vbnvcontext *resp = resp_data; 314 315 switch (req->op) { 316 case EC_VBNV_CONTEXT_OP_READ: 317 memcpy(resp->block, ec->vbnv_context, 318 sizeof(resp->block)); 319 len = sizeof(*resp); 320 break; 321 case EC_VBNV_CONTEXT_OP_WRITE: 322 memcpy(ec->vbnv_context, resp->block, 323 sizeof(resp->block)); 324 len = 0; 325 break; 326 default: 327 printf(" ** Unknown vbnv_context command %#02x\n", 328 req->op); 329 return -1; 330 } 331 break; 332 } 333 case EC_CMD_REBOOT_EC: { 334 const struct ec_params_reboot_ec *req = req_data; 335 336 printf("Request reboot type %d\n", req->cmd); 337 switch (req->cmd) { 338 case EC_REBOOT_DISABLE_JUMP: 339 len = 0; 340 break; 341 case EC_REBOOT_JUMP_RW: 342 ec->current_image = EC_IMAGE_RW; 343 len = 0; 344 break; 345 default: 346 puts(" ** Unknown type"); 347 return -1; 348 } 349 break; 350 } 351 case EC_CMD_HOST_EVENT_GET_B: { 352 struct ec_response_host_event_mask *resp = resp_data; 353 354 resp->mask = 0; 355 if (ec->recovery_req) { 356 resp->mask |= EC_HOST_EVENT_MASK( 357 EC_HOST_EVENT_KEYBOARD_RECOVERY); 358 } 359 360 len = sizeof(*resp); 361 break; 362 } 363 case EC_CMD_VBOOT_HASH: { 364 const struct ec_params_vboot_hash *req = req_data; 365 struct ec_response_vboot_hash *resp = resp_data; 366 struct fmap_entry *entry; 367 int ret, size; 368 369 entry = &ec->ec_config.region[EC_FLASH_REGION_RW]; 370 371 switch (req->cmd) { 372 case EC_VBOOT_HASH_RECALC: 373 case EC_VBOOT_HASH_GET: 374 size = SHA256_SUM_LEN; 375 len = get_image_used(ec, entry); 376 ret = hash_block("sha256", 377 ec->flash_data + entry->offset, 378 len, resp->hash_digest, &size); 379 if (ret) { 380 printf(" ** hash_block() failed\n"); 381 return -1; 382 } 383 resp->status = EC_VBOOT_HASH_STATUS_DONE; 384 resp->hash_type = EC_VBOOT_HASH_TYPE_SHA256; 385 resp->digest_size = size; 386 resp->reserved0 = 0; 387 resp->offset = entry->offset; 388 resp->size = len; 389 len = sizeof(*resp); 390 break; 391 default: 392 printf(" ** EC_CMD_VBOOT_HASH: Unknown command %d\n", 393 req->cmd); 394 return -1; 395 } 396 break; 397 } 398 case EC_CMD_FLASH_PROTECT: { 399 const struct ec_params_flash_protect *req = req_data; 400 struct ec_response_flash_protect *resp = resp_data; 401 uint32_t expect = EC_FLASH_PROTECT_ALL_NOW | 402 EC_FLASH_PROTECT_ALL_AT_BOOT; 403 404 printf("mask=%#x, flags=%#x\n", req->mask, req->flags); 405 if (req->flags == expect || req->flags == 0) { 406 resp->flags = req->flags ? EC_FLASH_PROTECT_ALL_NOW : 407 0; 408 resp->valid_flags = EC_FLASH_PROTECT_ALL_NOW; 409 resp->writable_flags = 0; 410 len = sizeof(*resp); 411 } else { 412 puts(" ** unexpected flash protect request\n"); 413 return -1; 414 } 415 break; 416 } 417 case EC_CMD_FLASH_REGION_INFO: { 418 const struct ec_params_flash_region_info *req = req_data; 419 struct ec_response_flash_region_info *resp = resp_data; 420 struct fmap_entry *entry; 421 422 switch (req->region) { 423 case EC_FLASH_REGION_RO: 424 case EC_FLASH_REGION_RW: 425 case EC_FLASH_REGION_WP_RO: 426 entry = &ec->ec_config.region[req->region]; 427 resp->offset = entry->offset; 428 resp->size = entry->length; 429 len = sizeof(*resp); 430 printf("EC flash region %d: offset=%#x, size=%#x\n", 431 req->region, resp->offset, resp->size); 432 break; 433 default: 434 printf("** Unknown flash region %d\n", req->region); 435 return -1; 436 } 437 break; 438 } 439 case EC_CMD_FLASH_ERASE: { 440 const struct ec_params_flash_erase *req = req_data; 441 442 memset(ec->flash_data + req->offset, 443 ec->ec_config.flash_erase_value, 444 req->size); 445 len = 0; 446 break; 447 } 448 case EC_CMD_FLASH_WRITE: { 449 const struct ec_params_flash_write *req = req_data; 450 451 memcpy(ec->flash_data + req->offset, req + 1, req->size); 452 len = 0; 453 break; 454 } 455 case EC_CMD_MKBP_STATE: 456 len = cros_ec_keyscan(ec, resp_data); 457 break; 458 case EC_CMD_ENTERING_MODE: 459 len = 0; 460 break; 461 default: 462 printf(" ** Unknown EC command %#02x\n", req_hdr->command); 463 return -1; 464 } 465 466 return len; 467 } 468 469 int cros_ec_sandbox_packet(struct udevice *udev, int out_bytes, int in_bytes) 470 { 471 struct cros_ec_dev *dev = dev_get_uclass_priv(udev); 472 struct ec_state *ec = dev_get_priv(dev->dev); 473 struct ec_host_request *req_hdr = (struct ec_host_request *)dev->dout; 474 const void *req_data = req_hdr + 1; 475 struct ec_host_response *resp_hdr = (struct ec_host_response *)dev->din; 476 void *resp_data = resp_hdr + 1; 477 int len; 478 479 len = process_cmd(ec, req_hdr, req_data, resp_hdr, resp_data); 480 if (len < 0) 481 return len; 482 483 resp_hdr->struct_version = 3; 484 resp_hdr->result = EC_RES_SUCCESS; 485 resp_hdr->data_len = len; 486 resp_hdr->reserved = 0; 487 len += sizeof(*resp_hdr); 488 resp_hdr->checksum = 0; 489 resp_hdr->checksum = (uint8_t) 490 -cros_ec_calc_checksum((const uint8_t *)resp_hdr, len); 491 492 return in_bytes; 493 } 494 495 void cros_ec_check_keyboard(struct cros_ec_dev *dev) 496 { 497 struct ec_state *ec = dev_get_priv(dev->dev); 498 ulong start; 499 500 printf("Press keys for EC to detect on reset (ESC=recovery)..."); 501 start = get_timer(0); 502 while (get_timer(start) < 1000) 503 ; 504 putc('\n'); 505 if (!sandbox_sdl_key_pressed(KEY_ESC)) { 506 ec->recovery_req = true; 507 printf(" - EC requests recovery\n"); 508 } 509 } 510 511 int cros_ec_probe(struct udevice *dev) 512 { 513 struct ec_state *ec = dev->priv; 514 struct cros_ec_dev *cdev = dev->uclass_priv; 515 struct udevice *keyb_dev; 516 ofnode node; 517 int err; 518 519 memcpy(ec, &s_state, sizeof(*ec)); 520 err = cros_ec_decode_ec_flash(dev, &ec->ec_config); 521 if (err) { 522 debug("%s: Cannot device EC flash\n", __func__); 523 return err; 524 } 525 526 node = ofnode_null(); 527 for (device_find_first_child(dev, &keyb_dev); 528 keyb_dev; 529 device_find_next_child(&keyb_dev)) { 530 if (device_get_uclass_id(keyb_dev) == UCLASS_KEYBOARD) { 531 node = dev_ofnode(keyb_dev); 532 break; 533 } 534 } 535 if (!ofnode_valid(node)) { 536 debug("%s: No cros_ec keyboard found\n", __func__); 537 } else if (keyscan_read_fdt_matrix(ec, node)) { 538 debug("%s: Could not read key matrix\n", __func__); 539 return -1; 540 } 541 542 /* If we loaded EC data, check that the length matches */ 543 if (ec->flash_data && 544 ec->flash_data_len != ec->ec_config.flash.length) { 545 printf("EC data length is %x, expected %x, discarding data\n", 546 ec->flash_data_len, ec->ec_config.flash.length); 547 os_free(ec->flash_data); 548 ec->flash_data = NULL; 549 } 550 551 /* Otherwise allocate the memory */ 552 if (!ec->flash_data) { 553 ec->flash_data_len = ec->ec_config.flash.length; 554 ec->flash_data = os_malloc(ec->flash_data_len); 555 if (!ec->flash_data) 556 return -ENOMEM; 557 } 558 559 cdev->dev = dev; 560 g_state = ec; 561 return cros_ec_register(dev); 562 } 563 564 struct dm_cros_ec_ops cros_ec_ops = { 565 .packet = cros_ec_sandbox_packet, 566 }; 567 568 static const struct udevice_id cros_ec_ids[] = { 569 { .compatible = "google,cros-ec-sandbox" }, 570 { } 571 }; 572 573 U_BOOT_DRIVER(cros_ec_sandbox) = { 574 .name = "cros_ec_sandbox", 575 .id = UCLASS_CROS_EC, 576 .of_match = cros_ec_ids, 577 .probe = cros_ec_probe, 578 .priv_auto_alloc_size = sizeof(struct ec_state), 579 .ops = &cros_ec_ops, 580 }; 581