This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx-apps.git

commit c3488c5b47f725e269f8d72d437a82a42e245cc9
Author: wangjianyu3 <[email protected]>
AuthorDate: Tue Jul 16 18:19:04 2024 +0800

    system/fastboot: Support upload & oem(memdump, filedump) command
    
    Signed-off-by: wangjianyu3 <[email protected]>
---
 system/fastboot/fastboot.c | 241 ++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 240 insertions(+), 1 deletion(-)

diff --git a/system/fastboot/fastboot.c b/system/fastboot/fastboot.c
index 8ca2090c5..6606d306c 100644
--- a/system/fastboot/fastboot.c
+++ b/system/fastboot/fastboot.c
@@ -110,6 +110,17 @@ struct fastboot_chunk_header_s
   uint32_t total_sz;        /* in bytes of chunk input file including chunk 
header and data */
 };
 
+struct fastboot_mem_s
+{
+  FAR void *addr;
+};
+
+struct fastboot_file_s
+{
+  char path[PATH_MAX];
+  off_t offset;
+};
+
 struct fastboot_ctx_s
 {
   int usbdev_in;
@@ -122,6 +133,16 @@ struct fastboot_ctx_s
   int wait_ms;
   FAR void *download_buffer;
   FAR struct fastboot_var_s *varlist;
+  CODE int (*upload_func)(FAR struct fastboot_ctx_s *context);
+  struct
+    {
+      size_t size;
+      union
+        {
+          struct fastboot_mem_s mem;
+          struct fastboot_file_s file;
+        } u;
+    } upload_param;
 };
 
 struct fastboot_cmd_s
@@ -147,6 +168,15 @@ static void fastboot_reboot(FAR struct fastboot_ctx_s 
*context,
                             FAR const char *arg);
 static void fastboot_reboot_bootloader(FAR struct fastboot_ctx_s *context,
                                        FAR const char *arg);
+static void fastboot_oem(FAR struct fastboot_ctx_s *context,
+                         FAR const char *arg);
+static void fastboot_upload(FAR struct fastboot_ctx_s *context,
+                            FAR const char *arg);
+
+static void fastboot_memdump(FAR struct fastboot_ctx_s *context,
+                             FAR const char *arg);
+static void fastboot_filedump(FAR struct fastboot_ctx_s *context,
+                              FAR const char *arg);
 
 /****************************************************************************
  * Private Data
@@ -159,7 +189,15 @@ static const struct fastboot_cmd_s g_fast_cmd[] =
   { "erase:",             fastboot_erase            },
   { "flash:",             fastboot_flash            },
   { "reboot-bootloader",  fastboot_reboot_bootloader},
-  { "reboot",             fastboot_reboot           }
+  { "reboot",             fastboot_reboot           },
+  { "oem",                fastboot_oem              },
+  { "upload",             fastboot_upload           }
+};
+
+static const struct fastboot_cmd_s g_oem_cmd[] =
+{
+  { "filedump",           fastboot_filedump         },
+  { "memdump",            fastboot_memdump          }
 };
 
 /****************************************************************************
@@ -582,6 +620,207 @@ static void fastboot_reboot_bootloader(FAR struct 
fastboot_ctx_s *context,
 #endif
 }
 
+static int fastboot_memdump_upload(FAR struct fastboot_ctx_s *context)
+{
+  return fastboot_write(context->usbdev_out,
+                        context->upload_param.u.mem.addr,
+                        context->upload_param.size);
+}
+
+/* Usage(host):
+ *   fastboot oem memdump <addr> <size>
+ *
+ * Example
+ *   fastboot oem memdump 0x44000000 0xb6c00
+ *   fastboot get_staged mem_44000000_440b6c00.bin
+ */
+
+static void fastboot_memdump(FAR struct fastboot_ctx_s *context,
+                             FAR const char *arg)
+{
+  if (!arg ||
+      sscanf(arg, "%p %zx",
+             &context->upload_param.u.mem.addr,
+             &context->upload_param.size) != 2)
+    {
+      fastboot_fail(context, "Invalid argument");
+      return;
+    }
+
+  fb_info("Memdump Addr: %p, Size: 0x%zx\n",
+          context->upload_param.u.mem.addr,
+          context->upload_param.size);
+  context->upload_func = fastboot_memdump_upload;
+  fastboot_okay(context, "");
+}
+
+static int fastboot_filedump_upload(FAR struct fastboot_ctx_s *context)
+{
+  size_t size = context->upload_param.size;
+  int fd;
+
+  fd = open(context->upload_param.u.file.path, O_RDONLY | O_CLOEXEC);
+  if (fd < 0)
+    {
+      fb_err("No such file or directory %d\n", errno);
+      return -errno;
+    }
+
+  if (context->upload_param.u.file.offset &&
+      lseek(fd, context->upload_param.u.file.offset,
+            context->upload_param.u.file.offset > 0 ? SEEK_SET :
+                                                      SEEK_END) < 0)
+    {
+      fb_err("Invalid argument, offset: %" PRIdOFF "\n",
+             context->upload_param.u.file.offset);
+      return -errno;
+    }
+
+  while (size > 0)
+    {
+      ssize_t nread = fastboot_read(fd, context->download_buffer,
+                                    MIN(size, context->download_max));
+      if (nread == 0)
+        {
+          break;
+        }
+      else if (nread < 0 ||
+               fastboot_write(context->usbdev_out,
+                              context->download_buffer,
+                              nread) < 0)
+        {
+          fb_err("Upload failed (%zu bytes left)\n", size);
+          return -errno;
+        }
+
+      size -= nread;
+    }
+
+  return 0;
+}
+
+/* Usage(host):
+ *   fastboot oem filedump <PATH> [<offset> <size>]
+ *
+ * Example
+ *   a. Upload the entire file:
+ *      fastboot oem filedump /dev/bootloader
+ *      fastboot get_staged bl_all.bin
+ *
+ *   b. Upload 4096 bytes of /dev/mem from offset 2048:
+ *      fastboot oem filedump /dev/mem 2048 4096
+ *      fastboot get_staged bl_2048_6144.bin
+ *
+ *   c. Get 2048 bytes from offset -1044480
+ *      fastboot oem "filedump /dev/bootloader -1044480 2048"
+ *      fastboot get_staged bl_l1044480_l1042432.txt
+ */
+
+static void fastboot_filedump(FAR struct fastboot_ctx_s *context,
+                              FAR const char *arg)
+{
+  struct stat sb;
+  int ret;
+
+  if (!arg)
+    {
+      fastboot_fail(context, "Invalid argument");
+      return;
+    }
+
+  ret = sscanf(arg, "%s %" PRIdOFF " %zu",
+               context->upload_param.u.file.path,
+               &context->upload_param.u.file.offset,
+               &context->upload_param.size);
+  if (ret != 1 && ret != 3)
+    {
+      fastboot_fail(context, "Failed to parse arguments");
+      return;
+    }
+  else if (ret == 1)
+    {
+      ret = stat(context->upload_param.u.file.path, &sb);
+      if (ret < 0)
+        {
+          fastboot_fail(context, "No such file or directory");
+          return;
+        }
+
+      context->upload_param.size = sb.st_size;
+      context->upload_param.u.file.offset = 0;
+    }
+
+  fb_info("Filedump Path: %s, Offset: %" PRIdOFF ", Size: %zu\n",
+          context->upload_param.u.file.path,
+          context->upload_param.u.file.offset,
+          context->upload_param.size);
+  context->upload_func = fastboot_filedump_upload;
+  fastboot_okay(context, "");
+}
+
+static void fastboot_upload(FAR struct fastboot_ctx_s *context,
+                            FAR const char *arg)
+{
+  char response[FASTBOOT_MSG_LEN];
+  int ret;
+
+  if (!context->upload_param.size || !context->upload_func)
+    {
+      fastboot_fail(context, "No data staged by the last command");
+      return;
+    }
+
+  snprintf(response, FASTBOOT_MSG_LEN, "DATA%08zx",
+           context->upload_param.size);
+
+  ret = fastboot_write(context->usbdev_out, response, strlen(response));
+  if (ret < 0)
+    {
+      fb_err("Reponse error [%d]\n", -ret);
+      goto done;
+    }
+
+  ret = context->upload_func(context);
+  if (ret < 0)
+    {
+      fb_err("Upload failed, [%d]\n", -ret);
+      fastboot_fail(context, "Upload failed");
+    }
+  else
+    {
+      fastboot_okay(context, "");
+    }
+
+done:
+  context->upload_param.size = 0;
+  context->upload_func = NULL;
+}
+
+static void fastboot_oem(FAR struct fastboot_ctx_s *context,
+                         FAR const char *arg)
+{
+  size_t ncmds = nitems(g_oem_cmd);
+  size_t index;
+
+  arg++;
+
+  for (index = 0; index < ncmds; index++)
+    {
+      size_t len = strlen(g_oem_cmd[index].prefix);
+      if (memcmp(arg, g_oem_cmd[index].prefix, len) == 0)
+        {
+          arg += len;
+          g_oem_cmd[index].handle(context, *arg == ' ' ? ++arg : NULL);
+          break;
+        }
+    }
+
+  if (index == ncmds)
+    {
+      fastboot_fail(context, "Unknown command");
+    }
+}
+
 static void fastboot_command_loop(FAR struct fastboot_ctx_s *context)
 {
   if (context->wait_ms > 0)

Reply via email to