void host_command_task(void) { host_command_init(); while (1) { /* Wait for the next command event */ int evt = task_wait_event(-1); /* Process it */ if ((evt & TASK_EVENT_CMD_PENDING) && pending_args) { pending_args->result = host_command_process(pending_args); host_send_response(pending_args); } } }
void host_command_received(struct host_cmd_handler_args *args) { /* * TODO(crosbug.com/p/23806): should warn if we already think we're in * a command. */ /* * If this is the reboot command, reboot immediately. This gives the * host processor a way to unwedge the EC even if it's busy with some * other command. */ if (args->command == EC_CMD_REBOOT) { system_reset(SYSTEM_RESET_HARD); /* Reset should never return; if it does, post an error */ args->result = EC_RES_ERROR; } #ifdef CONFIG_AP_HANG_DETECT /* If hang detection is enabled, check stop on host command */ hang_detect_stop_on_host_command(); #endif if (args->result) { ; /* driver has signalled an error, respond now */ #ifdef CONFIG_HOST_COMMAND_STATUS } else if (args->command == EC_CMD_GET_COMMS_STATUS) { args->result = host_command_process(args); #endif } else { /* Save the command */ pending_args = args; /* Wake up the task to handle the command */ task_set_event(TASK_ID_HOSTCMD, TASK_EVENT_CMD_PENDING, 0); return; } /* * TODO (crosbug.com/p/29315): This is typically running in interrupt * context, so it woud be better not to send the response here, and to * let the host command task send the response. */ /* Send the response now */ host_send_response(args); }
int host_command_reboot(struct host_cmd_handler_args *args) { struct ec_params_reboot_ec p; /* * Ensure reboot parameters don't get clobbered when the response * is sent in case data argument points to the host tx/rx buffer. */ memcpy(&p, args->params, sizeof(p)); if (p.cmd == EC_REBOOT_CANCEL) { /* Cancel pending reboot */ reboot_at_shutdown = EC_REBOOT_CANCEL; return EC_RES_SUCCESS; } else if (p.flags & EC_REBOOT_FLAG_ON_AP_SHUTDOWN) { /* Store request for processing at chipset shutdown */ reboot_at_shutdown = p.cmd; return EC_RES_SUCCESS; } #ifdef HAS_TASK_HOSTCMD if (p.cmd == EC_REBOOT_JUMP_RO || p.cmd == EC_REBOOT_JUMP_RW || p.cmd == EC_REBOOT_COLD || p.cmd == EC_REBOOT_HIBERNATE) { /* Clean busy bits on host for commands that won't return */ args->result = EC_RES_SUCCESS; host_send_response(args); } #endif CPRINTS("Executing host reboot command %d", p.cmd); switch (handle_pending_reboot(p.cmd)) { case EC_SUCCESS: return EC_RES_SUCCESS; case EC_ERROR_INVAL: return EC_RES_INVALID_PARAM; case EC_ERROR_ACCESS_DENIED: return EC_RES_ACCESS_DENIED; default: return EC_RES_ERROR; } }
static int flash_command_erase(struct host_cmd_handler_args *args) { const struct ec_params_flash_erase *p = args->params; if (flash_get_protect() & EC_FLASH_PROTECT_ALL_NOW) return EC_RES_ACCESS_DENIED; if (system_unsafe_to_overwrite(p->offset, p->size)) return EC_RES_ACCESS_DENIED; /* Indicate that we might be a while */ #if defined(HAS_TASK_HOSTCMD) && defined(CONFIG_HOST_COMMAND_STATUS) args->result = EC_RES_IN_PROGRESS; host_send_response(args); #endif if (flash_erase(p->offset, p->size)) return EC_RES_ERROR; return EC_RES_SUCCESS; }