diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/fastboot/Kconfig | 7 | ||||
-rw-r--r-- | drivers/fastboot/fb_command.c | 52 | ||||
-rw-r--r-- | drivers/fastboot/fb_getvar.c | 77 | ||||
-rw-r--r-- | drivers/usb/gadget/f_fastboot.c | 29 |
4 files changed, 152 insertions, 13 deletions
diff --git a/drivers/fastboot/Kconfig b/drivers/fastboot/Kconfig index 11fc0fe1c80..5e5855a76c2 100644 --- a/drivers/fastboot/Kconfig +++ b/drivers/fastboot/Kconfig @@ -242,6 +242,13 @@ config FASTBOOT_OEM_RUN this feature if you are using verified boot, as it will allow an attacker to bypass any restrictions you have in place. +config FASTBOOT_CMD_OEM_CONSOLE + bool "Enable the 'oem console' command" + depends on CONSOLE_RECORD + help + Add support for the "oem console" command to input and read console + record buffer. + endif # FASTBOOT endmenu diff --git a/drivers/fastboot/fb_command.c b/drivers/fastboot/fb_command.c index 5fcadcdf503..f95f4e4ae15 100644 --- a/drivers/fastboot/fb_command.c +++ b/drivers/fastboot/fb_command.c @@ -5,6 +5,7 @@ #include <common.h> #include <command.h> +#include <console.h> #include <env.h> #include <fastboot.h> #include <fastboot-internal.h> @@ -40,6 +41,7 @@ static void reboot_recovery(char *, char *); static void oem_format(char *, char *); static void oem_partconf(char *, char *); static void oem_bootbus(char *, char *); +static void oem_console(char *, char *); static void run_ucmd(char *, char *); static void run_acmd(char *, char *); @@ -107,6 +109,10 @@ static const struct { .command = "oem run", .dispatch = CONFIG_IS_ENABLED(FASTBOOT_OEM_RUN, (run_ucmd), (NULL)) }, + [FASTBOOT_COMMAND_OEM_CONSOLE] = { + .command = "oem console", + .dispatch = CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_CONSOLE, (oem_console), (NULL)) + }, [FASTBOOT_COMMAND_UCMD] = { .command = "UCmd", .dispatch = CONFIG_IS_ENABLED(FASTBOOT_UUU_SUPPORT, (run_ucmd), (NULL)) @@ -152,6 +158,35 @@ int fastboot_handle_command(char *cmd_string, char *response) return -1; } +void fastboot_multiresponse(int cmd, char *response) +{ + switch (cmd) { + case FASTBOOT_COMMAND_GETVAR: + fastboot_getvar_all(response); + break; + case FASTBOOT_COMMAND_OEM_CONSOLE: + if (CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_CONSOLE)) { + char buf[FASTBOOT_RESPONSE_LEN] = { 0 }; + + if (console_record_isempty()) { + console_record_reset(); + fastboot_okay(NULL, response); + } else { + int ret = console_record_readline(buf, sizeof(buf) - 5); + + if (ret < 0) + fastboot_fail("Error reading console", response); + else + fastboot_response("INFO", response, "%s", buf); + } + break; + } + default: + fastboot_fail("Unknown multiresponse command", response); + break; + } +} + /** * okay() - Send bare OKAY response * @@ -490,3 +525,20 @@ static void __maybe_unused oem_bootbus(char *cmd_parameter, char *response) else fastboot_okay(NULL, response); } + +/** + * oem_console() - Execute the OEM console command + * + * @cmd_parameter: Pointer to command parameter + * @response: Pointer to fastboot response buffer + */ +static void __maybe_unused oem_console(char *cmd_parameter, char *response) +{ + if (cmd_parameter) + console_in_puts(cmd_parameter); + + if (console_record_isempty()) + fastboot_fail("Empty console", response); + else + fastboot_response(FASTBOOT_MULTIRESPONSE_START, response, NULL); +} diff --git a/drivers/fastboot/fb_getvar.c b/drivers/fastboot/fb_getvar.c index 8cb8ffa2c6c..f65519c57b4 100644 --- a/drivers/fastboot/fb_getvar.c +++ b/drivers/fastboot/fb_getvar.c @@ -29,53 +29,67 @@ static void getvar_is_userspace(char *var_parameter, char *response); static const struct { const char *variable; + bool list; void (*dispatch)(char *var_parameter, char *response); } getvar_dispatch[] = { { .variable = "version", - .dispatch = getvar_version + .dispatch = getvar_version, + .list = true, }, { .variable = "version-bootloader", - .dispatch = getvar_version_bootloader + .dispatch = getvar_version_bootloader, + .list = true }, { .variable = "downloadsize", - .dispatch = getvar_downloadsize + .dispatch = getvar_downloadsize, + .list = true }, { .variable = "max-download-size", - .dispatch = getvar_downloadsize + .dispatch = getvar_downloadsize, + .list = true }, { .variable = "serialno", - .dispatch = getvar_serialno + .dispatch = getvar_serialno, + .list = true }, { .variable = "version-baseband", - .dispatch = getvar_version_baseband + .dispatch = getvar_version_baseband, + .list = true }, { .variable = "product", - .dispatch = getvar_product + .dispatch = getvar_product, + .list = true }, { .variable = "platform", - .dispatch = getvar_platform + .dispatch = getvar_platform, + .list = true }, { .variable = "current-slot", - .dispatch = getvar_current_slot + .dispatch = getvar_current_slot, + .list = true #if IS_ENABLED(CONFIG_FASTBOOT_FLASH) }, { .variable = "has-slot", - .dispatch = getvar_has_slot + .dispatch = getvar_has_slot, + .list = false #endif #if IS_ENABLED(CONFIG_FASTBOOT_FLASH_MMC) }, { .variable = "partition-type", - .dispatch = getvar_partition_type + .dispatch = getvar_partition_type, + .list = false #endif #if IS_ENABLED(CONFIG_FASTBOOT_FLASH) }, { .variable = "partition-size", - .dispatch = getvar_partition_size + .dispatch = getvar_partition_size, + .list = false #endif }, { .variable = "is-userspace", - .dispatch = getvar_is_userspace + .dispatch = getvar_is_userspace, + .list = true } }; @@ -237,6 +251,40 @@ static void getvar_is_userspace(char *var_parameter, char *response) fastboot_okay("no", response); } +static int current_all_dispatch; +void fastboot_getvar_all(char *response) +{ + /* + * Find a dispatch getvar that can be listed and send + * it as INFO until we reach the end. + */ + while (current_all_dispatch < ARRAY_SIZE(getvar_dispatch)) { + if (!getvar_dispatch[current_all_dispatch].list) { + current_all_dispatch++; + continue; + } + + char envstr[FASTBOOT_RESPONSE_LEN] = { 0 }; + + getvar_dispatch[current_all_dispatch].dispatch(NULL, envstr); + + char *envstr_start = envstr; + + if (!strncmp("OKAY", envstr, 4) || !strncmp("FAIL", envstr, 4)) + envstr_start += 4; + + fastboot_response("INFO", response, "%s: %s", + getvar_dispatch[current_all_dispatch].variable, + envstr_start); + + current_all_dispatch++; + return; + } + + fastboot_response("OKAY", response, NULL); + current_all_dispatch = 0; +} + /** * fastboot_getvar() - Writes variable indicated by cmd_parameter to response. * @@ -254,6 +302,9 @@ void fastboot_getvar(char *cmd_parameter, char *response) { if (!cmd_parameter) { fastboot_fail("missing var", response); + } else if (!strncmp("all", cmd_parameter, 3) && strlen(cmd_parameter) == 3) { + current_all_dispatch = 0; + fastboot_response(FASTBOOT_MULTIRESPONSE_START, response, NULL); } else { #define FASTBOOT_ENV_PREFIX "fastboot." int i; diff --git a/drivers/usb/gadget/f_fastboot.c b/drivers/usb/gadget/f_fastboot.c index 9f322c95508..09e740cc962 100644 --- a/drivers/usb/gadget/f_fastboot.c +++ b/drivers/usb/gadget/f_fastboot.c @@ -497,6 +497,25 @@ static void do_bootm_on_complete(struct usb_ep *ep, struct usb_request *req) do_exit_on_complete(ep, req); } +static int multiresponse_cmd = -1; +static void multiresponse_on_complete(struct usb_ep *ep, struct usb_request *req) +{ + char response[FASTBOOT_RESPONSE_LEN] = {0}; + + if (multiresponse_cmd == -1) + return; + + /* Call handler to obtain next response */ + fastboot_multiresponse(multiresponse_cmd, response); + fastboot_tx_write_str(response); + + /* If response is final OKAY/FAIL response disconnect this handler and unset cmd */ + if (!strncmp("OKAY", response, 4) || !strncmp("FAIL", response, 4)) { + multiresponse_cmd = -1; + fastboot_func->in_req->complete = fastboot_complete; + } +} + static void do_acmd_complete(struct usb_ep *ep, struct usb_request *req) { /* When usb dequeue complete will be called @@ -524,6 +543,16 @@ static void rx_handler_command(struct usb_ep *ep, struct usb_request *req) fastboot_fail("buffer overflow", response); } + if (!strncmp(FASTBOOT_MULTIRESPONSE_START, response, 4)) { + multiresponse_cmd = cmd; + fastboot_multiresponse(multiresponse_cmd, response); + + /* Only add complete callback if first is not a final OKAY/FAIL response */ + if (strncmp("OKAY", response, 4) && strncmp("FAIL", response, 4)) { + fastboot_func->in_req->complete = multiresponse_on_complete; + } + } + if (!strncmp("DATA", response, 4)) { req->complete = rx_handler_dl_image; req->length = rx_bytes_expected(ep); |