Home | History | Annotate | Download | only in fastboot
      1 // SPDX-License-Identifier: GPL-2.0+
      2 /*
      3  * (C) Copyright 2008 - 2009
      4  * Windriver, <www.windriver.com>
      5  * Tom Rix <Tom.Rix (at) windriver.com>
      6  *
      7  * Copyright 2011 Sebastian Andrzej Siewior <bigeasy (at) linutronix.de>
      8  *
      9  * Copyright 2014 Linaro, Ltd.
     10  * Rob Herring <robh (at) 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