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

[incubator-nuttx] branch master updated (ee17ae5 -> b5b00c6)

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

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


    from ee17ae5  tool: add code coverage tool
     new aaf1a5e  fs/partition: support parse mbr partition
     new b5b00c6  fs/partition: support parse gpt partition

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:
 fs/partition/Kconfig        |   8 +
 fs/partition/Make.defs      |   8 +
 fs/partition/fs_gpt.c       | 482 ++++++++++++++++++++++++++++++++++++++++++++
 fs/partition/fs_mbr.c       | 214 ++++++++++++++++++++
 fs/partition/fs_partition.c |   9 +
 fs/partition/partition.h    |  12 ++
 6 files changed, 733 insertions(+)
 create mode 100644 fs/partition/fs_gpt.c
 create mode 100644 fs/partition/fs_mbr.c

[incubator-nuttx] 01/02: fs/partition: support parse mbr partition

Posted by xi...@apache.org.
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/incubator-nuttx.git

commit aaf1a5e113c8443afca7fa14a0cf75f010069125
Author: Jiuzhu Dong <do...@xiaomi.com>
AuthorDate: Wed Sep 29 22:45:24 2021 +0800

    fs/partition: support parse mbr partition
    
    Signed-off-by: Jiuzhu Dong <do...@xiaomi.com>
---
 fs/partition/Kconfig        |   4 +
 fs/partition/Make.defs      |   4 +
 fs/partition/fs_mbr.c       | 214 ++++++++++++++++++++++++++++++++++++++++++++
 fs/partition/fs_partition.c |   5 ++
 fs/partition/partition.h    |   6 ++
 5 files changed, 233 insertions(+)

diff --git a/fs/partition/Kconfig b/fs/partition/Kconfig
index 584b602..a2f0b70 100644
--- a/fs/partition/Kconfig
+++ b/fs/partition/Kconfig
@@ -11,6 +11,10 @@ config PTABLE_PARTITION
 	bool "PTABLE support"
 	default n
 
+config MBR_PARTITION
+	bool "MBR support"
+	default n
+
 endmenu
 
 endif
diff --git a/fs/partition/Make.defs b/fs/partition/Make.defs
index 0d8cf9e..78d72b6 100644
--- a/fs/partition/Make.defs
+++ b/fs/partition/Make.defs
@@ -28,6 +28,10 @@ ifeq ($(CONFIG_PTABLE_PARTITION),y)
 CSRCS += fs_ptable.c
 endif
 
+ifeq ($(CONFIG_MBR_PARTITION),y)
+CSRCS += fs_mbr.c
+endif
+
 # Include partition build support
 
 DEPPATH += --dep-path partition
diff --git a/fs/partition/fs_mbr.c b/fs/partition/fs_mbr.c
new file mode 100644
index 0000000..84a5f66
--- /dev/null
+++ b/fs/partition/fs_mbr.c
@@ -0,0 +1,214 @@
+/****************************************************************************
+ * fs/partition/fs_mbr.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 <debug.h>
+#include <endian.h>
+#include <string.h>
+
+#include <nuttx/kmalloc.h>
+
+#include "partition.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define MBR_SIZE                   512
+#define MBR_LBA_TO_BLOCK(lba, blk) ((le32toh(lba) * 512 + (blk) - 1) / (blk))
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/* These three have identical behaviour; use the second one if DOS FDISK gets
+ * confused about extended/logical partitions starting past cylinder 1023.
+ */
+
+enum mbr_type_e
+{
+  DOS_EXTENDED_PARTITION = 5,
+  LINUX_EXTENDED_PARTITION = 0x85,
+  WIN98_EXTENDED_PARTITION = 0x0f,
+};
+
+/* Description of one partition table entry (D*S type) */
+
+begin_packed_struct struct mbr_entry_s
+{
+  uint8_t boot_indicator;   /* Maybe marked as an active partition */
+  uint8_t chs_begin[3];     /* Start of the partition in cylinders, heads and sectors */
+  uint8_t type;             /* Filesystem type */
+  uint8_t chs_end[3];       /* End of the partition in cylinders, heads and sectors */
+  uint32_t partition_start; /* Start of the partition in LBA notation */
+  uint32_t partition_size;  /* Start of the partition in LBA notation */
+} end_packed_struct;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static inline int is_extended(uint8_t type)
+{
+  return (type == DOS_EXTENDED_PARTITION ||
+          type == WIN98_EXTENDED_PARTITION ||
+          type == LINUX_EXTENDED_PARTITION);
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: parse_mbr_partition
+ *
+ * Description:
+ *   parse the mbr(Master_boot_record) partition.
+ *
+ * Input Parameters:
+ *   state   - The partition table state
+ *   handler - The function to be called for each found partition
+ *   arg     - A caller provided value to return with the handler
+ *
+ * Returned Value:
+ *   Zero on success; A negated errno value is returned on a failure
+ *
+ ****************************************************************************/
+
+int parse_mbr_partition(FAR struct partition_state_s *state,
+                        partition_handler_t handler,
+                        FAR void *arg)
+{
+  struct partition_s pentry;
+  FAR struct mbr_entry_s *table;
+  FAR struct mbr_entry_s *extended = NULL;
+  FAR uint8_t *buffer;
+  int num;
+  int ret;
+  int i;
+
+  num = (MBR_SIZE + state->blocksize - 1) / state->blocksize;
+  buffer = kmm_malloc(num * state->blocksize);
+  if (!buffer)
+    {
+      return -ENOMEM;
+    }
+
+  ret = read_partition_block(state, buffer, 0, num);
+  if (ret < 0)
+    {
+      kmm_free(buffer);
+      return ret;
+    }
+
+  if (buffer[0x1fe] != 0x55 || buffer[0x1ff] != 0xaa)
+    {
+      kmm_free(buffer);
+      return -EINVAL;
+    }
+
+  memset(&pentry, 0, sizeof(pentry));
+  table = (FAR struct mbr_entry_s *)&buffer[0x1be];
+  for (i = 0; i < 4; i++)
+    {
+      pentry.firstblock = MBR_LBA_TO_BLOCK(table[i].partition_start,
+                          state->blocksize);
+      pentry.nblocks    = MBR_LBA_TO_BLOCK(table[i].partition_size,
+                          state->blocksize);
+
+      if (pentry.nblocks != 0)
+        {
+          if (!is_extended(table[i].type))
+            {
+              handler(&pentry, arg);
+              pentry.index++;
+            }
+          else if(!extended)
+            {
+              extended = &table[i];
+            }
+        }
+      else
+        {
+          finfo("Skipping empty partition %d\n", i);
+        }
+    }
+
+  if (extended)
+    {
+      uint32_t ebr_block;
+      ebr_block = MBR_LBA_TO_BLOCK(extended->partition_start,
+                                   state->blocksize);
+      while (1)
+        {
+          ret = read_partition_block(state, buffer, ebr_block, num);
+          if (ret < 0)
+            {
+              goto out;
+            }
+
+          if (buffer[0x1fe] != 0x55 || buffer[0x1ff] != 0xaa)
+            {
+              ferr("block %x doesn't contain an EBR signature\n",
+                   ebr_block);
+              ret = -EINVAL;
+              goto out;
+            }
+
+          for (i = 0x1de; i < 0x1fe; ++i)
+            {
+              if (buffer[i])
+                {
+                  ferr("EBR's third or fourth partition non-empty\n");
+                  ret = -EINVAL;
+                  goto out;
+                }
+            }
+
+          /* the first entry defines the extended partition */
+
+          pentry.firstblock = ebr_block + MBR_LBA_TO_BLOCK(
+                              table[0].partition_start, state->blocksize);
+          pentry.nblocks = MBR_LBA_TO_BLOCK(table[0].partition_size,
+                           state->blocksize);
+          handler(&pentry, arg);
+          pentry.index++;
+
+          /* the second entry defines the start of the next ebr if != 0 */
+
+          if (table[1].partition_start)
+            {
+              ebr_block = pentry.firstblock + MBR_LBA_TO_BLOCK(
+                          table[1].partition_start, state->blocksize);
+            }
+          else
+            {
+              break;
+            }
+        }
+    }
+
+out:
+  kmm_free(buffer);
+  return ret;
+}
diff --git a/fs/partition/fs_partition.c b/fs/partition/fs_partition.c
index 4a9287d..95b5799 100644
--- a/fs/partition/fs_partition.c
+++ b/fs/partition/fs_partition.c
@@ -52,6 +52,11 @@ static const partition_parser_t g_parser[] =
 #ifdef CONFIG_PTABLE_PARTITION
   parse_ptable_partition,
 #endif
+
+#ifdef CONFIG_MBR_PARTITION
+  parse_mbr_partition,
+#endif
+
   NULL
 };
 
diff --git a/fs/partition/partition.h b/fs/partition/partition.h
index 8c05c14..2358202 100644
--- a/fs/partition/partition.h
+++ b/fs/partition/partition.h
@@ -58,6 +58,12 @@ int parse_ptable_partition(FAR struct partition_state_s *state,
                            FAR void *arg);
 #endif
 
+#ifdef CONFIG_MBR_PARTITION
+int parse_mbr_partition(FAR struct partition_state_s *state,
+                        partition_handler_t handler,
+                        FAR void *arg);
+#endif
+
 #endif /* CONFIG_DISABLE_MOUNTPOINT */
 
 #endif /* __FS_PARTITION_PARTITION_H */

[incubator-nuttx] 02/02: fs/partition: support parse gpt partition

Posted by xi...@apache.org.
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/incubator-nuttx.git

commit b5b00c6ba325e0f4aa24b8fd022bdef5586e3a65
Author: Jiuzhu Dong <do...@xiaomi.com>
AuthorDate: Mon Oct 11 10:48:44 2021 +0800

    fs/partition: support parse gpt partition
    
    Signed-off-by: Jiuzhu Dong <do...@xiaomi.com>
---
 fs/partition/Kconfig        |   4 +
 fs/partition/Make.defs      |   4 +
 fs/partition/fs_gpt.c       | 482 ++++++++++++++++++++++++++++++++++++++++++++
 fs/partition/fs_partition.c |   4 +
 fs/partition/partition.h    |   6 +
 5 files changed, 500 insertions(+)

diff --git a/fs/partition/Kconfig b/fs/partition/Kconfig
index a2f0b70..8221ba4 100644
--- a/fs/partition/Kconfig
+++ b/fs/partition/Kconfig
@@ -15,6 +15,10 @@ config MBR_PARTITION
 	bool "MBR support"
 	default n
 
+config GPT_PARTITION
+	bool "GPT support"
+	default n
+
 endmenu
 
 endif
diff --git a/fs/partition/Make.defs b/fs/partition/Make.defs
index 78d72b6..738cf2d 100644
--- a/fs/partition/Make.defs
+++ b/fs/partition/Make.defs
@@ -32,6 +32,10 @@ ifeq ($(CONFIG_MBR_PARTITION),y)
 CSRCS += fs_mbr.c
 endif
 
+ifeq ($(CONFIG_GPT_PARTITION),y)
+CSRCS += fs_gpt.c
+endif
+
 # Include partition build support
 
 DEPPATH += --dep-path partition
diff --git a/fs/partition/fs_gpt.c b/fs/partition/fs_gpt.c
new file mode 100644
index 0000000..55753fc
--- /dev/null
+++ b/fs/partition/fs_gpt.c
@@ -0,0 +1,482 @@
+/****************************************************************************
+ * fs/partition/fs_gpt.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 <ctype.h>
+#include <debug.h>
+#include <endian.h>
+
+#include <nuttx/kmalloc.h>
+
+#include "partition.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define GPT_BLOCK_SIZE                  512
+#define GPT_HEADER_SIGNATURE            0x5452415020494645ull
+#define GPT_PARTNAME_MAX_SIZE           (72 / sizeof(uint16_t))
+#define GPT_LBA_TO_BLOCK(lba, blk)      ((le64toh(lba) * 512 + (blk) -1) / (blk))
+#define GPT_MIN(x, y)                   (((x) < (y)) ? (x) : (y))
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct gpt_guid_s
+{
+  uint8_t b[16];
+};
+
+/* For limited backward compatibility, the space of the legacy MBR is still
+ * reserved in the GPT specification, but it is now used in a way that
+ * prevents MBR-based disk utilities from misrecognizing and possibly
+ * overwriting GPT disks. This is referred to as a protective MBR.
+ */
+
+begin_packed_struct struct legacy_partition_s
+{
+  uint8_t  boot_ind;                     /* 0x80 - active */
+  uint8_t  head;                         /* Starting head */
+  uint8_t  sector;                       /* Starting sector */
+  uint8_t  cyl;                          /* Starting cylinder */
+  uint8_t  sys_ind;                      /* What partition type */
+  uint8_t  end_head;                     /* End head */
+  uint8_t  end_sector;                   /* End sector */
+  uint8_t  end_cyl;                      /* End cylinder */
+  uint32_t start_sect;                   /* Starting sector counting from 0 */
+  uint32_t nr_sects;                     /* Nr of sectors in partition */
+} end_packed_struct;
+
+/* The partition table header defines the usable blocks on the disk.
+ * It also defines the number and size of the partition entries that
+ * make up the partition table (offsets 80 and 84 in the table).
+ */
+
+begin_packed_struct struct gpt_header_s
+{
+  uint64_t signature;                    /* EFI PART */
+  uint32_t revision;                     /* Revision info */
+  uint32_t header_size;                  /* Header size in little endian */
+  uint32_t header_crc32;                 /* CRC32 of header (offset +0 up to header size) */
+  uint32_t reserved1;                    /* Must be zero */
+  uint64_t my_lba;                       /* Current LBA (location of this header copy) */
+  uint64_t alternate_lba;                /* Backup LBA (location of the other header copy) */
+  uint64_t first_usable_lba;             /* First usable LBA for partitions primary partition table last LBA + 1 */
+  uint64_t last_usable_lba;              /* Last usable LBA secondary partition table first LBA − 1 */
+  struct gpt_guid_s disk_guid;           /* Disk GUID in mixed endian */
+  uint64_t partition_entry_lba;          /* Starting LBA of array of partition entries (always 2 in primary copy) */
+  uint32_t num_partition_entries;        /* Number of partition entries in array */
+  uint32_t sizeof_partition_entry;       /* Size of a single partition entry */
+  uint32_t partition_entry_array_crc32;  /* CRC32 of partition entries array in little endian */
+
+  /* The rest of the logical block is reserved by UEFI and must be zero.
+   * EFI standard handles this by:
+   *
+   * uint8_t    reserved2[ BlockSize - 92 ];
+   */
+} end_packed_struct;
+
+/* After the header, the Partition Entry Array describes partitions,
+ * using a minimum size of 128 bytes for each entry block.
+ */
+
+/* The 64-bit partition table attributes are shared between 48-bit
+ * common attributes for all partition types, and 16-bit
+ * type-specific attributes
+ */
+
+begin_packed_struct struct gpt_entry_attributes_s
+{
+  uint64_t required_to_function:1;
+  uint64_t reserved:47;
+  uint64_t type_guid_specific:16;
+} end_packed_struct;
+
+begin_packed_struct struct gpt_entry_s
+{
+  struct gpt_guid_s partition_type_guid;          /* Partition type GUID */
+  struct gpt_guid_s unique_partition_guid;        /* Unique partition GUID */
+  uint64_t starting_lba;                          /* First LBA */
+  uint64_t ending_lba;                            /* Last LBA */
+  struct gpt_entry_attributes_s attributes;       /* Attribute flags */
+  uint16_t partition_name[GPT_PARTNAME_MAX_SIZE]; /* Partition name */
+} end_packed_struct;
+
+begin_packed_struct struct gpt_ptable_s
+{
+  uint8_t mbr[512];
+  union
+  {
+    struct gpt_header_s gpt_header;
+    uint8_t gpt[512];
+  } u;
+} end_packed_struct;
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct gpt_guid_s g_null_guid;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: gpt_last_lba
+ *
+ * Description:
+ *   Return number of last logical block of device, 0 on error.
+ *
+ * Input Parameters:
+ *   state   - The partition table state
+ *
+ * Returned Value:
+ *   Returns last LBA value on success, 0 on error.
+ *   This is stored (by sd and ide-geometry) in
+ *   the part[0] entry for this disk, and is the number of
+ *   physical sectors available on the disk.
+ *
+ ****************************************************************************/
+
+static inline blkcnt_t gpt_last_lba(FAR struct partition_state_s *state)
+{
+  return (state->nblocks * state->blocksize + GPT_BLOCK_SIZE - 1) /
+         GPT_BLOCK_SIZE - 1;
+}
+
+/****************************************************************************
+ * Name: gpt_alloc_verify_entries()
+ *
+ * Description:
+ *   reads and verifies partition entries from disk
+ *
+ * Input Parameters:
+ *   state     - the handle of partition state
+ *   gpt       - a GPT header ptr.
+ *
+ * Returned Value:
+ *   Returns ptes on success,  NULL on error.
+ *   Allocates space for PTEs based on information found in @gpt.
+ *   Notes: remember to free pte when you're done!
+ *
+ ****************************************************************************/
+
+static FAR struct gpt_entry_s *
+gpt_alloc_verify_entries(FAR struct partition_state_s *state,
+                         FAR struct gpt_header_s *gpt)
+{
+  FAR struct gpt_entry_s *pte;
+  unsigned long from;
+  unsigned long size;
+  unsigned long blk;
+  uint32_t crc;
+  int ret;
+
+  size = le32toh(gpt->num_partition_entries) *
+         le32toh(gpt->sizeof_partition_entry);
+  if (!size)
+    {
+      return NULL;
+    }
+
+  blk = (size + (state->blocksize -1)) / state->blocksize;
+  pte = kmm_zalloc(blk * state->blocksize);
+  if (!pte)
+    {
+      return NULL;
+    }
+
+  from = GPT_LBA_TO_BLOCK(gpt->partition_entry_lba,
+                          state->blocksize);
+  ret = read_partition_block(state, pte, from, blk);
+  if (ret < 0)
+    {
+      kmm_free(pte);
+      ferr("Read ptr from block failed:%d.\n", ret);
+      return NULL;
+    }
+
+  /* Check the GUID Partition Table Entry Array CRC */
+
+  crc = crc32part((FAR const uint8_t *)pte, size, ~0l) ^ ~0l;
+  if (crc != le32toh(gpt->partition_entry_array_crc32))
+    {
+      ferr("GUID Partitition Entry Array CRC check failed.\n");
+      kmm_free(pte);
+      return NULL;
+    }
+
+  return pte;
+}
+
+/****************************************************************************
+ * Name: gpt_header_is_valid
+ *
+ * Description:
+ *   tests one GPT header for validity
+ *
+ * Input Parameters:
+ *   state   - The partition table state
+ *   gpt     - is a GPT header ptr.
+ *   lba     - is the logical block address of the GPT header to test
+ *
+ * Returned Value:
+ *   Returns 0 if valid,  a negative errno returned on error.
+ *
+ ****************************************************************************/
+
+static int gpt_header_is_valid(FAR struct partition_state_s *state,
+                               FAR struct gpt_header_s *gpt, blkcnt_t lba)
+{
+  uint32_t crc;
+  uint32_t origcrc;
+  blkcnt_t lastlba;
+
+  /* Check the GPT header signature */
+
+  if (le64toh(gpt->signature) != GPT_HEADER_SIGNATURE)
+    {
+      ferr("GUID Partition Table Header signature is wrong:"
+            "0x%" PRIx64 " != 0x%" PRIx64 "\n",
+            le64toh(gpt->signature), GPT_HEADER_SIGNATURE);
+      return -EINVAL;
+    }
+
+  /* Check the GUID Partition Table CRC */
+
+  origcrc = gpt->header_crc32;
+  gpt->header_crc32 = 0;
+  crc = crc32part((FAR const uint8_t *)gpt,
+                  le32toh(gpt->header_size), ~0l) ^ ~0l;
+  if (crc != le32toh(origcrc))
+    {
+      ferr("GUID Partition Table Header CRC is wrong: %" PRIx32
+           " != %" PRIx32 "\n", crc, le32toh(origcrc));
+      return -EINVAL;
+    }
+
+  gpt->header_crc32 = origcrc;
+
+  /* Check that the my_lba entry points to the LBA that contains
+   * the GUID Partition Table
+   */
+
+  if (le64toh(gpt->my_lba) != lba)
+    {
+      ferr("GPT: my_lba incorrect: %" PRIx64 " != %" PRIx64 "\n",
+           le64toh(gpt->my_lba), lba);
+      return -EINVAL;
+    }
+
+  /* Check the first_usable_lba and last_usable_lba are within the disk. */
+
+  lastlba = gpt_last_lba(state);
+  if (le64toh(gpt->first_usable_lba) > lastlba)
+    {
+      ferr("GPT: first_usable_lba incorrect: %" PRId64 " > %" PRId64 "\n",
+           le64toh(gpt->first_usable_lba), lastlba);
+      return -EINVAL;
+    }
+
+  if (le64toh(gpt->last_usable_lba) > lastlba)
+    {
+      ferr("GPT: last_usable_lba incorrect: %" PRId64 " > %" PRId64 "\n",
+           le64toh(gpt->last_usable_lba), lastlba);
+      return -EINVAL;
+    }
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: gpt_pte_is_valid()
+ *
+ * Description:
+ *   tests one PTE for validity
+ *
+ * Input Parameters:
+ *   pte is the pte to check
+ *   lastlba is last lba of the disk
+ *
+ * Returned Value:
+ *   Returns 1 if valid,  0 on error.
+ *
+ ****************************************************************************/
+
+static inline int gpt_pte_is_valid(FAR const struct gpt_entry_s *pte,
+                                   blkcnt_t lastlba)
+{
+  if (!memcmp(&pte->partition_type_guid, &g_null_guid,
+              sizeof(g_null_guid)) ||
+      le64toh(pte->starting_lba) > lastlba ||
+      le64toh(pte->ending_lba) > lastlba)
+    {
+      return 0;
+    }
+
+  return 1;
+}
+
+static void gpt_part_set_name(FAR struct gpt_entry_s *pte,
+                              FAR char *dest, size_t len)
+{
+  int i;
+
+  if (--len > GPT_PARTNAME_MAX_SIZE)
+    {
+      len = GPT_PARTNAME_MAX_SIZE;
+    }
+
+  for (i = 0; i < len; i++)
+    {
+      uint8_t c = pte->partition_name[i];
+      dest[i] = (c && !isprint(c)) ? '.' : c;
+    }
+
+  dest[i] = 0;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: parse_gpt_partition
+ *
+ * Description:
+ *   parse the gpt(EFI GUID Partition Table) partition.
+ *
+ * Input Parameters:
+ *   state   - The partition table state
+ *   handler - The function to be called for each found partition
+ *   arg     - A caller provided value to return with the handler
+ *
+ * Returned Value:
+ *   Zero on success; A negated errno value is returned on a failure
+ *
+ ****************************************************************************/
+
+int parse_gpt_partition(FAR struct partition_state_s *state,
+                        partition_handler_t handler,
+                        FAR void *arg)
+{
+  FAR struct legacy_partition_s *pmbr;
+  FAR struct gpt_ptable_s *ptbl;
+  FAR struct gpt_header_s *gpt;
+  FAR struct gpt_entry_s *ptes;
+  struct partition_s pentry;
+  int nb_part;
+  int count;
+  int ret;
+
+  /* Read GPT Ptable (LBA0 + LBA1) */
+
+  count = (sizeof(struct gpt_ptable_s) + (state->blocksize - 1)) /
+          state->blocksize;
+  ptbl = kmm_malloc(count * state->blocksize);
+  if (!ptbl)
+    {
+      return -ENOMEM;
+    }
+
+  ret = read_partition_block(state, ptbl, 0, count);
+  if (ret < 0)
+    {
+      goto err;
+    }
+
+  /* Verify mbr is valid */
+
+  pmbr = (FAR struct legacy_partition_s *)&ptbl->mbr[0x1be];
+  if (pmbr->sys_ind != 0xee)
+    {
+      ret = -EINVAL;
+      goto err;
+    }
+
+  /* Verify gpt header is valid */
+
+  gpt = &(ptbl->u.gpt_header);
+  ret = gpt_header_is_valid(state, gpt, 1);
+  if (ret >= 0)
+    {
+      /* Verify gpt header is valid */
+
+      ptes = gpt_alloc_verify_entries(state, gpt);
+    }
+
+  if (ret < 0 || !ptes)
+    {
+      /* Read and Verify backup gpt header is valid */
+
+      finfo("Primary GPT is invalid, using alternate GPT.\n");
+
+      count = (GPT_BLOCK_SIZE + state->blocksize - 1) / state->blocksize;
+      ret = read_partition_block(state, ptbl,
+                                 GPT_LBA_TO_BLOCK(gpt->alternate_lba,
+                                 state->blocksize), count);
+      if (ret < 0)
+        {
+          goto err;
+        }
+
+      gpt = (FAR struct gpt_header_s *)ptbl;
+      ret = gpt_header_is_valid(state, gpt,
+                                le64toh(gpt->alternate_lba));
+      if (ret >= 0)
+        {
+          /* Verify gpt header is valid */
+
+          ptes = gpt_alloc_verify_entries(state, gpt);
+        }
+    }
+
+  if (ret < 0 || !ptes)
+    {
+      finfo("Alternate GPT is also invalid!!\n");
+      goto err;
+    }
+
+  nb_part = le32toh(gpt->num_partition_entries);
+  for (pentry.index = 0; pentry.index < nb_part; pentry.index++)
+    {
+      pentry.firstblock = GPT_LBA_TO_BLOCK(ptes[pentry.index].starting_lba,
+                                           state->blocksize);
+      pentry.nblocks = GPT_LBA_TO_BLOCK(ptes[pentry.index].ending_lba,
+                                        state->blocksize) -
+                       pentry.firstblock;
+      pentry.blocksize = state->blocksize;
+      gpt_part_set_name(&ptes[pentry.index], pentry.name,
+                        sizeof(pentry.name));
+      handler(&pentry, arg);
+    }
+
+  kmm_free(ptes);
+err:
+  kmm_free(ptbl);
+  return ret;
+}
diff --git a/fs/partition/fs_partition.c b/fs/partition/fs_partition.c
index 95b5799..1c52897 100644
--- a/fs/partition/fs_partition.c
+++ b/fs/partition/fs_partition.c
@@ -53,6 +53,10 @@ static const partition_parser_t g_parser[] =
   parse_ptable_partition,
 #endif
 
+#ifdef CONFIG_GPT_PARTITION
+  parse_gpt_partition,
+#endif
+
 #ifdef CONFIG_MBR_PARTITION
   parse_mbr_partition,
 #endif
diff --git a/fs/partition/partition.h b/fs/partition/partition.h
index 2358202..8c79b2c 100644
--- a/fs/partition/partition.h
+++ b/fs/partition/partition.h
@@ -58,6 +58,12 @@ int parse_ptable_partition(FAR struct partition_state_s *state,
                            FAR void *arg);
 #endif
 
+#ifdef CONFIG_GPT_PARTITION
+int parse_gpt_partition(FAR struct partition_state_s *state,
+                        partition_handler_t handler,
+                        FAR void *arg);
+#endif
+
 #ifdef CONFIG_MBR_PARTITION
 int parse_mbr_partition(FAR struct partition_state_s *state,
                         partition_handler_t handler,