fastboot: multiresponse support

Currently u-boot fastboot can only send one message back to host,
so if there is a need to print more than one line messages must be
kept sending until all the required data is obtained. This behavior
can be adjusted using multiresponce ability (getting multiple lines
of response) proposed in this patch.

Signed-off-by: Ion Agorria <ion@agorria.com>
Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
Reviewed-by: Mattijs Korpershoek <mkorpershoek@baylibre.com>
Link: https://lore.kernel.org/r/20240105072212.6615-2-clamor95@gmail.com
Signed-off-by: Mattijs Korpershoek <mkorpershoek@baylibre.com>
This commit is contained in:
Ion Agorria 2024-01-05 09:22:06 +02:00 committed by Mattijs Korpershoek
parent c5e461fbf7
commit 85fcd69dc2
4 changed files with 80 additions and 6 deletions

View File

@ -5,6 +5,7 @@
#include <common.h>
#include <command.h>
#include <console.h>
#include <env.h>
#include <fastboot.h>
#include <fastboot-internal.h>
@ -152,6 +153,15 @@ int fastboot_handle_command(char *cmd_string, char *response)
return -1;
}
void fastboot_multiresponse(int cmd, char *response)
{
switch (cmd) {
default:
fastboot_fail("Unknown multiresponse command", response);
break;
}
}
/**
* okay() - Send bare OKAY response
*

View File

@ -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);

View File

@ -14,6 +14,16 @@
#define FASTBOOT_VERSION "0.4"
/*
* Signals u-boot fastboot code to send multiple responses by
* calling response generating function repeatedly until a OKAY/FAIL
* is generated as final response.
*
* This status code is only used internally to signal, must NOT
* be sent to host.
*/
#define FASTBOOT_MULTIRESPONSE_START ("MORE")
/* The 64 defined bytes plus \0 */
#define FASTBOOT_COMMAND_LEN (64 + 1)
#define FASTBOOT_RESPONSE_LEN (64 + 1)
@ -172,5 +182,13 @@ void fastboot_data_download(const void *fastboot_data,
*/
void fastboot_data_complete(char *response);
/**
* fastboot_handle_multiresponse() - Called for each response to send
*
* @cmd: Command id that requested multiresponse
* @response: Pointer to fastboot response buffer
*/
void fastboot_multiresponse(int cmd, char *response);
void fastboot_acmd_complete(void);
#endif /* _FASTBOOT_H_ */

View File

@ -42,16 +42,15 @@ static int fastboot_remote_port;
static int fastboot_our_port;
/**
* fastboot_udp_send_info() - Send an INFO packet during long commands.
* fastboot_udp_send_response() - Send an response into UDP
*
* @msg: String describing the reason for waiting
* @response: Response to send
*/
static void fastboot_udp_send_info(const char *msg)
static void fastboot_udp_send_response(const char *response)
{
uchar *packet;
uchar *packet_base;
int len = 0;
char response[FASTBOOT_RESPONSE_LEN] = {0};
struct fastboot_header response_header = {
.id = FASTBOOT_FASTBOOT,
@ -66,7 +65,6 @@ static void fastboot_udp_send_info(const char *msg)
memcpy(packet, &response_header, sizeof(response_header));
packet += sizeof(response_header);
/* Write response */
fastboot_response("INFO", response, "%s", msg);
memcpy(packet, response, strlen(response));
packet += strlen(response);
@ -91,6 +89,7 @@ static void fastboot_udp_send_info(const char *msg)
static void fastboot_timed_send_info(const char *msg)
{
static ulong start;
char response[FASTBOOT_RESPONSE_LEN] = {0};
/* Initialize timer */
if (start == 0)
@ -99,7 +98,8 @@ static void fastboot_timed_send_info(const char *msg)
/* Send INFO packet to host every 30 seconds */
if (time >= 30000) {
start = get_timer(0);
fastboot_udp_send_info(msg);
fastboot_response("INFO", response, "%s", msg);
fastboot_udp_send_response(response);
}
}
@ -180,6 +180,23 @@ static void fastboot_send(struct fastboot_header header, char *fastboot_data,
} else {
cmd = fastboot_handle_command(command, response);
pending_command = false;
if (!strncmp(FASTBOOT_MULTIRESPONSE_START, response, 4)) {
while (1) {
/* Call handler to obtain next response */
fastboot_multiresponse(cmd, response);
/*
* Send more responses or break to send
* final OKAY/FAIL response
*/
if (strncmp("OKAY", response, 4) &&
strncmp("FAIL", response, 4))
fastboot_udp_send_response(response);
else
break;
}
}
}
/*
* Sent some INFO packets, need to update sequence number in