"Das U-Boot" Source Tree
at master 574 lines 16 kB view raw
1// SPDX-License-Identifier: BSD-2-Clause 2/* 3 * Copyright (C) 2016 The Android Open Source Project 4 */ 5 6#include <command.h> 7#include <console.h> 8#include <env.h> 9#include <fastboot.h> 10#include <fastboot-internal.h> 11#include <fb_mmc.h> 12#include <fb_nand.h> 13#include <part.h> 14#include <stdlib.h> 15#include <vsprintf.h> 16#include <linux/printk.h> 17 18/** 19 * image_size - final fastboot image size 20 */ 21static u32 image_size; 22 23/** 24 * fastboot_bytes_received - number of bytes received in the current download 25 */ 26static u32 fastboot_bytes_received; 27 28/** 29 * fastboot_bytes_expected - number of bytes expected in the current download 30 */ 31static u32 fastboot_bytes_expected; 32 33static void okay(char *, char *); 34static void getvar(char *, char *); 35static void download(char *, char *); 36static void flash(char *, char *); 37static void erase(char *, char *); 38static void reboot_bootloader(char *, char *); 39static void reboot_fastbootd(char *, char *); 40static void reboot_recovery(char *, char *); 41static void oem_format(char *, char *); 42static void oem_partconf(char *, char *); 43static void oem_bootbus(char *, char *); 44static void oem_console(char *, char *); 45static void oem_board(char *, char *); 46static void run_ucmd(char *, char *); 47static void run_acmd(char *, char *); 48 49static const struct { 50 const char *command; 51 void (*dispatch)(char *cmd_parameter, char *response); 52} commands[FASTBOOT_COMMAND_COUNT] = { 53 [FASTBOOT_COMMAND_GETVAR] = { 54 .command = "getvar", 55 .dispatch = getvar 56 }, 57 [FASTBOOT_COMMAND_DOWNLOAD] = { 58 .command = "download", 59 .dispatch = download 60 }, 61 [FASTBOOT_COMMAND_FLASH] = { 62 .command = "flash", 63 .dispatch = CONFIG_IS_ENABLED(FASTBOOT_FLASH, (flash), (NULL)) 64 }, 65 [FASTBOOT_COMMAND_ERASE] = { 66 .command = "erase", 67 .dispatch = CONFIG_IS_ENABLED(FASTBOOT_FLASH, (erase), (NULL)) 68 }, 69 [FASTBOOT_COMMAND_BOOT] = { 70 .command = "boot", 71 .dispatch = okay 72 }, 73 [FASTBOOT_COMMAND_CONTINUE] = { 74 .command = "continue", 75 .dispatch = okay 76 }, 77 [FASTBOOT_COMMAND_REBOOT] = { 78 .command = "reboot", 79 .dispatch = okay 80 }, 81 [FASTBOOT_COMMAND_REBOOT_BOOTLOADER] = { 82 .command = "reboot-bootloader", 83 .dispatch = reboot_bootloader 84 }, 85 [FASTBOOT_COMMAND_REBOOT_FASTBOOTD] = { 86 .command = "reboot-fastboot", 87 .dispatch = reboot_fastbootd 88 }, 89 [FASTBOOT_COMMAND_REBOOT_RECOVERY] = { 90 .command = "reboot-recovery", 91 .dispatch = reboot_recovery 92 }, 93 [FASTBOOT_COMMAND_SET_ACTIVE] = { 94 .command = "set_active", 95 .dispatch = okay 96 }, 97 [FASTBOOT_COMMAND_OEM_FORMAT] = { 98 .command = "oem format", 99 .dispatch = CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_FORMAT, (oem_format), (NULL)) 100 }, 101 [FASTBOOT_COMMAND_OEM_PARTCONF] = { 102 .command = "oem partconf", 103 .dispatch = CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_PARTCONF, (oem_partconf), (NULL)) 104 }, 105 [FASTBOOT_COMMAND_OEM_BOOTBUS] = { 106 .command = "oem bootbus", 107 .dispatch = CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_BOOTBUS, (oem_bootbus), (NULL)) 108 }, 109 [FASTBOOT_COMMAND_OEM_RUN] = { 110 .command = "oem run", 111 .dispatch = CONFIG_IS_ENABLED(FASTBOOT_OEM_RUN, (run_ucmd), (NULL)) 112 }, 113 [FASTBOOT_COMMAND_OEM_CONSOLE] = { 114 .command = "oem console", 115 .dispatch = CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_CONSOLE, (oem_console), (NULL)) 116 }, 117 [FASTBOOT_COMMAND_OEM_BOARD] = { 118 .command = "oem board", 119 .dispatch = CONFIG_IS_ENABLED(FASTBOOT_OEM_BOARD, (oem_board), (NULL)) 120 }, 121 [FASTBOOT_COMMAND_UCMD] = { 122 .command = "UCmd", 123 .dispatch = CONFIG_IS_ENABLED(FASTBOOT_UUU_SUPPORT, (run_ucmd), (NULL)) 124 }, 125 [FASTBOOT_COMMAND_ACMD] = { 126 .command = "ACmd", 127 .dispatch = CONFIG_IS_ENABLED(FASTBOOT_UUU_SUPPORT, (run_acmd), (NULL)) 128 }, 129}; 130 131/** 132 * fastboot_handle_command - Handle fastboot command 133 * 134 * @cmd_string: Pointer to command string 135 * @response: Pointer to fastboot response buffer 136 * 137 * Return: Executed command, or -1 if not recognized 138 */ 139int fastboot_handle_command(char *cmd_string, char *response) 140{ 141 int i; 142 char *cmd_parameter; 143 144 cmd_parameter = cmd_string; 145 strsep(&cmd_parameter, ":"); 146 147 for (i = 0; i < FASTBOOT_COMMAND_COUNT; i++) { 148 if (!strcmp(commands[i].command, cmd_string)) { 149 if (commands[i].dispatch) { 150 commands[i].dispatch(cmd_parameter, 151 response); 152 return i; 153 } else { 154 pr_err("command %s not supported.\n", cmd_string); 155 fastboot_fail("Unsupported command", response); 156 return -1; 157 } 158 } 159 } 160 161 pr_err("command %s not recognized.\n", cmd_string); 162 fastboot_fail("unrecognized command", response); 163 return -1; 164} 165 166void fastboot_multiresponse(int cmd, char *response) 167{ 168 switch (cmd) { 169 case FASTBOOT_COMMAND_GETVAR: 170 fastboot_getvar_all(response); 171 break; 172 case FASTBOOT_COMMAND_OEM_CONSOLE: 173 if (CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_CONSOLE)) { 174 char buf[FASTBOOT_RESPONSE_LEN] = { 0 }; 175 176 if (console_record_isempty()) { 177 console_record_reset(); 178 fastboot_okay(NULL, response); 179 } else { 180 int ret = console_record_readline(buf, sizeof(buf) - 5); 181 182 if (ret < 0) 183 fastboot_fail("Error reading console", response); 184 else 185 fastboot_response("INFO", response, "%s", buf); 186 } 187 break; 188 } 189 default: 190 fastboot_fail("Unknown multiresponse command", response); 191 break; 192 } 193} 194 195/** 196 * okay() - Send bare OKAY response 197 * 198 * @cmd_parameter: Pointer to command parameter 199 * @response: Pointer to fastboot response buffer 200 * 201 * Send a bare OKAY fastboot response. This is used where the command is 202 * valid, but all the work is done after the response has been sent (e.g. 203 * boot, reboot etc.) 204 */ 205static void okay(char *cmd_parameter, char *response) 206{ 207 fastboot_okay(NULL, response); 208} 209 210/** 211 * getvar() - Read a config/version variable 212 * 213 * @cmd_parameter: Pointer to command parameter 214 * @response: Pointer to fastboot response buffer 215 */ 216static void getvar(char *cmd_parameter, char *response) 217{ 218 fastboot_getvar(cmd_parameter, response); 219} 220 221/** 222 * fastboot_download() - Start a download transfer from the client 223 * 224 * @cmd_parameter: Pointer to command parameter 225 * @response: Pointer to fastboot response buffer 226 */ 227static void download(char *cmd_parameter, char *response) 228{ 229 char *tmp; 230 231 if (!cmd_parameter) { 232 fastboot_fail("Expected command parameter", response); 233 return; 234 } 235 fastboot_bytes_received = 0; 236 fastboot_bytes_expected = hextoul(cmd_parameter, &tmp); 237 if (fastboot_bytes_expected == 0) { 238 fastboot_fail("Expected nonzero image size", response); 239 return; 240 } 241 /* 242 * Nothing to download yet. Response is of the form: 243 * [DATA|FAIL]$cmd_parameter 244 * 245 * where cmd_parameter is an 8 digit hexadecimal number 246 */ 247 if (fastboot_bytes_expected > fastboot_buf_size) { 248 fastboot_fail(cmd_parameter, response); 249 } else { 250 printf("Starting download of %d bytes\n", 251 fastboot_bytes_expected); 252 fastboot_response("DATA", response, "%s", cmd_parameter); 253 } 254} 255 256/** 257 * fastboot_data_remaining() - return bytes remaining in current transfer 258 * 259 * Return: Number of bytes left in the current download 260 */ 261u32 fastboot_data_remaining(void) 262{ 263 return fastboot_bytes_expected - fastboot_bytes_received; 264} 265 266/** 267 * fastboot_data_download() - Copy image data to fastboot_buf_addr. 268 * 269 * @fastboot_data: Pointer to received fastboot data 270 * @fastboot_data_len: Length of received fastboot data 271 * @response: Pointer to fastboot response buffer 272 * 273 * Copies image data from fastboot_data to fastboot_buf_addr. Writes to 274 * response. fastboot_bytes_received is updated to indicate the number 275 * of bytes that have been transferred. 276 * 277 * On completion sets image_size and ${filesize} to the total size of the 278 * downloaded image. 279 */ 280void fastboot_data_download(const void *fastboot_data, 281 unsigned int fastboot_data_len, 282 char *response) 283{ 284#define BYTES_PER_DOT 0x20000 285 u32 pre_dot_num, now_dot_num; 286 287 if (fastboot_data_len == 0 || 288 (fastboot_bytes_received + fastboot_data_len) > 289 fastboot_bytes_expected) { 290 fastboot_fail("Received invalid data length", 291 response); 292 return; 293 } 294 /* Download data to fastboot_buf_addr */ 295 memcpy(fastboot_buf_addr + fastboot_bytes_received, 296 fastboot_data, fastboot_data_len); 297 298 pre_dot_num = fastboot_bytes_received / BYTES_PER_DOT; 299 fastboot_bytes_received += fastboot_data_len; 300 now_dot_num = fastboot_bytes_received / BYTES_PER_DOT; 301 302 if (pre_dot_num != now_dot_num) { 303 putc('.'); 304 if (!(now_dot_num % 74)) 305 putc('\n'); 306 } 307 *response = '\0'; 308} 309 310/** 311 * fastboot_data_complete() - Mark current transfer complete 312 * 313 * @response: Pointer to fastboot response buffer 314 * 315 * Set image_size and ${filesize} to the total size of the downloaded image. 316 */ 317void fastboot_data_complete(char *response) 318{ 319 /* Download complete. Respond with "OKAY" */ 320 fastboot_okay(NULL, response); 321 printf("\ndownloading of %d bytes finished\n", fastboot_bytes_received); 322 image_size = fastboot_bytes_received; 323 env_set_hex("filesize", image_size); 324 fastboot_bytes_expected = 0; 325 fastboot_bytes_received = 0; 326} 327 328/** 329 * flash() - write the downloaded image to the indicated partition. 330 * 331 * @cmd_parameter: Pointer to partition name 332 * @response: Pointer to fastboot response buffer 333 * 334 * Writes the previously downloaded image to the partition indicated by 335 * cmd_parameter. Writes to response. 336 */ 337static void __maybe_unused flash(char *cmd_parameter, char *response) 338{ 339 if (IS_ENABLED(CONFIG_FASTBOOT_FLASH_MMC)) 340 fastboot_mmc_flash_write(cmd_parameter, fastboot_buf_addr, 341 image_size, response); 342 343 if (IS_ENABLED(CONFIG_FASTBOOT_FLASH_NAND)) 344 fastboot_nand_flash_write(cmd_parameter, fastboot_buf_addr, 345 image_size, response); 346} 347 348/** 349 * erase() - erase the indicated partition. 350 * 351 * @cmd_parameter: Pointer to partition name 352 * @response: Pointer to fastboot response buffer 353 * 354 * Erases the partition indicated by cmd_parameter (clear to 0x00s). Writes 355 * to response. 356 */ 357static void __maybe_unused erase(char *cmd_parameter, char *response) 358{ 359 if (IS_ENABLED(CONFIG_FASTBOOT_FLASH_MMC)) 360 fastboot_mmc_erase(cmd_parameter, response); 361 362 if (IS_ENABLED(CONFIG_FASTBOOT_FLASH_NAND)) 363 fastboot_nand_erase(cmd_parameter, response); 364} 365 366/** 367 * run_ucmd() - Execute the UCmd command 368 * 369 * @cmd_parameter: Pointer to command parameter 370 * @response: Pointer to fastboot response buffer 371 */ 372static void __maybe_unused run_ucmd(char *cmd_parameter, char *response) 373{ 374 if (!cmd_parameter) { 375 pr_err("missing slot suffix\n"); 376 fastboot_fail("missing command", response); 377 return; 378 } 379 380 if (run_command(cmd_parameter, 0)) 381 fastboot_fail("", response); 382 else 383 fastboot_okay(NULL, response); 384} 385 386static char g_a_cmd_buff[64]; 387 388void fastboot_acmd_complete(void) 389{ 390 run_command(g_a_cmd_buff, 0); 391} 392 393/** 394 * run_acmd() - Execute the ACmd command 395 * 396 * @cmd_parameter: Pointer to command parameter 397 * @response: Pointer to fastboot response buffer 398 */ 399static void __maybe_unused run_acmd(char *cmd_parameter, char *response) 400{ 401 if (!cmd_parameter) { 402 pr_err("missing slot suffix\n"); 403 fastboot_fail("missing command", response); 404 return; 405 } 406 407 if (strlen(cmd_parameter) > sizeof(g_a_cmd_buff)) { 408 pr_err("too long command\n"); 409 fastboot_fail("too long command", response); 410 return; 411 } 412 413 strcpy(g_a_cmd_buff, cmd_parameter); 414 fastboot_okay(NULL, response); 415} 416 417/** 418 * reboot_bootloader() - Sets reboot bootloader flag. 419 * 420 * @cmd_parameter: Pointer to command parameter 421 * @response: Pointer to fastboot response buffer 422 */ 423static void reboot_bootloader(char *cmd_parameter, char *response) 424{ 425 if (fastboot_set_reboot_flag(FASTBOOT_REBOOT_REASON_BOOTLOADER)) 426 fastboot_fail("Cannot set reboot flag", response); 427 else 428 fastboot_okay(NULL, response); 429} 430 431/** 432 * reboot_fastbootd() - Sets reboot fastboot flag. 433 * 434 * @cmd_parameter: Pointer to command parameter 435 * @response: Pointer to fastboot response buffer 436 */ 437static void reboot_fastbootd(char *cmd_parameter, char *response) 438{ 439 if (fastboot_set_reboot_flag(FASTBOOT_REBOOT_REASON_FASTBOOTD)) 440 fastboot_fail("Cannot set fastboot flag", response); 441 else 442 fastboot_okay(NULL, response); 443} 444 445/** 446 * reboot_recovery() - Sets reboot recovery flag. 447 * 448 * @cmd_parameter: Pointer to command parameter 449 * @response: Pointer to fastboot response buffer 450 */ 451static void reboot_recovery(char *cmd_parameter, char *response) 452{ 453 if (fastboot_set_reboot_flag(FASTBOOT_REBOOT_REASON_RECOVERY)) 454 fastboot_fail("Cannot set recovery flag", response); 455 else 456 fastboot_okay(NULL, response); 457} 458 459/** 460 * oem_format() - Execute the OEM format command 461 * 462 * @cmd_parameter: Pointer to command parameter 463 * @response: Pointer to fastboot response buffer 464 */ 465static void __maybe_unused oem_format(char *cmd_parameter, char *response) 466{ 467 char cmdbuf[32]; 468 const int mmc_dev = config_opt_enabled(CONFIG_FASTBOOT_FLASH_MMC, 469 CONFIG_FASTBOOT_FLASH_MMC_DEV, -1); 470 471 if (!env_get("partitions")) { 472 fastboot_fail("partitions not set", response); 473 } else { 474 sprintf(cmdbuf, "gpt write mmc %x $partitions", mmc_dev); 475 if (run_command(cmdbuf, 0)) 476 fastboot_fail("", response); 477 else 478 fastboot_okay(NULL, response); 479 } 480} 481 482/** 483 * oem_partconf() - Execute the OEM partconf command 484 * 485 * @cmd_parameter: Pointer to command parameter 486 * @response: Pointer to fastboot response buffer 487 */ 488static void __maybe_unused oem_partconf(char *cmd_parameter, char *response) 489{ 490 char cmdbuf[32]; 491 const int mmc_dev = config_opt_enabled(CONFIG_FASTBOOT_FLASH_MMC, 492 CONFIG_FASTBOOT_FLASH_MMC_DEV, -1); 493 494 if (!cmd_parameter) { 495 fastboot_fail("Expected command parameter", response); 496 return; 497 } 498 499 /* execute 'mmc partconfg' command with cmd_parameter arguments*/ 500 snprintf(cmdbuf, sizeof(cmdbuf), "mmc partconf %x %s 0", mmc_dev, cmd_parameter); 501 printf("Execute: %s\n", cmdbuf); 502 if (run_command(cmdbuf, 0)) 503 fastboot_fail("Cannot set oem partconf", response); 504 else 505 fastboot_okay(NULL, response); 506} 507 508/** 509 * oem_bootbus() - Execute the OEM bootbus command 510 * 511 * @cmd_parameter: Pointer to command parameter 512 * @response: Pointer to fastboot response buffer 513 */ 514static void __maybe_unused oem_bootbus(char *cmd_parameter, char *response) 515{ 516 char cmdbuf[32]; 517 const int mmc_dev = config_opt_enabled(CONFIG_FASTBOOT_FLASH_MMC, 518 CONFIG_FASTBOOT_FLASH_MMC_DEV, -1); 519 520 if (!cmd_parameter) { 521 fastboot_fail("Expected command parameter", response); 522 return; 523 } 524 525 /* execute 'mmc bootbus' command with cmd_parameter arguments*/ 526 snprintf(cmdbuf, sizeof(cmdbuf), "mmc bootbus %x %s", mmc_dev, cmd_parameter); 527 printf("Execute: %s\n", cmdbuf); 528 if (run_command(cmdbuf, 0)) 529 fastboot_fail("Cannot set oem bootbus", response); 530 else 531 fastboot_okay(NULL, response); 532} 533 534/** 535 * oem_console() - Execute the OEM console command 536 * 537 * @cmd_parameter: Pointer to command parameter 538 * @response: Pointer to fastboot response buffer 539 */ 540static void __maybe_unused oem_console(char *cmd_parameter, char *response) 541{ 542 if (cmd_parameter) 543 console_in_puts(cmd_parameter); 544 545 if (console_record_isempty()) 546 fastboot_fail("Empty console", response); 547 else 548 fastboot_response(FASTBOOT_MULTIRESPONSE_START, response, NULL); 549} 550 551/** 552 * fastboot_oem_board() - Execute the OEM board command. This is default 553 * weak implementation, which may be overwritten in board/ files. 554 * 555 * @cmd_parameter: Pointer to command parameter 556 * @data: Pointer to fastboot input buffer 557 * @size: Size of the fastboot input buffer 558 * @response: Pointer to fastboot response buffer 559 */ 560void __weak fastboot_oem_board(char *cmd_parameter, void *data, u32 size, char *response) 561{ 562 fastboot_fail("oem board function not defined", response); 563} 564 565/** 566 * oem_board() - Execute the OEM board command 567 * 568 * @cmd_parameter: Pointer to command parameter 569 * @response: Pointer to fastboot response buffer 570 */ 571static void __maybe_unused oem_board(char *cmd_parameter, char *response) 572{ 573 fastboot_oem_board(cmd_parameter, (void *)fastboot_buf_addr, image_size, response); 574}