一文了解fastboot

什么是fastboot

  1. fastboot是android使用的一种刷机方法。android系统设计了2种刷机方式:fastboot和recovery。
  2. fastboot使用usb作为物理传输。刷机其实是镜像传输+烧录,fastboot刷机时就是通过usb线来传输镜像的
  3. fastboot是uboot种的一个命令。uboot进行命令行中后,如果需要刷机,则可以在命令行中执行fastboot命令就可以让uboot进入fastboot模式,刷机就是在fastboot模式下进行的。
  4. fastboot需要主机端的fastboot软件配合。要实现fastboot刷机,只有开发板端uboot是不行的,还需要在主机有fastboot.exe配合。
  5. fastboot在开发板和主机间定义了一套协议。其实就是fastboot是我们在开发板和主机之间定义的一套协议,这套协议以usb为底层传输物理层,协议规定了主机fastbooot软件和开发板fastboot软件之间的信息传输规则。消息传递可以实现功能有:主机可以向开发板发送命令、开发板可以向主机发送回复、主机可以向开发板发送文件(download)

图1 fastboot运行演示

fastboot的工作原理

  1. uboot的fastboot的命令将开发板伪装成一个usb设备。开发板本身并不是一个usb设备,所以开发板直接插到电脑是没有反应的,没有提示发现设备需要装驱动的。伪装之后开发板就被主机windows识别成一个安卓手机了。
  2. 主机的fastboot软件和开发板的fastboot程序通信来工作。平时工作时,开发板端只要执行了fastboot命令进入fastboot模式即可,剩下的就不用管了。主机端通过运行fastboot命令,传递不同的参数来实现主机端和开发板端的通信。 譬如主机端执行fastboot devices,则这个命令通过usb线被传递到开发板中被开发板的fastboot程序接收,接收后去处理向主机端发送发聩信息,主机端接收到反馈信息后显示出来。
  3. 学习fastboot时分析代码的思路是:主机端:fastboot.exe的源代码没有,fastboot协议虽然能找到但是很枯燥,所以主机端没有去分析。开发板端:主要分析点就是uboot如何进入fastboot模式,fastboot模式下如何响应主机发送的各种命令。

fastboot源码分析

int do_fastboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
 int ret = 1;
 int check_timeout = 0;
 uint64_t timeout_endtime = 0;
 uint64_t timeout_ticks = 0;
 long timeout_seconds = -1;
 int continue_from_disconnect = 0;

 if (set_partition_table())
  return 1;


 /* Time out */
 if (2 == argc)
 {
  long try_seconds;
  char *try_seconds_end;
  /* Check for timeout */
  try_seconds = simple_strtol(argv[1], &try_seconds_end, 10);
  if ((try_seconds_end != argv[1]) && (try_seconds >= 0))
  {
   check_timeout = 1;
   timeout_seconds = try_seconds;
   printf("Fastboot inactivity timeout %ld seconds\n", timeout_seconds);
  }
 }

 if (1 == check_timeout)
 {
  timeout_ticks = (uint64_t) (timeout_seconds * get_tbclk());
 }


 do
 {
  continue_from_disconnect = 0;

  /* Initialize the board specific support */
  if (0 == fastboot_init(&interface))
  {
   int poll_status;

   /* If we got this far, we are a success */
   ret = 0;

   timeout_endtime = get_ticks();
   timeout_endtime += timeout_ticks;

   LCD_turnon();

   while (1)
   {
    uint64_t current_time = 0;
    poll_status = fastboot_poll();

    if (1 == check_timeout)
     current_time = get_ticks();

    /* Check if the user wanted to terminate with ^C */
    if ((poll_status != FASTBOOT_OK) && (ctrlc()))
    {
     printf("Fastboot ended by user\n");
     continue_from_disconnect = 0;
     break;
    }

    if (FASTBOOT_ERROR == poll_status)
    {
     /* Error */
     printf("Fastboot error \n");
     break;
    }
    else if (FASTBOOT_DISCONNECT == poll_status)
    {
     /* break, cleanup and re-init */
     printf("Fastboot disconnect detected\n");
     continue_from_disconnect = 1;
     break;
    }
    else if ((1 == check_timeout) &&
        (FASTBOOT_INACTIVE == poll_status))
    {
     /* No activity */
     if (current_time >= timeout_endtime)
     {
      printf("Fastboot inactivity detected\n");
      break;
     }
    }
    else
    {
     /* Something happened */
     /* Actual works of parsing are done by rx_handler */
     if (1 == check_timeout)
     {
      /* Update the timeout endtime */
      timeout_endtime = current_time;
      timeout_endtime += timeout_ticks;
     }
    }
   } /* while (1) */
  }

  /* Reset the board specific support */
  fastboot_shutdown();

  LCD_setfgcolor(0x000010);
  LCD_setleftcolor(0x000010);
  LCD_setprogress(100);

  /* restart the loop if a disconnect was detected */
 } while (continue_from_disconnect);

 return ret;
}

do_fastboot函数

  • do_fastboot函数本身涉及到很多操作SD/Nand等磁盘的,主要目的就是为了刷机。要完整的分析fastboot的函数细节很复杂很麻烦,我们并不是要做这个。

关键点:rx_handler

  • do_fastboot fastboot_poll fboot_usb_int_hndlr fboot_usb_pkt_receive fboot_usb_int_bulkout fastboot_interface->rx_handler(函数指针) 指向cmd_fastboot.c/rx_handler
  • 最终uboot这边的fastboot是通过rx_handler函数来处理主机端fastboot软件发送过来的信息的。fastboot协议的命令实现都是在这个函数中体现的,所示这个函数就是重点
static int rx_handler (const unsigned char *buffer, unsigned int buffer_size)
{
 int ret = 1;

 /* Use 65 instead of 64
    null gets dropped  
    strcpy's need the extra byte */
 char response[65];

 if (download_size) 
 {
  /* Something to download */

  if (buffer_size)
  {
   /* Handle possible overflow */
   unsigned int transfer_size = download_size - download_bytes;

   if (buffer_size < transfer_size)
    transfer_size = buffer_size;
   
   /* Save the data to the transfer buffer */
   memcpy (interface.transfer_buffer + download_bytes, 
    buffer, transfer_size);

   download_bytes += transfer_size;

   /* Check if transfer is done */
   if (download_bytes >= download_size)
   {
    /* Reset global transfer variable,
       Keep download_bytes because it will be
       used in the next possible flashing command */
    download_size = 0;

    if (download_error)
    {
     /* There was an earlier error */
     sprintf(response, "ERROR");
    }
    else
    {
     /* Everything has transferred,
        send the OK response */
     sprintf(response, "OKAY");
    }
    fastboot_tx_status(response, strlen(response), FASTBOOT_TX_ASYNC);

    printf ("\ndownloading of %d bytes finished\n", download_bytes);
    LCD_setprogress(0);
   }
···
···
//此处省略,如需可自己去看源码

else
 {
  /* A command */

  /* Cast to make compiler happy with string functions */
  const char *cmdbuf = (char *) buffer;

  /* Generic failed response */
  sprintf(response, "FAIL");

  /* reboot 
     Reboot the board. */
  if (memcmp(cmdbuf, "reboot", 6) == 0)
  {
   if (!strcmp(cmdbuf + 6, "-bootloader"))
   {
    strcpy((char *)interface.transfer_buffer, (char *)FASTBOOT_REBOOT_MAGIC);
   }
   else
   {
    memset(interface.transfer_buffer, 0x0, FASTBOOT_REBOOT_MAGIC_SIZE);
   }

   sprintf(response,"OKAY");
   fastboot_tx_status(response, strlen(response), FASTBOOT_TX_SYNC);
   //udelay (1000000); /* 1 sec */

   do_reset (NULL, 0, 0, NULL);
   
   /* This code is unreachable,
      leave it to make the compiler happy */
   return 0;
  }
···
···
//此处省略,如需可自己去看源码

大文件download机制

  • rx_handler函数中通过if和else分成了两部分,if部分负责处理download,else部分负责处理命令。usb传输单次传输最大只能有限个字节(64、256),因此当发送比较小的东西(譬如命令)时可以单词传输完毕;当发送比较大的东西时(譬如文件)就必须要分包发送。

download后的响应机制

  • 开发板端通过fastboot_tx_status函数向主机发送响应,主机显示这个响应。

fastboot常用命令

  1. fastboot getvar:作用是得到一些fastboot中定义的变量名的值,譬如version、product、serialno、downloadsize
  2. fastboot erase:擦除
  3. fastboot download:下载
  4. fastboot boot:启动内核
  5. fastboot flash:烧录
  6. fastboot oem:oem是用户自定义的,其他命令都是fastboot协议定义的,但是有时候自带的命令不足以使用,oem厂商可能希望定义一些自己专有的命令,则可以使用oem命令。

  • 24
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

踏马潜行

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值