int get_recovery_mode_switch(void) { uint32_t ec_events; ec_events = google_chromeec_get_events_b(); /* Enter recovery mode either on keyboard recovery / fastboot event. */ return !!((ec_events & EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_RECOVERY)) || (ec_events & EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_FASTBOOT))); }
void google_chromeec_log_events(uint64_t mask) { u8 event; uint64_t wake_mask; bool restore_wake_mask = false; if (!IS_ENABLED(CONFIG_ELOG)) return; /* * If the EC supports unified wake masks, then there is no need to set * wake mask before reading out the host events. */ if (google_chromeec_check_feature(EC_FEATURE_UNIFIED_WAKE_MASKS) != 1) { wake_mask = google_chromeec_get_wake_mask(); google_chromeec_set_wake_mask(mask); restore_wake_mask = true; } while ((event = google_chromeec_get_event()) != 0) { if (EC_HOST_EVENT_MASK(event) & mask) elog_add_event_byte(ELOG_TYPE_EC_EVENT, event); } if (restore_wake_mask) google_chromeec_set_wake_mask(wake_mask); }
int clear_recovery_mode_switch(void) { const uint32_t kb_rec_mask = EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_RECOVERY); /* Unconditionally clear the EC recovery request. */ return google_chromeec_clear_events_b(kb_rec_mask); }
int get_recovery_mode_switch(void) { uint32_t ec_events; ec_events = google_chromeec_get_events_b(); return !!(ec_events & EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_RECOVERY)); }
static void google_chromeec_elog_add_recovery_event(void *unused) { uint64_t *events = cbmem_find(CBMEM_ID_EC_HOSTEVENT); uint8_t event_byte = EC_EVENT_KEYBOARD_RECOVERY; if (!events) return; if (!(*events & EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_RECOVERY))) return; if (*events & EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_RECOVERY_HW_REINIT)) event_byte = EC_EVENT_KEYBOARD_RECOVERY_HWREINIT; elog_add_event_byte(ELOG_TYPE_EC_EVENT, event_byte); }
int clear_recovery_mode_switch(void) { if (IS_ENABLED(CONFIG_EC_GOOGLE_CHROMEEC)) /* Clear keyboard recovery event. */ return google_chromeec_clear_events_b( EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_RECOVERY)); return 0; }
int get_recovery_mode_switch(void) { /* Check for dedicated recovery switch first. */ if (google_chromeec_get_switches() & EC_SWITCH_DEDICATED_RECOVERY) return 1; /* Otherwise check if the EC has posted the keyboard recovery event. */ return !!(google_chromeec_get_events_b() & EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_RECOVERY)); }
/* * In AP S0 -> S3 & S0ix transitions, * the chipset_suspend is called. * * The chipset_in_state(CHIPSET_STATE_STANDBY | CHIPSET_STATE_ON) * is used to detect the S0ix transiton. * * During S0ix entry, the wake mask for lid open is enabled. * */ void lpc_enable_wake_mask_for_lid_open(void) { if ((chipset_in_state(CHIPSET_STATE_STANDBY | CHIPSET_STATE_ON)) || chipset_in_state(CHIPSET_STATE_STANDBY)) { uint32_t mask = 0; mask = ((lpc_get_host_event_mask(LPC_HOST_EVENT_WAKE)) | EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN)); lpc_set_host_event_mask(LPC_HOST_EVENT_WAKE, mask); } }
int clear_recovery_mode_switch(void) { #if IS_ENABLED(CONFIG_EC_GOOGLE_CHROMEEC) const uint32_t kb_rec_mask = EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_RECOVERY); /* Unconditionally clear the EC recovery request. */ return google_chromeec_clear_events_b(kb_rec_mask); #else return 0; #endif }
int get_recovery_mode_switch(void) { uint32_t ec_events; /* The GPIO is active low. */ if (!gpio_get(GPIO_RECOVERY)) return 1; ec_events = google_chromeec_get_events_b(); return !!(ec_events & EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_RECOVERY)); }
int cros_ec_get_lid_shutdown_mask(struct udevice *dev) { u32 mask; int ret; ret = cros_ec_get_event_mask(dev, EC_CMD_HOST_EVENT_GET_SMI_MASK, &mask); if (ret < 0) return ret; return !!(mask & EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_CLOSED)); }
int get_recovery_mode_switch(void) { #if CONFIG_EC_GOOGLE_CHROMEEC uint32_t ec_events; ec_events = google_chromeec_get_events_b(); return !!(ec_events & EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_RECOVERY)); #else return 0; #endif }
/* There are actually two recovery switches. One is the magic keyboard chord, * the other is driven by Servo. */ int get_recovery_mode_switch(void) { u8 ec_switches = inb(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_SWITCHES); u32 ec_events; /* If a switch is set, we don't need to look at events. */ if (ec_switches & (EC_SWITCH_KEYBOARD_RECOVERY | EC_SWITCH_DEDICATED_RECOVERY)) return 1; /* Else check if the EC has posted the keyboard recovery event. */ ec_events = google_chromeec_get_events_b(); return !!(ec_events & EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_RECOVERY)); }
int cros_ec_get_host_events(struct cros_ec_dev *dev, uint32_t *events_ptr) { struct ec_response_host_event_mask *resp; /* * Use the B copy of the event flags, because the main copy is already * used by ACPI/SMI. */ if (ec_command_inptr(dev, EC_CMD_HOST_EVENT_GET_B, 0, NULL, 0, (uint8_t **)&resp, sizeof(*resp)) < (int)sizeof(*resp)) return -1; if (resp->mask & EC_HOST_EVENT_MASK(EC_HOST_EVENT_INVALID)) return -1; *events_ptr = resp->mask; return 0; }
void google_chromeec_log_events(u32 mask) { #if CONFIG_ELOG u8 event; u32 wake_mask; /* Set wake mask so events will be read from ACPI interface */ wake_mask = google_chromeec_get_wake_mask(); google_chromeec_set_wake_mask(mask); while ((event = google_chromeec_get_event()) != 0) { if (EC_HOST_EVENT_MASK(event) & mask) elog_add_event_byte(ELOG_TYPE_EC_EVENT, event); } google_chromeec_set_wake_mask(wake_mask); #endif }
static int cros_ec_rtc_event(struct notifier_block *nb, unsigned long queued_during_suspend, void *_notify) { struct cros_ec_rtc *cros_ec_rtc; struct rtc_device *rtc; struct cros_ec_device *cros_ec; u32 host_event; cros_ec_rtc = container_of(nb, struct cros_ec_rtc, notifier); rtc = cros_ec_rtc->rtc; cros_ec = cros_ec_rtc->cros_ec; host_event = cros_ec_get_host_event(cros_ec); if (host_event & EC_HOST_EVENT_MASK(EC_HOST_EVENT_RTC)) { rtc_update_irq(rtc, 1, RTC_IRQF | RTC_AF); return NOTIFY_OK; } else { return NOTIFY_DONE; } }
int get_recovery_mode_switch(void) { #if IS_ENABLED(CONFIG_EC_GOOGLE_CHROMEEC) u8 ec_switches; u32 ec_events; mec_io_bytes(0, EC_LPC_ADDR_MEMMAP + EC_MEMMAP_SWITCHES, 1, &ec_switches, NULL); /* If a switch is set, we don't need to look at events. */ if (ec_switches & (EC_SWITCH_DEDICATED_RECOVERY)) return 1; /* Else check if the EC has posted the keyboard recovery event. */ ec_events = google_chromeec_get_events_b(); return !!(ec_events & EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_RECOVERY)); #else return 0; #endif }
int cros_ec_set_lid_shutdown_mask(struct udevice *dev, int enable) { u32 mask; int ret; ret = cros_ec_get_event_mask(dev, EC_CMD_HOST_EVENT_GET_SMI_MASK, &mask); if (ret < 0) return ret; /* Set lid close event state in the EC SMI event mask */ if (enable) mask |= EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_CLOSED); else mask &= ~EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_CLOSED); ret = cros_ec_set_event_mask(dev, EC_CMD_HOST_EVENT_SET_SMI_MASK, mask); if (ret < 0) return ret; printf("EC: %sabled lid close event\n", enable ? "en" : "dis"); return 0; }
/* Find the last port80 code from the previous boot */ static u16 google_chromeec_get_port80_last_boot(void) { struct ec_response_port80_last_boot rsp; struct chromeec_command cmd = { .cmd_code = EC_CMD_PORT80_LAST_BOOT, .cmd_data_out = &rsp, .cmd_size_out = sizeof(rsp), }; /* Get last port80 code */ if (google_chromeec_command(&cmd) == 0) return rsp.code; return 0; } #endif void google_chromeec_log_events(u32 mask) { #if CONFIG_ELOG u8 event; u16 code; /* Find the last port80 code */ code = google_chromeec_get_port80_last_boot(); /* Log the last post code only if it is abornmal */ if (code > 0 && code != POST_OS_BOOT && code != POST_OS_RESUME) printk(BIOS_DEBUG, "Chrome EC: Last POST code was 0x%02x\n", code); while ((event = google_chromeec_get_event()) != 0) { if (EC_HOST_EVENT_MASK(event) & mask) elog_add_event_byte(ELOG_TYPE_EC_EVENT, event); } #endif }
/** * Process an emulated EC command * * @param ec Current emulated EC state * @param req_hdr Pointer to request header * @param req_data Pointer to body of request * @param resp_hdr Pointer to place to put response header * @param resp_data Pointer to place to put response data, if any * @return length of response data, or 0 for no response data, or -1 on error */ static int process_cmd(struct ec_state *ec, struct ec_host_request *req_hdr, const void *req_data, struct ec_host_response *resp_hdr, void *resp_data) { int len; /* TODO([email protected]): Check checksums */ debug("EC command %#0x\n", req_hdr->command); switch (req_hdr->command) { case EC_CMD_HELLO: { const struct ec_params_hello *req = req_data; struct ec_response_hello *resp = resp_data; resp->out_data = req->in_data + 0x01020304; len = sizeof(*resp); break; } case EC_CMD_GET_VERSION: { struct ec_response_get_version *resp = resp_data; strcpy(resp->version_string_ro, "sandbox_ro"); strcpy(resp->version_string_rw, "sandbox_rw"); resp->current_image = ec->current_image; debug("Current image %d\n", resp->current_image); len = sizeof(*resp); break; } case EC_CMD_VBNV_CONTEXT: { const struct ec_params_vbnvcontext *req = req_data; struct ec_response_vbnvcontext *resp = resp_data; switch (req->op) { case EC_VBNV_CONTEXT_OP_READ: memcpy(resp->block, ec->vbnv_context, sizeof(resp->block)); len = sizeof(*resp); break; case EC_VBNV_CONTEXT_OP_WRITE: memcpy(ec->vbnv_context, resp->block, sizeof(resp->block)); len = 0; break; default: printf(" ** Unknown vbnv_context command %#02x\n", req->op); return -1; } break; } case EC_CMD_REBOOT_EC: { const struct ec_params_reboot_ec *req = req_data; printf("Request reboot type %d\n", req->cmd); switch (req->cmd) { case EC_REBOOT_DISABLE_JUMP: len = 0; break; case EC_REBOOT_JUMP_RW: ec->current_image = EC_IMAGE_RW; len = 0; break; default: puts(" ** Unknown type"); return -1; } break; } case EC_CMD_HOST_EVENT_GET_B: { struct ec_response_host_event_mask *resp = resp_data; resp->mask = 0; if (ec->recovery_req) { resp->mask |= EC_HOST_EVENT_MASK( EC_HOST_EVENT_KEYBOARD_RECOVERY); } len = sizeof(*resp); break; } case EC_CMD_VBOOT_HASH: { const struct ec_params_vboot_hash *req = req_data; struct ec_response_vboot_hash *resp = resp_data; struct fmap_entry *entry; int ret, size; entry = &ec->ec_config.region[EC_FLASH_REGION_RW]; switch (req->cmd) { case EC_VBOOT_HASH_RECALC: case EC_VBOOT_HASH_GET: size = SHA256_SUM_LEN; len = get_image_used(ec, entry); ret = hash_block("sha256", ec->flash_data + entry->offset, len, resp->hash_digest, &size); if (ret) { printf(" ** hash_block() failed\n"); return -1; } resp->status = EC_VBOOT_HASH_STATUS_DONE; resp->hash_type = EC_VBOOT_HASH_TYPE_SHA256; resp->digest_size = size; resp->reserved0 = 0; resp->offset = entry->offset; resp->size = len; len = sizeof(*resp); break; default: printf(" ** EC_CMD_VBOOT_HASH: Unknown command %d\n", req->cmd); return -1; } break; } case EC_CMD_FLASH_PROTECT: { const struct ec_params_flash_protect *req = req_data; struct ec_response_flash_protect *resp = resp_data; uint32_t expect = EC_FLASH_PROTECT_ALL_NOW | EC_FLASH_PROTECT_ALL_AT_BOOT; printf("mask=%#x, flags=%#x\n", req->mask, req->flags); if (req->flags == expect || req->flags == 0) { resp->flags = req->flags ? EC_FLASH_PROTECT_ALL_NOW : 0; resp->valid_flags = EC_FLASH_PROTECT_ALL_NOW; resp->writable_flags = 0; len = sizeof(*resp); } else { puts(" ** unexpected flash protect request\n"); return -1; } break; } case EC_CMD_FLASH_REGION_INFO: { const struct ec_params_flash_region_info *req = req_data; struct ec_response_flash_region_info *resp = resp_data; struct fmap_entry *entry; switch (req->region) { case EC_FLASH_REGION_RO: case EC_FLASH_REGION_RW: case EC_FLASH_REGION_WP_RO: entry = &ec->ec_config.region[req->region]; resp->offset = entry->offset; resp->size = entry->length; len = sizeof(*resp); printf("EC flash region %d: offset=%#x, size=%#x\n", req->region, resp->offset, resp->size); break; default: printf("** Unknown flash region %d\n", req->region); return -1; } break; } case EC_CMD_FLASH_ERASE: { const struct ec_params_flash_erase *req = req_data; memset(ec->flash_data + req->offset, ec->ec_config.flash_erase_value, req->size); len = 0; break; } case EC_CMD_FLASH_WRITE: { const struct ec_params_flash_write *req = req_data; memcpy(ec->flash_data + req->offset, req + 1, req->size); len = 0; break; } case EC_CMD_MKBP_STATE: len = cros_ec_keyscan(ec, resp_data); break; case EC_CMD_ENTERING_MODE: len = 0; break; default: printf(" ** Unknown EC command %#02x\n", req_hdr->command); return -1; } return len; }
/* Host Event helpers */ static int ev_is_set(int event) { return host_get_events() & EC_HOST_EVENT_MASK(event); }
int get_recovery_mode_switch(void) { /* Check if the EC has posted the keyboard recovery event. */ return !!(google_chromeec_get_events_b() & EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_RECOVERY)); }
static VbError_t twostop_init_vboot_library(firmware_storage_t *file, void *gbb, uint32_t gbb_offset, size_t gbb_size, crossystem_data_t *cdata, VbCommonParams *cparams) { VbError_t err; VbInitParams iparams; int virtual_dev_switch = cros_fdtdec_config_has_prop(gd->fdt_blob, "virtual-dev-switch"); #ifdef CONFIG_MKBP struct mkbp_dev *mdev = board_get_mkbp_dev(); #endif memset(&iparams, 0, sizeof(iparams)); iparams.flags = check_ro_normal_support(); #ifdef CONFIG_MKBP if (mdev) { uint32_t ec_events = 0; const uint32_t kb_rec_mask = EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_RECOVERY); /* Read keyboard recovery flag from EC, then clear it */ if (mkbp_get_host_events(mdev, &ec_events)) { /* * TODO: what can we do if that fails? Request * recovery? We don't simply want to fail, because * that'll prevent us from going into recovery mode. * We don't want to go into recovery mode * automatically, because that'll break snow. */ VBDEBUG("VbInit: unable to read EC events\n"); ec_events = 0; } if (ec_events & kb_rec_mask) { iparams.flags |= VB_INIT_FLAG_REC_BUTTON_PRESSED; if (mkbp_clear_host_events(mdev, kb_rec_mask)) VBDEBUG("VbInit: unable to clear " "EC KB recovery event\n"); } } #endif if (cdata->boot_write_protect_switch) iparams.flags |= VB_INIT_FLAG_WP_ENABLED; if (cdata->boot_recovery_switch) iparams.flags |= VB_INIT_FLAG_REC_BUTTON_PRESSED; if (cdata->boot_developer_switch) iparams.flags |= VB_INIT_FLAG_DEV_SWITCH_ON; if (cdata->boot_oprom_loaded) iparams.flags |= VB_INIT_FLAG_OPROM_LOADED; if (cdata->oprom_matters) iparams.flags |= VB_INIT_FLAG_OPROM_MATTERS; if (virtual_dev_switch) iparams.flags |= VB_INIT_FLAG_VIRTUAL_DEV_SWITCH; if (cros_fdtdec_config_has_prop(gd->fdt_blob, "ec-software-sync")) iparams.flags |= VB_INIT_FLAG_EC_SOFTWARE_SYNC; if (cros_fdtdec_config_has_prop(gd->fdt_blob, "ec-slow-update")) iparams.flags |= VB_INIT_FLAG_EC_SLOW_UPDATE; if (flash_sw_wp_is_enabled(file)) iparams.flags |= VB_INIT_FLAG_SW_WP_ENABLED; VBDEBUG("iparams.flags: %08x\n", iparams.flags); if ((err = VbInit(cparams, &iparams))) { VBDEBUG("VbInit: %u\n", err); /* * If vboot wants EC to reboot to RO, make request now, * because there isn't a clear path to pass this request * through to do_vboot_twostop(). */ if (err == VBERROR_EC_REBOOT_TO_RO_REQUIRED) request_ec_reboot_to_ro(); return err; } #ifdef CONFIG_VIDEO_TEGRA tegra_lcd_check_next_stage(gd->fdt_blob, 0); #endif #ifdef CONFIG_EXYNOS_DISPLAYPORT exynos_lcd_check_next_stage(gd->fdt_blob, 0); #endif VBDEBUG("iparams.out_flags: %08x\n", iparams.out_flags); if (virtual_dev_switch) { cdata->boot_developer_switch = (iparams.out_flags & VB_INIT_OUT_ENABLE_DEVELOPER) ? 1 : 0; VBDEBUG("cdata->boot_developer_switch=%d\n", cdata->boot_developer_switch); } if (iparams.out_flags & VB_INIT_OUT_CLEAR_RAM) wipe_unused_memory(cdata, cparams); /* Load required information of GBB */ if (iparams.out_flags & VB_INIT_OUT_ENABLE_DISPLAY) { if (gbb_read_bmp_block(gbb, file, gbb_offset, gbb_size)) return VBERROR_INVALID_GBB; have_read_gbb_bmp_block = 1; } if (cdata->boot_developer_switch || iparams.out_flags & VB_INIT_OUT_ENABLE_RECOVERY) { if (gbb_read_recovery_key(gbb, file, gbb_offset, gbb_size)) return VBERROR_INVALID_GBB; } return VBERROR_SUCCESS; }
static void ev_clear(int event) { host_clear_events(EC_HOST_EVENT_MASK(event)); }
int clear_recovery_mode_switch(void) { /* Clear keyboard recovery event. */ return google_chromeec_clear_events_b( EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_RECOVERY)); }