1 // SPDX-License-Identifier: BSD-2-Clause
3 * Copyright (C) 2016 The Android Open Source Project
10 #include <net/fastboot_udp.h>
16 FASTBOOT_FASTBOOT
= 3,
19 struct __packed fastboot_header
{
25 #define PACKET_SIZE 1024
26 #define DATA_SIZE (PACKET_SIZE - sizeof(struct fastboot_header))
28 /* Sequence number sent for every packet */
29 static unsigned short sequence_number
= 1;
30 static const unsigned short packet_size
= PACKET_SIZE
;
31 static const unsigned short udp_version
= 1;
33 /* Keep track of last packet for resubmission */
34 static uchar last_packet
[PACKET_SIZE
];
35 static unsigned int last_packet_len
;
37 static struct in_addr fastboot_remote_ip
;
38 /* The UDP port at their end */
39 static int fastboot_remote_port
;
40 /* The UDP port at our end */
41 static int fastboot_our_port
;
44 * fastboot_udp_send_info() - Send an INFO packet during long commands.
46 * @msg: String describing the reason for waiting
48 static void fastboot_udp_send_info(const char *msg
)
53 char response
[FASTBOOT_RESPONSE_LEN
] = {0};
55 struct fastboot_header response_header
= {
56 .id
= FASTBOOT_FASTBOOT
,
58 .seq
= htons(sequence_number
)
61 packet
= net_tx_packet
+ net_eth_hdr_size() + IP_UDP_HDR_SIZE
;
65 memcpy(packet
, &response_header
, sizeof(response_header
));
66 packet
+= sizeof(response_header
);
68 fastboot_response("INFO", response
, "%s", msg
);
69 memcpy(packet
, response
, strlen(response
));
70 packet
+= strlen(response
);
72 len
= packet
- packet_base
;
74 /* Save packet for retransmitting */
75 last_packet_len
= len
;
76 memcpy(last_packet
, packet_base
, last_packet_len
);
78 net_send_udp_packet(net_server_ethaddr
, fastboot_remote_ip
,
79 fastboot_remote_port
, fastboot_our_port
, len
);
83 * fastboot_timed_send_info() - Send INFO packet every 30 seconds
85 * @msg: String describing the reason for waiting
87 * Send an INFO packet during long commands based on timer. An INFO packet
88 * is sent if the time is 30 seconds after start. Else, noop.
90 static void fastboot_timed_send_info(const char *msg
)
94 /* Initialize timer */
97 ulong time
= get_timer(start
);
98 /* Send INFO packet to host every 30 seconds */
100 start
= get_timer(0);
101 fastboot_udp_send_info(msg
);
106 * fastboot_send() - Sends a packet in response to received fastboot packet
108 * @header: Header for response packet
109 * @fastboot_data: Pointer to received fastboot data
110 * @fastboot_data_len: Length of received fastboot data
111 * @retransmit: Nonzero if sending last sent packet
113 static void fastboot_send(struct fastboot_header header
, char *fastboot_data
,
114 unsigned int fastboot_data_len
, uchar retransmit
)
119 const char *error_msg
= "An error occurred.";
121 struct fastboot_header response_header
= header
;
122 static char command
[FASTBOOT_COMMAND_LEN
];
124 static bool pending_command
;
125 char response
[FASTBOOT_RESPONSE_LEN
] = {0};
128 * We will always be sending some sort of packet, so
129 * cobble together the packet headers now.
131 packet
= net_tx_packet
+ net_eth_hdr_size() + IP_UDP_HDR_SIZE
;
132 packet_base
= packet
;
134 /* Resend last packet */
136 memcpy(packet
, last_packet
, last_packet_len
);
137 net_send_udp_packet(net_server_ethaddr
, fastboot_remote_ip
,
138 fastboot_remote_port
, fastboot_our_port
,
143 response_header
.seq
= htons(response_header
.seq
);
144 memcpy(packet
, &response_header
, sizeof(response_header
));
145 packet
+= sizeof(response_header
);
149 tmp
= htons(sequence_number
);
150 memcpy(packet
, &tmp
, sizeof(tmp
));
151 packet
+= sizeof(tmp
);
154 tmp
= htons(udp_version
);
155 memcpy(packet
, &tmp
, sizeof(tmp
));
156 packet
+= sizeof(tmp
);
157 tmp
= htons(packet_size
);
158 memcpy(packet
, &tmp
, sizeof(tmp
));
159 packet
+= sizeof(tmp
);
162 memcpy(packet
, error_msg
, strlen(error_msg
));
163 packet
+= strlen(error_msg
);
165 case FASTBOOT_FASTBOOT
:
166 if (cmd
== FASTBOOT_COMMAND_DOWNLOAD
) {
167 if (!fastboot_data_len
&& !fastboot_data_remaining()) {
168 fastboot_data_complete(response
);
170 fastboot_data_download(fastboot_data
,
174 } else if (!pending_command
) {
175 strlcpy(command
, fastboot_data
,
176 min((size_t)fastboot_data_len
+ 1,
178 pending_command
= true;
180 cmd
= fastboot_handle_command(command
, response
);
181 pending_command
= false;
184 * Sent some INFO packets, need to update sequence number in
187 if (header
.seq
!= sequence_number
) {
188 response_header
.seq
= htons(sequence_number
);
189 memcpy(packet_base
, &response_header
,
190 sizeof(response_header
));
192 /* Write response to packet */
193 memcpy(packet
, response
, strlen(response
));
194 packet
+= strlen(response
);
197 pr_err("ID %d not implemented.\n", header
.id
);
201 len
= packet
- packet_base
;
203 /* Save packet for retransmitting */
204 last_packet_len
= len
;
205 memcpy(last_packet
, packet_base
, last_packet_len
);
207 net_send_udp_packet(net_server_ethaddr
, fastboot_remote_ip
,
208 fastboot_remote_port
, fastboot_our_port
, len
);
210 fastboot_handle_boot(cmd
, strncmp("OKAY", response
, 4) == 0);
212 if (!strncmp("OKAY", response
, 4) || !strncmp("FAIL", response
, 4))
217 * fastboot_handler() - Incoming UDP packet handler.
219 * @packet: Pointer to incoming UDP packet
220 * @dport: Destination UDP port
221 * @sip: Source IP address
222 * @sport: Source UDP port
223 * @len: Packet length
225 static void fastboot_handler(uchar
*packet
, unsigned int dport
,
226 struct in_addr sip
, unsigned int sport
,
229 struct fastboot_header header
;
230 char fastboot_data
[DATA_SIZE
] = {0};
231 unsigned int fastboot_data_len
= 0;
233 if (dport
!= fastboot_our_port
)
236 fastboot_remote_ip
= sip
;
237 fastboot_remote_port
= sport
;
239 if (len
< sizeof(struct fastboot_header
) || len
> PACKET_SIZE
)
241 memcpy(&header
, packet
, sizeof(header
));
243 header
.seq
= ntohs(header
.seq
);
244 packet
+= sizeof(header
);
245 len
-= sizeof(header
);
249 fastboot_send(header
, fastboot_data
, 0, 0);
252 case FASTBOOT_FASTBOOT
:
253 fastboot_data_len
= len
;
255 memcpy(fastboot_data
, packet
, len
);
256 if (header
.seq
== sequence_number
) {
257 fastboot_send(header
, fastboot_data
,
258 fastboot_data_len
, 0);
260 } else if (header
.seq
== sequence_number
- 1) {
261 /* Retransmit last sent packet */
262 fastboot_send(header
, fastboot_data
,
263 fastboot_data_len
, 1);
267 pr_err("ID %d not implemented.\n", header
.id
);
268 header
.id
= FASTBOOT_ERROR
;
269 fastboot_send(header
, fastboot_data
, 0, 0);
274 void fastboot_udp_start_server(void)
276 printf("Using %s device\n", eth_get_name());
277 printf("Listening for fastboot command on %pI4\n", &net_ip
);
279 fastboot_our_port
= CONFIG_UDP_FUNCTION_FASTBOOT_PORT
;
281 if (IS_ENABLED(CONFIG_FASTBOOT_FLASH
))
282 fastboot_set_progress_callback(fastboot_timed_send_info
);
284 net_set_udp_handler(fastboot_handler
);
286 /* zero out server ether in case the server ip has changed */
287 memset(net_server_ethaddr
, 0, 6);