You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by je...@apache.org on 2021/10/28 06:54:36 UTC

[incubator-nuttx-apps] branch master updated (b480d00 -> f5e40d3)

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

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


    from b480d00  rexec: support send command with arguments
     new aaf6f5c  fsutils/mkmbr: support mbr partition format
     new f5e40d3  fsutils/mkgpt: support gpt partition format

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 {industry/abnt_codi => fsutils/mkgpt}/Kconfig    |   8 +-
 {builtin => fsutils/mkgpt}/Make.defs             |   6 +-
 {examples/smps => fsutils/mkgpt}/Makefile        |  14 +-
 fsutils/mkgpt/mkgpt.c                            | 599 +++++++++++++++++++++++
 {examples/hdc1008_demo => fsutils/mkmbr}/Kconfig |   8 +-
 {builtin => fsutils/mkmbr}/Make.defs             |   6 +-
 {examples/smps => fsutils/mkmbr}/Makefile        |  14 +-
 fsutils/mkmbr/mkmbr.c                            | 188 +++++++
 8 files changed, 816 insertions(+), 27 deletions(-)
 copy {industry/abnt_codi => fsutils/mkgpt}/Kconfig (57%)
 copy {builtin => fsutils/mkgpt}/Make.defs (89%)
 copy {examples/smps => fsutils/mkgpt}/Makefile (87%)
 create mode 100644 fsutils/mkgpt/mkgpt.c
 copy {examples/hdc1008_demo => fsutils/mkmbr}/Kconfig (62%)
 copy {builtin => fsutils/mkmbr}/Make.defs (89%)
 copy {examples/smps => fsutils/mkmbr}/Makefile (87%)
 create mode 100644 fsutils/mkmbr/mkmbr.c

[incubator-nuttx-apps] 01/02: fsutils/mkmbr: support mbr partition format

Posted by je...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit aaf6f5c4cbdf83901267b9a797353be17bbe26e1
Author: Jiuzhu Dong <do...@xiaomi.com>
AuthorDate: Fri Sep 24 22:11:12 2021 +0800

    fsutils/mkmbr: support mbr partition format
    
    Signed-off-by: Jiuzhu Dong <do...@xiaomi.com>
---
 fsutils/mkmbr/Kconfig   |  11 +++
 fsutils/mkmbr/Make.defs |  23 ++++++
 fsutils/mkmbr/Makefile  |  32 +++++++++
 fsutils/mkmbr/mkmbr.c   | 188 ++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 254 insertions(+)

diff --git a/fsutils/mkmbr/Kconfig b/fsutils/mkmbr/Kconfig
new file mode 100644
index 0000000..7a84030
--- /dev/null
+++ b/fsutils/mkmbr/Kconfig
@@ -0,0 +1,11 @@
+#
+# For a description of the syntax of this configuration file,
+# see the file kconfig-language.txt in the NuttX tools repository.
+#
+
+config FSUTILS_MKMBR
+	bool "mkmbr utility"
+	default n
+	select BCH
+	---help---
+		Enables support for the mkmbr utility
diff --git a/fsutils/mkmbr/Make.defs b/fsutils/mkmbr/Make.defs
new file mode 100644
index 0000000..89de722
--- /dev/null
+++ b/fsutils/mkmbr/Make.defs
@@ -0,0 +1,23 @@
+############################################################################
+# apps/fsutils/mkmbr/Make.defs
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+############################################################################
+
+ifneq ($(CONFIG_FSUTILS_MKMBR),)
+CONFIGURED_APPS += $(APPDIR)/fsutils/mkmbr
+endif
diff --git a/fsutils/mkmbr/Makefile b/fsutils/mkmbr/Makefile
new file mode 100644
index 0000000..96abeff
--- /dev/null
+++ b/fsutils/mkmbr/Makefile
@@ -0,0 +1,32 @@
+############################################################################
+# apps/fsutils/mkmbr/Make.defs
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+############################################################################
+
+include $(APPDIR)/Make.defs
+
+# mkmbr built-in application info
+
+PROGNAME  = mkmbr
+PRIORITY  = 100
+STACKSIZE = $(CONFIG_DEFAULT_TASK_STACKSIZE)
+MODULE    = $(CONFIG_FSUTILS_MKMBR)
+
+MAINSRC = mkmbr.c
+
+include $(APPDIR)/Application.mk
diff --git a/fsutils/mkmbr/mkmbr.c b/fsutils/mkmbr/mkmbr.c
new file mode 100644
index 0000000..9c02512
--- /dev/null
+++ b/fsutils/mkmbr/mkmbr.c
@@ -0,0 +1,188 @@
+/****************************************************************************
+ * apps/fsutils/mkmbr/mkmbr.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <endian.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#ifndef FAR
+#define FAR
+#endif
+
+#define PACKED                   __attribute__((packed))
+#define PARTITION_BOOTABLE_FLAG  0x80
+#define PARTITION_TYPE           0x83  /* GNU/Linux */
+#define MBR_BOOT_SIGNATURE       0xAA55
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct PACKED partition_s
+{
+  uint8_t  bootable_flag;
+  uint8_t  first_sector_chs[3];
+  uint8_t  type;
+  uint8_t  last_sector_chs[3];
+  uint32_t first_sector_lba;
+  uint32_t sectors_num_lba;
+};
+
+struct PACKED mbr_s
+{
+  uint8_t            bootstrap[446];
+  struct partition_s partitions[4];
+  uint16_t           boot_signature;
+};
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const char g_usage[] = "\
+Usage: \n\
+\n\
+  mkmbr dev p1_start p1_sectors [p2_start p2_sectors [...]]\n\
+\n\
+Where:\n\
+  dev    - block device path\n\
+  pX_start   - first sector number or \"auto\" to use next free sector\n\
+  pX_sectors - partition's sectors count or \"auto\" to use all free space\n\
+\n";
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static void print_usage(void)
+{
+  write(STDERR_FILENO, g_usage, sizeof(g_usage));
+}
+
+static void mbr_init(FAR struct mbr_s *mbr)
+{
+  memset(mbr, 0, sizeof(struct mbr_s));
+  mbr->boot_signature = MBR_BOOT_SIGNATURE;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+int main(int argc, FAR char *argv[])
+{
+  unsigned long bsize;
+  unsigned long start;
+  unsigned long size;
+  unsigned long next;
+  struct mbr_s mbr;
+  struct stat st;
+  int partn;
+  int argn;
+  int fd;
+  int ret;
+
+  if (argc < 4 || argc % 2 != 0)
+    {
+      print_usage();
+      return EINVAL;
+    }
+
+  fd = open(argv[1], O_RDWR);
+  if (fd < 0)
+    {
+      return errno;
+    }
+
+  ret = fstat(fd, &st);
+  if (ret < 0)
+    {
+      goto err_exit;
+    }
+
+  next = 1;
+  bsize = st.st_size / 512;
+  mbr_init(&mbr);
+  for (partn = 0; partn < 4 && next < bsize; partn++)
+    {
+      argn = 2 * (partn + 1);
+      if (!strcmp(argv[argn], "auto"))
+        {
+          start = next;
+        }
+      else
+        {
+          errno = 0;
+          start = strtoul(argv[argn], NULL, 0);
+          if (errno)
+            {
+              goto err_exit;
+            }
+        }
+
+      if (!strcmp(argv[argn + 1], "auto"))
+        {
+          size = bsize - start;
+        }
+      else
+        {
+          errno = 0;
+          size = strtoul(argv[argn + 1], NULL, 0);
+          if (errno)
+            {
+              goto err_exit;
+            }
+        }
+
+      if (start < next || start + size > bsize)
+        {
+          errno = EINVAL;
+          goto err_exit;
+        }
+
+      mbr.partitions[partn].first_sector_lba = htole32(start);
+      mbr.partitions[partn].sectors_num_lba  = htole32(size);
+      mbr.partitions[partn].type             = PARTITION_TYPE;
+      next = start + size;
+    }
+
+  ret = write(fd, &mbr, sizeof(mbr));
+  if (ret >= 0)
+    {
+      errno = 0;
+    }
+
+err_exit:
+  close(fd);
+  return errno;
+}

[incubator-nuttx-apps] 02/02: fsutils/mkgpt: support gpt partition format

Posted by je...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit f5e40d38092c5de472ea90c44448c04dc574e948
Author: Jiuzhu Dong <do...@xiaomi.com>
AuthorDate: Sat Sep 25 22:24:13 2021 +0800

    fsutils/mkgpt: support gpt partition format
    
    Signed-off-by: Jiuzhu Dong <do...@xiaomi.com>
---
 fsutils/mkgpt/Kconfig   |  12 +
 fsutils/mkgpt/Make.defs |  23 ++
 fsutils/mkgpt/Makefile  |  32 +++
 fsutils/mkgpt/mkgpt.c   | 599 ++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 666 insertions(+)

diff --git a/fsutils/mkgpt/Kconfig b/fsutils/mkgpt/Kconfig
new file mode 100644
index 0000000..b27545d
--- /dev/null
+++ b/fsutils/mkgpt/Kconfig
@@ -0,0 +1,12 @@
+#
+# For a description of the syntax of this configuration file,
+# see the file kconfig-language.txt in the NuttX tools repository.
+#
+
+config FSUTILS_MKGPT
+	bool "mkgpt utility"
+	default n
+	select BCH
+	select DEV_URANDOM
+	---help---
+		Enables support for the mkgpt utility
diff --git a/fsutils/mkgpt/Make.defs b/fsutils/mkgpt/Make.defs
new file mode 100644
index 0000000..9f92d81
--- /dev/null
+++ b/fsutils/mkgpt/Make.defs
@@ -0,0 +1,23 @@
+############################################################################
+# apps/fsutils/mkgpt/Make.defs
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+############################################################################
+
+ifneq ($(CONFIG_FSUTILS_MKGPT),)
+CONFIGURED_APPS += $(APPDIR)/fsutils/mkgpt
+endif
diff --git a/fsutils/mkgpt/Makefile b/fsutils/mkgpt/Makefile
new file mode 100644
index 0000000..1379ac4
--- /dev/null
+++ b/fsutils/mkgpt/Makefile
@@ -0,0 +1,32 @@
+############################################################################
+# apps/fsutils/mkgpt/Make.defs
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+############################################################################
+
+include $(APPDIR)/Make.defs
+
+# mkgpt built-in application info
+
+PROGNAME  = mkgpt
+PRIORITY  = 100
+STACKSIZE = $(CONFIG_DEFAULT_TASK_STACKSIZE)
+MODULE    = $(CONFIG_FSUTILS_MKGPT)
+
+MAINSRC = mkgpt.c
+
+include $(APPDIR)/Application.mk
diff --git a/fsutils/mkgpt/mkgpt.c b/fsutils/mkgpt/mkgpt.c
new file mode 100644
index 0000000..ac27448
--- /dev/null
+++ b/fsutils/mkgpt/mkgpt.c
@@ -0,0 +1,599 @@
+/****************************************************************************
+ * apps/fsutils/mkgpt/mkgpt.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <crc32.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#ifndef FAR
+#define FAR
+#endif
+
+#define EFI_VERSION       0x00010000
+#define EFI_MAGIC         "EFI PART"
+#define EFI_ENTRIES       128
+#define EFI_NAMELEN       36
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct efi_header_s
+{
+  uint8_t  magic[8];
+  uint32_t version;
+  uint32_t header_sz;
+  uint32_t crc32;
+  uint32_t reserved;
+  uint64_t header_lba;
+  uint64_t backup_lba;
+  uint64_t first_lba;
+  uint64_t last_lba;
+  uint8_t  volume_uuid[16];
+  uint64_t entries_lba;
+  uint32_t entries_count;
+  uint32_t entries_size;
+  uint32_t entries_crc32;
+}
+__attribute__ ((packed));
+
+struct efi_entry_s
+{
+  uint8_t  type_uuid[16];
+  uint8_t  uniq_uuid[16];
+  uint64_t first_lba;
+  uint64_t last_lba;
+  uint64_t attr;
+  uint16_t name[EFI_NAMELEN];
+};
+
+struct efi_ptable_s
+{
+  uint8_t mbr[512];
+  union
+  {
+    struct efi_header_s header;
+    uint8_t block[512];
+  };
+
+  struct efi_entry_s entry[EFI_ENTRIES];
+};
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const uint8_t g_partition_type_uuid[16] =
+{
+  0xa2, 0xa0, 0xd0, 0xeb, 0xe5, 0xb9, 0x33, 0x44,
+  0x87, 0xc0, 0x68, 0xb6, 0xb7, 0x26, 0x99, 0xc7,
+};
+
+static const uint8_t g_partition_type_efi[16] =
+{
+  0x28, 0x73, 0x2a, 0xc1, 0x1f, 0xf8, 0xd2, 0x11,
+  0xba, 0x4b, 0x00, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b,
+};
+
+static const uint8_t g_partition_type_linux[16] =
+{
+  0xa2, 0xa0, 0xd0, 0xeb, 0xe5, 0xb9, 0x33, 0x44,
+  0x87, 0xc0, 0x68, 0xb6, 0xb7, 0x26, 0x99, 0xc7,
+};
+
+static const uint8_t g_partition_type_swap[16] =
+{
+  0x6d, 0xfd, 0x57, 0x06, 0xab, 0xa4, 0xc4, 0x43,
+  0x84, 0xe5, 0x09, 0x33, 0xc8, 0x4b, 0x4f, 0x4f,
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static void get_uuid(FAR uint8_t *uuid)
+{
+  int fd;
+  fd = open("/dev/urandom", O_RDONLY);
+  if (fd > 0)
+    {
+      read(fd, uuid, 16);
+      close(fd);
+    }
+}
+
+static void init_mbr(FAR uint8_t *mbr, uint32_t blocks)
+{
+  /* nonbootable */
+
+  mbr[0x1be] = 0x00;
+
+  /* bogus CHS */
+
+  mbr[0x1bf] = 0x00;
+  mbr[0x1c0] = 0x01;
+  mbr[0x1c1] = 0x00;
+
+  /* GPT partition */
+
+  mbr[0x1c2] = 0xee;
+
+  /* bogus CHS */
+
+  mbr[0x1c3] = 0xfe;
+  mbr[0x1c4] = 0xff;
+  mbr[0x1c5] = 0xff;
+
+  /* start */
+
+  mbr[0x1c6] = 0x01;
+  mbr[0x1c7] = 0x00;
+  mbr[0x1c8] = 0x00;
+  mbr[0x1c9] = 0x00;
+
+  memcpy(mbr + 0x1ca, &blocks, sizeof(uint32_t));
+
+  /* signature */
+
+  mbr[0x1fe] = 0x55;
+  mbr[0x1ff] = 0xaa;
+}
+
+int add_ptn(FAR struct efi_ptable_s *ptbl, uint64_t first, uint64_t last,
+            FAR const char *name, FAR const uint8_t *type)
+{
+  FAR struct efi_header_s *hdr = &ptbl->header;
+  FAR struct efi_entry_s *entry = ptbl->entry;
+  int n;
+
+  if (first < 34)
+    {
+      fprintf(stderr, "partition '%s' overlaps partition table\n", name);
+      return -1;
+    }
+
+  if (last > hdr->last_lba)
+    {
+      fprintf(stderr, "partition '%s' does not fit on disk\n", name);
+      return -1;
+    }
+
+  if (hdr->entries_count > EFI_ENTRIES)
+    {
+      fprintf(stderr, "out of partition table entries\n");
+      return -1;
+    }
+
+  memcpy(entry[hdr->entries_count].type_uuid, type, 16);
+  get_uuid(entry[hdr->entries_count].uniq_uuid);
+  entry[hdr->entries_count].first_lba = first;
+  entry[hdr->entries_count].last_lba = last;
+  entry[hdr->entries_count].attr = 1ull << 63;
+  for (n = 0; n < EFI_NAMELEN && *name; n++)
+    {
+      entry[hdr->entries_count].name[n] = *name++;
+    }
+
+  hdr->entries_count++;
+  return 0;
+}
+
+static int usage(void)
+{
+  fprintf(stderr,
+    "usage: mkgpt write <disk> [ <partition> ]*\n"
+    "       mkgpt read <disk>\n"
+    "\n"
+    "partition:  [<name>]:<size>[kmg][=linux|=swap|=efi]\n"
+    "       or:  @<file-of-partitions>\n"
+    );
+  return 0;
+}
+
+static void show(FAR struct efi_ptable_s *ptbl)
+{
+  FAR struct efi_entry_s *entry = ptbl->entry;
+  char name[EFI_NAMELEN + 1];
+  unsigned n;
+  unsigned m;
+
+  fprintf(stderr, "ptn  start block   end block     name\n");
+  fprintf(stderr, "---- ------------- ------------- --------------------\n");
+
+  for (n = 0; n < ptbl->header.entries_count; n++)
+    {
+      for (m = 0; m < EFI_NAMELEN; m++)
+        {
+          name[m] = entry[n].name[m] & 127;
+        }
+
+      name[m] = 0;
+      fprintf(stderr, "#%03d %13" PRIu64 " %13" PRIu64" %s\n",
+              n + 1, entry[n].first_lba, entry[n].last_lba, name);
+    }
+}
+
+static uint64_t parse_size(FAR const char *sz)
+{
+  size_t l = strlen(sz);
+  uint64_t n = strtoull(sz, 0, 0);
+
+  if (l)
+    {
+      switch (sz[l - 1])
+        {
+          case 'k':
+          case 'K':
+            n *= 1024;
+            break;
+          case 'm':
+          case 'M':
+            n *= 1024 * 1024;
+            break;
+          case 'g':
+          case 'G':
+            n *= 1024 * 1024 * 1024;
+            break;
+        }
+    }
+
+  return n;
+}
+
+static int parse_ptn(FAR struct efi_ptable_s *ptbl, FAR char *x,
+                     FAR uint64_t *lba)
+{
+  FAR const uint8_t *type = g_partition_type_uuid;
+  FAR char *y = strchr(x, ':');
+  FAR char *z;
+  uint64_t sz;
+
+  if (!y)
+    {
+      fprintf(stderr, "invalid partition entry: %s\n", x);
+      return -1;
+    }
+
+  *y++ = 0;
+  z = strchr(y, '=');
+  if (z)
+    {
+      *z++ = 0;
+      if (!strcmp(z, "efi"))
+        {
+          type = g_partition_type_efi;
+        }
+      else if (!strcmp(z, "linux"))
+        {
+          type = g_partition_type_linux;
+        }
+      else if (!strcmp(z, "swap"))
+        {
+          type = g_partition_type_swap;
+        }
+    }
+
+  if (*y == '0')
+    {
+      sz = ptbl->header.last_lba - *lba;
+    }
+  else
+    {
+      sz = parse_size(y);
+      if (sz & 511)
+        {
+          fprintf(stderr, "partition size must be multiple of 512\n");
+          return -1;
+        }
+
+      sz /= 512;
+    }
+
+  if (sz == 0)
+    {
+      fprintf(stderr, "zero size partitions not allowed\n");
+      return -1;
+    }
+
+  if (x[0] && add_ptn(ptbl, *lba, *lba + sz - 1, x, type))
+    {
+      return -1;
+    }
+
+  *lba += sz;
+  return 0;
+}
+
+static void update_crc32(FAR struct efi_ptable_s *ptbl)
+{
+  uint32_t n;
+
+  n = crc32part((FAR const uint8_t *)ptbl->entry,
+                sizeof(ptbl->entry[0]) *
+                ptbl->header.entries_count, ~0l) ^ ~0l;
+  ptbl->header.entries_crc32 = n;
+
+  ptbl->header.crc32 = 0;
+  n = crc32part((FAR const uint8_t *)&ptbl->header,
+                sizeof(ptbl->header), ~0l) ^ ~0l;
+  ptbl->header.crc32 = n;
+}
+
+static int verify_gpt_pratition(FAR struct efi_ptable_s *ptbl)
+{
+  FAR struct efi_header_s *hdr = &ptbl->header;
+  uint32_t orgcrc;
+
+  if ((ptbl->mbr[0x1c2] != 0xee && ptbl->mbr[0x1c2] != 0x00) ||
+      ptbl->mbr[0x1fe] != 0x55 || ptbl->mbr[0x1ff] != 0xaa)
+    {
+      fprintf(stderr, "Invalid Protective or Hybrid MBR(%x)\n",
+              ptbl->mbr[0x1c2]);
+      return -1;
+    }
+
+  if (memcmp(hdr->magic, EFI_MAGIC, sizeof(hdr->magic)))
+    {
+      fprintf(stderr, "GPT: Header signature is wrong\n");
+      return -1;
+    }
+
+  orgcrc = hdr->crc32;
+  hdr->crc32 = 0;
+  if (orgcrc != (crc32part((FAR const uint8_t *)hdr,
+      sizeof(*hdr), ~0l) ^ ~0l))
+    {
+      fprintf(stderr, "GPT: Header CRC is wrong\n");
+      return -1;
+    }
+
+  hdr->crc32 = orgcrc;
+  if (hdr->header_lba != 1)
+    {
+      fprintf(stderr, "GPT: Header starting lba incorrect\n");
+      return -1;
+    }
+
+  if (hdr->entries_crc32 != (crc32part((FAR const uint8_t *)ptbl->entry,
+      sizeof(ptbl->entry[0]) * ptbl->header.entries_count, ~0l) ^ ~0l))
+    {
+      fprintf(stderr, "GPT: Header entry signature is wrong\n");
+      return -1;
+    }
+
+  show(ptbl);
+  return 0;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+int main(int argc, FAR char **argv)
+{
+  FAR struct efi_header_s *hdr;
+  FAR struct efi_ptable_s *ptbl;
+  FAR const char *device;
+  struct stat s;
+  uint64_t sz;
+  uint64_t lba;
+  uint64_t off;
+  int ret = -1;
+  int fd;
+  bool verify = false;
+
+  if (argc < 2)
+    {
+      return usage();
+    }
+
+  device = argv[2];
+  if (!strcmp(argv[1], "write") && argc >= 3)
+    {
+      argc -= 2;
+      argv += 2;
+    }
+  else if (!strcmp(argv[1], "read"))
+    {
+      verify = true;
+    }
+  else
+    {
+      return usage();
+    }
+
+  fd = open(device, O_RDWR);
+  if (fd < 0)
+    {
+      fprintf(stderr, "error: cannot open '%s'\n", device);
+      return ret;
+    }
+
+  if (fstat(fd, &s))
+    {
+      fprintf(stderr, "error: cannot stat '%s'\n", device);
+      goto err;
+    }
+
+  sz = s.st_size;
+  if (sz & 511)
+    {
+      fprintf(stderr, "error: file size not multiple of 512\n");
+      goto err;
+    }
+
+  sz /= 512;
+  ptbl = calloc(1, sizeof(*ptbl));
+  if (!ptbl)
+    {
+      goto err;
+    }
+
+  if (verify)
+    {
+      if (read(fd, ptbl, sizeof(*ptbl)) != sizeof(*ptbl))
+        {
+          fprintf(stderr, "error read primary partition table\n");
+          goto out;
+        }
+
+      ret = verify_gpt_pratition(ptbl);
+      goto out;
+    }
+
+  init_mbr(ptbl->mbr, sz - 1);
+  hdr = &ptbl->header;
+  memcpy(hdr->magic, EFI_MAGIC, sizeof(hdr->magic));
+  hdr->version = EFI_VERSION;
+  hdr->header_sz = sizeof(struct efi_header_s);
+  hdr->header_lba = 1;
+  hdr->backup_lba = sz - 1;
+  hdr->first_lba = 34;
+  hdr->last_lba = sz - 33;
+  get_uuid(hdr->volume_uuid);
+  hdr->entries_lba = 2;
+  hdr->entries_count = 0;
+  hdr->entries_size = sizeof(struct efi_entry_s);
+  lba = hdr->first_lba;
+
+  while (argc > 1)
+    {
+      if (argv[1][0] == '@')
+        {
+          FAR char *p;
+          FAR FILE *f;
+          char line[256];
+
+          f = fopen(argv[1] + 1, "r");
+          if (!f)
+            {
+              fprintf(stderr, "cannot read partitions from '%s\n", argv[1]);
+              goto out;
+            }
+
+          while (fgets(line, sizeof(line), f))
+            {
+              p = line + strlen(line);
+              while (p > line)
+                {
+                  if (*--p > ' ')
+                    {
+                      break;
+                    }
+
+                  *p = 0;
+                }
+
+              p = line;
+              while (*p && (*p <= ' '))
+                {
+                  p++;
+                }
+
+              if (*p == '#')
+                {
+                  continue;
+                }
+
+              if (*p == 0)
+                {
+                  continue;
+                }
+
+              if (parse_ptn(ptbl, p, &lba))
+                {
+                  fclose(f);
+                  goto out;
+                }
+            }
+
+          fclose(f);
+        }
+      else
+        {
+          if (parse_ptn(ptbl, argv[1], &lba))
+            {
+              goto out;
+            }
+        }
+
+      argc--;
+      argv++;
+    }
+
+  update_crc32(ptbl);
+  show(ptbl);
+  off = (sz - 33) * 512;
+  if (write(fd, ptbl, sizeof(*ptbl)) != sizeof(*ptbl))
+    {
+      fprintf(stderr, "error writing primary partition table\n");
+      goto out;
+    }
+
+  if (lseek(fd, off, SEEK_SET) != off)
+    {
+      fprintf(stderr, "error seeking to secondary partition table\n");
+      goto out;
+    }
+
+  /* reverse these for the secondary copy */
+
+  hdr->header_lba = sz -1;
+  hdr->backup_lba = 1;
+  update_crc32(ptbl);
+
+  if (write(fd, &ptbl->entry, sizeof(ptbl->entry)) !=
+      sizeof(ptbl->entry))
+    {
+      fprintf(stderr, "error writing secondary partition table\n");
+      goto out;
+    }
+
+  if (write(fd, &ptbl->header, 512) != 512)
+    {
+      fprintf(stderr, "error writing secondary partition header\n");
+      goto out;
+    }
+
+  fsync(fd);
+
+out:
+  free(ptbl);
+err:
+  close(fd);
+  return ret;
+}