1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * (C) Copyright 2008 - 2009 4 * Windriver, <www.windriver.com> 5 * Tom Rix <Tom.Rix@windriver.com> 6 * 7 * Copyright 2011 Sebastian Andrzej Siewior <bigeasy@linutronix.de> 8 * 9 * Copyright 2014 Linaro, Ltd. 10 * Rob Herring <robh@kernel.org> 11 */ 12 13 #include <common.h> 14 #include <fastboot.h> 15 #include <net/fastboot.h> 16 17 /** 18 * fastboot_buf_addr - base address of the fastboot download buffer 19 */ 20 void *fastboot_buf_addr; 21 22 /** 23 * fastboot_buf_size - size of the fastboot download buffer 24 */ 25 u32 fastboot_buf_size; 26 27 /** 28 * fastboot_progress_callback - callback executed during long operations 29 */ 30 void (*fastboot_progress_callback)(const char *msg); 31 32 /** 33 * fastboot_response() - Writes a response of the form "$tag$reason". 34 * 35 * @tag: The first part of the response 36 * @response: Pointer to fastboot response buffer 37 * @format: printf style format string 38 */ 39 void fastboot_response(const char *tag, char *response, 40 const char *format, ...) 41 { 42 va_list args; 43 44 strlcpy(response, tag, FASTBOOT_RESPONSE_LEN); 45 if (format) { 46 va_start(args, format); 47 vsnprintf(response + strlen(response), 48 FASTBOOT_RESPONSE_LEN - strlen(response) - 1, 49 format, args); 50 va_end(args); 51 } 52 } 53 54 /** 55 * fastboot_fail() - Write a FAIL response of the form "FAIL$reason". 56 * 57 * @reason: Pointer to returned reason string 58 * @response: Pointer to fastboot response buffer 59 */ 60 void fastboot_fail(const char *reason, char *response) 61 { 62 fastboot_response("FAIL", response, "%s", reason); 63 } 64 65 /** 66 * fastboot_okay() - Write an OKAY response of the form "OKAY$reason". 67 * 68 * @reason: Pointer to returned reason string, or NULL to send a bare "OKAY" 69 * @response: Pointer to fastboot response buffer 70 */ 71 void fastboot_okay(const char *reason, char *response) 72 { 73 if (reason) 74 fastboot_response("OKAY", response, "%s", reason); 75 else 76 fastboot_response("OKAY", response, NULL); 77 } 78 79 /** 80 * fastboot_set_reboot_flag() - Set flag to indicate reboot-bootloader 81 * 82 * Set flag which indicates that we should reboot into the bootloader 83 * following the reboot that fastboot executes after this function. 84 * 85 * This function should be overridden in your board file with one 86 * which sets whatever flag your board specific Android bootloader flow 87 * requires in order to re-enter the bootloader. 88 */ 89 int __weak fastboot_set_reboot_flag(void) 90 { 91 return -ENOSYS; 92 } 93 94 /** 95 * fastboot_get_progress_callback() - Return progress callback 96 * 97 * Return: Pointer to function called during long operations 98 */ 99 void (*fastboot_get_progress_callback(void))(const char *) 100 { 101 return fastboot_progress_callback; 102 } 103 104 /** 105 * fastboot_boot() - Execute fastboot boot command 106 * 107 * If ${fastboot_bootcmd} is set, run that command to execute the boot 108 * process, if that returns, then exit the fastboot server and return 109 * control to the caller. 110 * 111 * Otherwise execute "bootm <fastboot_buf_addr>", if that fails, reset 112 * the board. 113 */ 114 void fastboot_boot(void) 115 { 116 char *s; 117 118 s = env_get("fastboot_bootcmd"); 119 if (s) { 120 run_command(s, CMD_FLAG_ENV); 121 } else { 122 static char boot_addr_start[12]; 123 static char *const bootm_args[] = { 124 "bootm", boot_addr_start, NULL 125 }; 126 127 snprintf(boot_addr_start, sizeof(boot_addr_start) - 1, 128 "0x%p", fastboot_buf_addr); 129 printf("Booting kernel at %s...\n\n\n", boot_addr_start); 130 131 do_bootm(NULL, 0, 2, bootm_args); 132 133 /* 134 * This only happens if image is somehow faulty so we start 135 * over. We deliberately leave this policy to the invocation 136 * of fastbootcmd if that's what's being run 137 */ 138 do_reset(NULL, 0, 0, NULL); 139 } 140 } 141 142 /** 143 * fastboot_set_progress_callback() - set progress callback 144 * 145 * @progress: Pointer to progress callback 146 * 147 * Set a callback which is invoked periodically during long running operations 148 * (flash and erase). This can be used (for example) by the UDP transport to 149 * send INFO responses to keep the client alive whilst those commands are 150 * executing. 151 */ 152 void fastboot_set_progress_callback(void (*progress)(const char *msg)) 153 { 154 fastboot_progress_callback = progress; 155 } 156 157 /* 158 * fastboot_init() - initialise new fastboot protocol session 159 * 160 * @buf_addr: Pointer to download buffer, or NULL for default 161 * @buf_size: Size of download buffer, or zero for default 162 */ 163 void fastboot_init(void *buf_addr, u32 buf_size) 164 { 165 fastboot_buf_addr = buf_addr ? buf_addr : 166 (void *)CONFIG_FASTBOOT_BUF_ADDR; 167 fastboot_buf_size = buf_size ? buf_size : CONFIG_FASTBOOT_BUF_SIZE; 168 fastboot_set_progress_callback(NULL); 169 } 170