1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (C) 2016 The Android Open Source Project 4 */ 5 6 #include <common.h> 7 #include <fastboot.h> 8 #include <net.h> 9 #include <net/fastboot.h> 10 11 /* Fastboot port # defined in spec */ 12 #define WELL_KNOWN_PORT 5554 13 14 enum { 15 FASTBOOT_ERROR = 0, 16 FASTBOOT_QUERY = 1, 17 FASTBOOT_INIT = 2, 18 FASTBOOT_FASTBOOT = 3, 19 }; 20 21 struct __packed fastboot_header { 22 uchar id; 23 uchar flags; 24 unsigned short seq; 25 }; 26 27 #define PACKET_SIZE 1024 28 #define DATA_SIZE (PACKET_SIZE - sizeof(struct fastboot_header)) 29 30 /* Sequence number sent for every packet */ 31 static unsigned short sequence_number = 1; 32 static const unsigned short packet_size = PACKET_SIZE; 33 static const unsigned short udp_version = 1; 34 35 /* Keep track of last packet for resubmission */ 36 static uchar last_packet[PACKET_SIZE]; 37 static unsigned int last_packet_len; 38 39 static struct in_addr fastboot_remote_ip; 40 /* The UDP port at their end */ 41 static int fastboot_remote_port; 42 /* The UDP port at our end */ 43 static int fastboot_our_port; 44 45 static void boot_downloaded_image(void); 46 47 #if CONFIG_IS_ENABLED(FASTBOOT_FLASH) 48 /** 49 * fastboot_udp_send_info() - Send an INFO packet during long commands. 50 * 51 * @msg: String describing the reason for waiting 52 */ 53 static void fastboot_udp_send_info(const char *msg) 54 { 55 uchar *packet; 56 uchar *packet_base; 57 int len = 0; 58 char response[FASTBOOT_RESPONSE_LEN] = {0}; 59 60 struct fastboot_header response_header = { 61 .id = FASTBOOT_FASTBOOT, 62 .flags = 0, 63 .seq = htons(sequence_number) 64 }; 65 ++sequence_number; 66 packet = net_tx_packet + net_eth_hdr_size() + IP_UDP_HDR_SIZE; 67 packet_base = packet; 68 69 /* Write headers */ 70 memcpy(packet, &response_header, sizeof(response_header)); 71 packet += sizeof(response_header); 72 /* Write response */ 73 fastboot_response("INFO", response, "%s", msg); 74 memcpy(packet, response, strlen(response)); 75 packet += strlen(response); 76 77 len = packet - packet_base; 78 79 /* Save packet for retransmitting */ 80 last_packet_len = len; 81 memcpy(last_packet, packet_base, last_packet_len); 82 83 net_send_udp_packet(net_server_ethaddr, fastboot_remote_ip, 84 fastboot_remote_port, fastboot_our_port, len); 85 } 86 87 /** 88 * fastboot_timed_send_info() - Send INFO packet every 30 seconds 89 * 90 * @msg: String describing the reason for waiting 91 * 92 * Send an INFO packet during long commands based on timer. An INFO packet 93 * is sent if the time is 30 seconds after start. Else, noop. 94 */ 95 static void fastboot_timed_send_info(const char *msg) 96 { 97 static ulong start; 98 99 /* Initialize timer */ 100 if (start == 0) 101 start = get_timer(0); 102 ulong time = get_timer(start); 103 /* Send INFO packet to host every 30 seconds */ 104 if (time >= 30000) { 105 start = get_timer(0); 106 fastboot_udp_send_info(msg); 107 } 108 } 109 #endif 110 111 /** 112 * fastboot_send() - Sends a packet in response to received fastboot packet 113 * 114 * @header: Header for response packet 115 * @fastboot_data: Pointer to received fastboot data 116 * @fastboot_data_len: Length of received fastboot data 117 * @retransmit: Nonzero if sending last sent packet 118 */ 119 static void fastboot_send(struct fastboot_header header, char *fastboot_data, 120 unsigned int fastboot_data_len, uchar retransmit) 121 { 122 uchar *packet; 123 uchar *packet_base; 124 int len = 0; 125 const char *error_msg = "An error occurred."; 126 short tmp; 127 struct fastboot_header response_header = header; 128 static char command[FASTBOOT_COMMAND_LEN]; 129 static int cmd = -1; 130 static bool pending_command; 131 char response[FASTBOOT_RESPONSE_LEN] = {0}; 132 133 /* 134 * We will always be sending some sort of packet, so 135 * cobble together the packet headers now. 136 */ 137 packet = net_tx_packet + net_eth_hdr_size() + IP_UDP_HDR_SIZE; 138 packet_base = packet; 139 140 /* Resend last packet */ 141 if (retransmit) { 142 memcpy(packet, last_packet, last_packet_len); 143 net_send_udp_packet(net_server_ethaddr, fastboot_remote_ip, 144 fastboot_remote_port, fastboot_our_port, 145 last_packet_len); 146 return; 147 } 148 149 response_header.seq = htons(response_header.seq); 150 memcpy(packet, &response_header, sizeof(response_header)); 151 packet += sizeof(response_header); 152 153 switch (header.id) { 154 case FASTBOOT_QUERY: 155 tmp = htons(sequence_number); 156 memcpy(packet, &tmp, sizeof(tmp)); 157 packet += sizeof(tmp); 158 break; 159 case FASTBOOT_INIT: 160 tmp = htons(udp_version); 161 memcpy(packet, &tmp, sizeof(tmp)); 162 packet += sizeof(tmp); 163 tmp = htons(packet_size); 164 memcpy(packet, &tmp, sizeof(tmp)); 165 packet += sizeof(tmp); 166 break; 167 case FASTBOOT_ERROR: 168 memcpy(packet, error_msg, strlen(error_msg)); 169 packet += strlen(error_msg); 170 break; 171 case FASTBOOT_FASTBOOT: 172 if (cmd == FASTBOOT_COMMAND_DOWNLOAD) { 173 if (!fastboot_data_len && !fastboot_data_remaining()) { 174 fastboot_data_complete(response); 175 } else { 176 fastboot_data_download(fastboot_data, 177 fastboot_data_len, 178 response); 179 } 180 } else if (!pending_command) { 181 strlcpy(command, fastboot_data, 182 min((size_t)fastboot_data_len + 1, 183 sizeof(command))); 184 pending_command = true; 185 } else { 186 cmd = fastboot_handle_command(command, response); 187 pending_command = false; 188 } 189 /* 190 * Sent some INFO packets, need to update sequence number in 191 * header 192 */ 193 if (header.seq != sequence_number) { 194 response_header.seq = htons(sequence_number); 195 memcpy(packet_base, &response_header, 196 sizeof(response_header)); 197 } 198 /* Write response to packet */ 199 memcpy(packet, response, strlen(response)); 200 packet += strlen(response); 201 break; 202 default: 203 pr_err("ID %d not implemented.\n", header.id); 204 return; 205 } 206 207 len = packet - packet_base; 208 209 /* Save packet for retransmitting */ 210 last_packet_len = len; 211 memcpy(last_packet, packet_base, last_packet_len); 212 213 net_send_udp_packet(net_server_ethaddr, fastboot_remote_ip, 214 fastboot_remote_port, fastboot_our_port, len); 215 216 /* Continue boot process after sending response */ 217 if (!strncmp("OKAY", response, 4)) { 218 switch (cmd) { 219 case FASTBOOT_COMMAND_BOOT: 220 boot_downloaded_image(); 221 break; 222 223 case FASTBOOT_COMMAND_CONTINUE: 224 net_set_state(NETLOOP_SUCCESS); 225 break; 226 227 case FASTBOOT_COMMAND_REBOOT: 228 case FASTBOOT_COMMAND_REBOOT_BOOTLOADER: 229 do_reset(NULL, 0, 0, NULL); 230 break; 231 } 232 } 233 234 if (!strncmp("OKAY", response, 4) || !strncmp("FAIL", response, 4)) 235 cmd = -1; 236 } 237 238 /** 239 * boot_downloaded_image() - Boots into downloaded image. 240 */ 241 static void boot_downloaded_image(void) 242 { 243 fastboot_boot(); 244 net_set_state(NETLOOP_SUCCESS); 245 } 246 247 /** 248 * fastboot_handler() - Incoming UDP packet handler. 249 * 250 * @packet: Pointer to incoming UDP packet 251 * @dport: Destination UDP port 252 * @sip: Source IP address 253 * @sport: Source UDP port 254 * @len: Packet length 255 */ 256 static void fastboot_handler(uchar *packet, unsigned int dport, 257 struct in_addr sip, unsigned int sport, 258 unsigned int len) 259 { 260 struct fastboot_header header; 261 char fastboot_data[DATA_SIZE] = {0}; 262 unsigned int fastboot_data_len = 0; 263 264 if (dport != fastboot_our_port) 265 return; 266 267 fastboot_remote_ip = sip; 268 fastboot_remote_port = sport; 269 270 if (len < sizeof(struct fastboot_header) || len > PACKET_SIZE) 271 return; 272 memcpy(&header, packet, sizeof(header)); 273 header.flags = 0; 274 header.seq = ntohs(header.seq); 275 packet += sizeof(header); 276 len -= sizeof(header); 277 278 switch (header.id) { 279 case FASTBOOT_QUERY: 280 fastboot_send(header, fastboot_data, 0, 0); 281 break; 282 case FASTBOOT_INIT: 283 case FASTBOOT_FASTBOOT: 284 fastboot_data_len = len; 285 if (len > 0) 286 memcpy(fastboot_data, packet, len); 287 if (header.seq == sequence_number) { 288 fastboot_send(header, fastboot_data, 289 fastboot_data_len, 0); 290 sequence_number++; 291 } else if (header.seq == sequence_number - 1) { 292 /* Retransmit last sent packet */ 293 fastboot_send(header, fastboot_data, 294 fastboot_data_len, 1); 295 } 296 break; 297 default: 298 pr_err("ID %d not implemented.\n", header.id); 299 header.id = FASTBOOT_ERROR; 300 fastboot_send(header, fastboot_data, 0, 0); 301 break; 302 } 303 } 304 305 void fastboot_start_server(void) 306 { 307 printf("Using %s device\n", eth_get_name()); 308 printf("Listening for fastboot command on %pI4\n", &net_ip); 309 310 fastboot_our_port = WELL_KNOWN_PORT; 311 312 fastboot_set_progress_callback(fastboot_timed_send_info); 313 net_set_udp_handler(fastboot_handler); 314 315 /* zero out server ether in case the server ip has changed */ 316 memset(net_server_ethaddr, 0, 6); 317 } 318