Browse Source

添加磁盘分区格式 gpt

linzhenxing 3 years ago
parent
commit
39d7bd7707

+ 121 - 0
components/drivers/include/drivers/gpt.h

@@ -0,0 +1,121 @@
+#ifndef __GPT_H
+#define __GPT_H
+#include <stdint.h>
+#include <drivers/mmcsd_card.h>
+typedef struct
+{
+    uint8_t b[16];
+} guid_t;
+
+#define MSDOS_MBR_SIGNATURE 0xaa55
+#define EFI_PMBR_OSTYPE_EFI 0xEF
+#define EFI_PMBR_OSTYPE_EFI_GPT 0xEE
+
+#define GPT_MBR_PROTECTIVE  1
+#define GPT_MBR_HYBRID      2
+
+#define GPT_HEADER_SIGNATURE 0x5452415020494645ULL
+#define GPT_HEADER_REVISION_V1 0x00010000
+#define GPT_PRIMARY_PARTITION_TABLE_LBA 1
+
+typedef guid_t gpt_guid_t __attribute__ ((aligned (4)));
+#define EFI_GUID(a, b, c, d...) (gpt_guid_t){ {                 \
+    (a) & 0xff, ((a) >> 8) & 0xff, ((a) >> 16) & 0xff, ((a) >> 24) & 0xff,  \
+    (b) & 0xff, ((b) >> 8) & 0xff,                      \
+    (c) & 0xff, ((c) >> 8) & 0xff, d } }
+
+#define NULL_GUID \
+    EFI_GUID(0x00000000, 0x0000, 0x0000,\
+             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)
+#define PARTITION_SYSTEM_GUID \
+    EFI_GUID( 0xC12A7328, 0xF81F, 0x11d2, \
+              0xBA, 0x4B, 0x00, 0xA0, 0xC9, 0x3E, 0xC9, 0x3B)
+#define LEGACY_MBR_PARTITION_GUID \
+    EFI_GUID( 0x024DEE41, 0x33E7, 0x11d3, \
+              0x9D, 0x69, 0x00, 0x08, 0xC7, 0x81, 0xF3, 0x9F)
+#define PARTITION_MSFT_RESERVED_GUID \
+    EFI_GUID( 0xE3C9E316, 0x0B5C, 0x4DB8, \
+              0x81, 0x7D, 0xF9, 0x2D, 0xF0, 0x02, 0x15, 0xAE)
+#define PARTITION_BASIC_DATA_GUID \
+    EFI_GUID( 0xEBD0A0A2, 0xB9E5, 0x4433, \
+              0x87, 0xC0, 0x68, 0xB6, 0xB7, 0x26, 0x99, 0xC7)
+#define PARTITION_LINUX_RAID_GUID \
+    EFI_GUID( 0xa19d880f, 0x05fc, 0x4d3b, \
+              0xa0, 0x06, 0x74, 0x3f, 0x0f, 0x84, 0x91, 0x1e)
+#define PARTITION_LINUX_SWAP_GUID \
+    EFI_GUID( 0x0657fd6d, 0xa4ab, 0x43c4, \
+              0x84, 0xe5, 0x09, 0x33, 0xc8, 0x4b, 0x4f, 0x4f)
+#define PARTITION_LINUX_LVM_GUID \
+    EFI_GUID( 0xe6d6d379, 0xf507, 0x44c2, \
+              0xa2, 0x3c, 0x23, 0x8f, 0x2a, 0x3d, 0xf9, 0x28)
+#pragma pack(push, 1)
+typedef struct _gpt_header
+{
+    uint64_t signature;
+    uint32_t revision;
+    uint32_t header_size;
+    uint32_t header_crc32;
+    uint32_t reserved1;
+    uint64_t my_lba;
+    uint64_t alternate_lba;
+    uint64_t first_usable_lba;
+    uint64_t last_usable_lba;
+    gpt_guid_t disk_guid;
+    uint64_t partition_entry_lba;
+    uint32_t num_partition_entries;
+    uint32_t sizeof_partition_entry;
+    uint32_t partition_entry_array_crc32;
+
+    /* The rest of the logical block is reserved by UEFI and must be zero.
+     * EFI standard handles this by:
+     *
+     * uint8_t      reserved2[ BlockSize - 92 ];
+     */
+} gpt_header;
+
+typedef struct _gpt_entry_attributes
+{
+    uint64_t required_to_function:1;
+    uint64_t reserved:47;
+    uint64_t type_guid_specific:16;
+} gpt_entry_attributes;
+
+typedef struct _gpt_entry
+{
+    gpt_guid_t partition_type_guid;
+    gpt_guid_t unique_partition_guid;
+    uint64_t starting_lba;
+    uint64_t ending_lba;
+    gpt_entry_attributes attributes;
+    uint16_t partition_name[72/sizeof(uint16_t)];
+} gpt_entry;
+
+typedef struct _gpt_mbr_record
+{
+    uint8_t boot_indicator; /* unused by EFI, set to 0x80 for bootable */
+    uint8_t start_head;     /* unused by EFI, pt start in CHS */
+    uint8_t start_sector;   /* unused by EFI, pt start in CHS */
+    uint8_t start_track;
+    uint8_t os_type;        /* EFI and legacy non-EFI OS types */
+    uint8_t end_head;       /* unused by EFI, pt end in CHS */
+    uint8_t end_sector;     /* unused by EFI, pt end in CHS */
+    uint8_t end_track;      /* unused by EFI, pt end in CHS */
+    uint32_t starting_lba;   /* used by EFI - start addr of the on disk pt */
+    uint32_t size_in_lba;    /* used by EFI - size of pt in LBA */
+} gpt_mbr_record;
+
+
+typedef struct _legacy_mbr
+{
+    uint8_t boot_code[440];
+    uint32_t unique_mbr_signature;
+    uint16_t unknown;
+    gpt_mbr_record partition_record[4];
+    uint16_t signature;
+} legacy_mbr;
+#pragma pack(pop)
+
+int check_gpt(struct rt_mmcsd_card *card);
+int get_partition_param(struct rt_mmcsd_card *card, struct dfs_partition *part, uint32_t pindex);
+void gpt_free();
+#endif /*__GPT_H*/

+ 1 - 0
components/drivers/include/drivers/mmcsd_card.h

@@ -141,6 +141,7 @@ struct rt_mmcsd_card {
 	rt_uint32_t	max_data_rate;	/* max data transfer rate */
 	rt_uint32_t	card_capacity;	/* card capacity, unit:KB */
 	rt_uint32_t	card_blksize;	/* card block size */
+	rt_uint32_t	card_sec_cnt;   /* card sector count*/
 	rt_uint32_t	erase_size;	/* erase size in sectors */
 	rt_uint16_t	card_type;
 #define CARD_TYPE_MMC                   0 /* MMC card */

+ 3 - 0
components/drivers/include/drivers/mmcsd_core.h

@@ -15,6 +15,8 @@
 #include <drivers/mmcsd_host.h>
 #include <drivers/mmcsd_card.h>
 #include <drivers/mmcsd_cmd.h>
+#include <stddef.h>
+#include <stdint.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -235,6 +237,7 @@ void mmcsd_free_host(struct rt_mmcsd_host *host);
 int rt_mmcsd_core_init(void);
 
 int rt_mmcsd_blk_init(void);
+rt_int32_t read_lba(struct rt_mmcsd_card *card, size_t lba, uint8_t *buffer, size_t count);
 rt_int32_t rt_mmcsd_blk_probe(struct rt_mmcsd_card *card);
 void rt_mmcsd_blk_remove(struct rt_mmcsd_card *card);
 

+ 1 - 0
components/drivers/sdio/SConscript

@@ -7,6 +7,7 @@ block_dev.c
 mmcsd_core.c
 sd.c
 sdio.c
+gpt.c
 mmc.c
 """)
 

+ 158 - 61
components/drivers/sdio/block_dev.c

@@ -12,6 +12,7 @@
 #include <dfs_fs.h>
 
 #include <drivers/mmcsd_core.h>
+#include <drivers/gpt.h>
 
 #define DBG_TAG               "SDIO"
 #ifdef RT_SDIO_DEBUG
@@ -339,6 +340,19 @@ static rt_int32_t mmcsd_set_blksize(struct rt_mmcsd_card *card)
 
     return 0;
 }
+rt_int32_t read_lba(struct rt_mmcsd_card *card, size_t lba, uint8_t *buffer, size_t count)
+{
+    rt_uint8_t status = 0;
+
+    status = mmcsd_set_blksize(card);
+    if(status)
+    {
+        return status;
+    }
+    mmcsd_delay_ms(1);
+    status = rt_mmcsd_req_blk(card, lba, buffer, count, 0);
+    return status;
+}
 
 #ifdef RT_USING_DEVICE_OPS
 const static struct rt_device_ops mmcsd_blk_ops =
@@ -360,25 +374,34 @@ rt_int32_t rt_mmcsd_blk_probe(struct rt_mmcsd_card *card)
     char dname[10];
     char sname[16];
     struct mmcsd_blk_device *blk_dev = RT_NULL;
+    int gpt_chk = 0;
 
-    err = mmcsd_set_blksize(card);
-    if(err)
+    LOG_D("probe mmcsd block device!");
+    gpt_chk = check_gpt(card);
+    if (gpt_chk == 1)
     {
-        return err;
+        status = RT_EOK;
     }
-
-    LOG_D("probe mmcsd block device!");
-
-    /* get the first sector to read partition table */
-    sector = (rt_uint8_t *)rt_malloc(SECTOR_SIZE);
-    if (sector == RT_NULL)
+    else
     {
-        LOG_E("allocate partition sector buffer failed!");
+        err = mmcsd_set_blksize(card);
+        if(err)
+        {
+            return err;
+        }
+        mmcsd_delay_ms(1);
+        /* get the first sector to read partition table */
+        sector = (rt_uint8_t *)rt_malloc(SECTOR_SIZE);
+        if (sector == RT_NULL)
+        {
+            LOG_E("allocate partition sector buffer failed!");
 
         return -RT_ENOMEM;
     }
 
-    status = rt_mmcsd_req_blk(card, 0, sector, 1, 0);
+        status = rt_mmcsd_req_blk(card, 0, sector, 1, 0);
+    }
+
     if (status == RT_EOK)
     {
         blk_dev = rt_calloc(1, sizeof(struct mmcsd_blk_device));
@@ -420,68 +443,135 @@ rt_int32_t rt_mmcsd_blk_probe(struct rt_mmcsd_card *card)
         rt_device_register(&(blk_dev->dev), card->host->name,
             RT_DEVICE_FLAG_RDWR);
         rt_list_insert_after(&blk_devices, &blk_dev->list);
-
-        for (i = 0; i < RT_MMCSD_MAX_PARTITION; i++)
+        if (gpt_chk == 1)
         {
-            blk_dev = rt_calloc(1, sizeof(struct mmcsd_blk_device));
-            if (!blk_dev)
+            for (i = 0; i < 128; i++)
             {
-                LOG_E("mmcsd:malloc memory failed!");
-                break;
-            }
+                blk_dev = rt_calloc(1, sizeof(struct mmcsd_blk_device));
+                if (!blk_dev)
+                {
+                    LOG_E("mmcsd:malloc memory failed!");
+                    break;
+                }
+                blk_dev->max_req_size = BLK_MIN((card->host->max_dma_segs *
+                                                card->host->max_seg_size) >> 9,
+                                                (card->host->max_blk_count *
+                                                card->host->max_blk_size) >> 9);
+
+                /* get the first partition */
+                status = get_partition_param(card, &blk_dev->part, i);
+                if (status == RT_EOK)
+                {
+                    rt_snprintf(dname, sizeof(dname)-1, "%s%d", card->host->name,i);
+                    rt_snprintf(sname, sizeof(sname)-1, "sem_%s%d", card->host->name,i+1);
+                    blk_dev->part.lock = rt_sem_create(sname, 1, RT_IPC_FLAG_FIFO);
+
+                    /* register mmcsd device */
+                    blk_dev->dev.type = RT_Device_Class_Block;
+#ifdef RT_USING_DEVICE_OPS
+                    blk_dev->dev.ops  = &mmcsd_blk_ops;
+#else
+                    blk_dev->dev.init = rt_mmcsd_init;
+                    blk_dev->dev.open = rt_mmcsd_open;
+                    blk_dev->dev.close = rt_mmcsd_close;
+                    blk_dev->dev.read = rt_mmcsd_read;
+                    blk_dev->dev.write = rt_mmcsd_write;
+                    blk_dev->dev.control = rt_mmcsd_control;
+#endif
+                    blk_dev->card = card;
 
-            blk_dev->max_req_size = BLK_MIN((card->host->max_dma_segs *
-                                             card->host->max_seg_size) >> 9,
-                                            (card->host->max_blk_count *
-                                             card->host->max_blk_size) >> 9);
+                    blk_dev->geometry.bytes_per_sector = 1<<9;
+                    blk_dev->geometry.block_size = card->card_blksize;
+                    blk_dev->geometry.sector_count = blk_dev->part.size;
 
-            /* get the first partition */
-            status = dfs_filesystem_get_partition(&blk_dev->part, sector, i);
-            if (status == RT_EOK)
-            {
-                rt_snprintf(dname, sizeof(dname)-1, "%s%d", card->host->name,i);
-                rt_snprintf(sname, sizeof(sname)-1, "sem_%s%d", card->host->name,i+1);
-                blk_dev->part.lock = rt_sem_create(sname, 1, RT_IPC_FLAG_FIFO);
+                    blk_dev->dev.user_data = blk_dev;
 
-                /* register mmcsd device */
-                blk_dev->dev.type = RT_Device_Class_Block;
+                    rt_device_register(&(blk_dev->dev), dname,
+                        RT_DEVICE_FLAG_RDWR);
+                    rt_list_insert_after(&blk_devices, &blk_dev->list);
+                }
+                else
+                {
+                    rt_free(blk_dev);
+                    blk_dev = RT_NULL;
+                    break;
+                }
+
+#ifdef RT_USING_DFS_MNTTABLE
+                if (blk_dev)
+                {
+                    LOG_I("try to mount file system!");
+                    /* try to mount file system on this block device */
+                    dfs_mount_device(&(blk_dev->dev));
+                }
+#endif
+            }
+
+        }
+        else
+        {
+            for (i = 0; i < RT_MMCSD_MAX_PARTITION; i++)
+            {
+                blk_dev = rt_calloc(1, sizeof(struct mmcsd_blk_device));
+                if (!blk_dev)
+                {
+                    LOG_E("mmcsd:malloc memory failed!");
+                    break;
+                }
+                blk_dev->max_req_size = BLK_MIN((card->host->max_dma_segs *
+                                                card->host->max_seg_size) >> 9,
+                                                (card->host->max_blk_count *
+                                                card->host->max_blk_size) >> 9);
+
+                /* get the first partition */
+                status = dfs_filesystem_get_partition(&blk_dev->part, sector, i);
+                if (status == RT_EOK)
+                {
+                    rt_snprintf(dname, sizeof(dname)-1, "%s%d", card->host->name,i);
+                    rt_snprintf(sname, sizeof(sname)-1, "sem_%s%d", card->host->name,i+1);
+                    blk_dev->part.lock = rt_sem_create(sname, 1, RT_IPC_FLAG_FIFO);
+
+                    /* register mmcsd device */
+                    blk_dev->dev.type = RT_Device_Class_Block;
 #ifdef RT_USING_DEVICE_OPS
-                blk_dev->dev.ops  = &mmcsd_blk_ops;
+                    blk_dev->dev.ops  = &mmcsd_blk_ops;
 #else
-                blk_dev->dev.init = rt_mmcsd_init;
-                blk_dev->dev.open = rt_mmcsd_open;
-                blk_dev->dev.close = rt_mmcsd_close;
-                blk_dev->dev.read = rt_mmcsd_read;
-                blk_dev->dev.write = rt_mmcsd_write;
-                blk_dev->dev.control = rt_mmcsd_control;
+                    blk_dev->dev.init = rt_mmcsd_init;
+                    blk_dev->dev.open = rt_mmcsd_open;
+                    blk_dev->dev.close = rt_mmcsd_close;
+                    blk_dev->dev.read = rt_mmcsd_read;
+                    blk_dev->dev.write = rt_mmcsd_write;
+                    blk_dev->dev.control = rt_mmcsd_control;
 #endif
-                blk_dev->card = card;
+                    blk_dev->card = card;
 
-                blk_dev->geometry.bytes_per_sector = 1<<9;
-                blk_dev->geometry.block_size = card->card_blksize;
-                blk_dev->geometry.sector_count = blk_dev->part.size;
+                    blk_dev->geometry.bytes_per_sector = 1<<9;
+                    blk_dev->geometry.block_size = card->card_blksize;
+                    blk_dev->geometry.sector_count = blk_dev->part.size;
 
-                blk_dev->dev.user_data = blk_dev;
+                    blk_dev->dev.user_data = blk_dev;
 
-                rt_device_register(&(blk_dev->dev), dname,
-                    RT_DEVICE_FLAG_RDWR);
-                rt_list_insert_after(&blk_devices, &blk_dev->list);
-            }
-            else
-            {
-                rt_free(blk_dev);
-                blk_dev = RT_NULL;
-                break;
-            }
+                    rt_device_register(&(blk_dev->dev), dname,
+                        RT_DEVICE_FLAG_RDWR);
+                    rt_list_insert_after(&blk_devices, &blk_dev->list);
+                }
+                else
+                {
+                    rt_free(blk_dev);
+                    blk_dev = RT_NULL;
+                    break;
+                }
 
 #ifdef RT_USING_DFS_MNTTABLE
-            if (blk_dev)
-            {
-                LOG_I("try to mount file system!");
-                /* try to mount file system on this block device */
-                dfs_mount_device(&(blk_dev->dev));
-            }
+                if (blk_dev)
+                {
+                    LOG_I("try to mount file system!");
+                    /* try to mount file system on this block device */
+                    dfs_mount_device(&(blk_dev->dev));
+                }
 #endif
+            }
+
         }
     }
     else
@@ -490,8 +580,15 @@ rt_int32_t rt_mmcsd_blk_probe(struct rt_mmcsd_card *card)
         err = -RT_ERROR;
     }
 
-    /* release sector buffer */
-    rt_free(sector);
+    if (gpt_chk == 1)
+    {
+        gpt_free();
+    }
+    else
+    {
+        /* release sector buffer */
+        rt_free(sector);
+    }
 
     return err;
 }

+ 558 - 0
components/drivers/sdio/gpt.c

@@ -0,0 +1,558 @@
+#include <rtthread.h>
+#include <dfs_fs.h>
+#include <drivers/gpt.h>
+#include <drivers/mmcsd_core.h>
+
+#define DBG_TAG               "GPT"
+#ifdef RT_SDIO_DEBUG
+#define DBG_LVL               DBG_LOG
+#else
+#define DBG_LVL               DBG_INFO
+#endif /* RT_SDIO_DEBUG */
+#include <rtdbg.h>
+
+#define min(a, b) a < b ? a : b
+static int force_gpt = 0;
+
+static inline int efi_guidcmp (gpt_guid_t left, gpt_guid_t right)
+{
+    return rt_memcmp(&left, &right, sizeof (gpt_guid_t));
+}
+
+static uint32_t last_lba(struct rt_mmcsd_card *card)
+{
+    RT_ASSERT(card != RT_NULL);
+    return (card->card_sec_cnt) - 1;
+}
+
+static inline int pmbr_part_valid(gpt_mbr_record *part)
+{
+    if (part->os_type != EFI_PMBR_OSTYPE_EFI_GPT)
+    {
+        goto invalid;
+    }
+
+    /* set to 0x00000001 (i.e., the LBA of the GPT Partition Header) */
+    if ((uint32_t)(part->starting_lba) != GPT_PRIMARY_PARTITION_TABLE_LBA)
+    {
+        goto invalid;
+    }
+
+    return GPT_MBR_PROTECTIVE;
+invalid:
+    return 0;
+}
+/*
+*
+* return ret
+* ret = 0, invalid mbr
+* ret = 1, protect mbr
+* ret = 2, hybrid mbr
+*/
+int is_pmbr_valid(legacy_mbr *mbr, uint64_t total_sectors)
+{
+    uint32_t sz = 0;
+    int i, part = 0, ret = 0; /* invalid by default */
+
+    if (!mbr || (uint16_t)(mbr->signature) != MSDOS_MBR_SIGNATURE)
+    {
+        goto done;
+    }
+
+    for (i = 0; i < 4; i++)
+    {
+        ret = pmbr_part_valid(&mbr->partition_record[i]);
+        if (ret == GPT_MBR_PROTECTIVE)
+        {
+            part = i;
+            /*
+             * Ok, we at least know that there's a protective MBR,
+             * now check if there are other partition types for
+             * hybrid MBR.
+             */
+            goto check_hybrid;
+        }
+    }
+
+    if (ret != GPT_MBR_PROTECTIVE)
+    {
+        goto done;
+    }
+
+check_hybrid:
+    for (i = 0; i < 4; i++)
+    {
+        if ((mbr->partition_record[i].os_type !=
+            EFI_PMBR_OSTYPE_EFI_GPT) &&
+            (mbr->partition_record[i].os_type != 0x00))
+        {
+            ret = GPT_MBR_HYBRID;
+        }
+
+    }
+
+    /*
+     * Protective MBRs take up the lesser of the whole disk
+     * or 2 TiB (32bit LBA), ignoring the rest of the disk.
+     * Some partitioning programs, nonetheless, choose to set
+     * the size to the maximum 32-bit limitation, disregarding
+     * the disk size.
+     *
+     * Hybrid MBRs do not necessarily comply with this.
+     *
+     * Consider a bad value here to be a warning to support dd'ing
+     * an image from a smaller disk to a larger disk.
+     */
+    if (ret == GPT_MBR_PROTECTIVE)
+    {
+        sz = (uint32_t)(mbr->partition_record[part].size_in_lba);
+        if (sz != (uint32_t) total_sectors - 1 && sz != 0xFFFFFFFF)
+        {
+            LOG_I("GPT: mbr size in lba (%u) different than whole disk (%u).\n",
+                 sz, min(total_sectors - 1, 0xFFFFFFFF));
+        }
+    }
+
+done:
+    return ret;
+
+}
+
+static gpt_entry *alloc_read_gpt_entries(struct rt_mmcsd_card *card, gpt_header *gpt)
+{
+    size_t count;
+    gpt_entry *pte;
+
+    if (!gpt)
+    {
+        return RT_NULL;
+    }
+
+    count = (size_t)(gpt->num_partition_entries) * (gpt->sizeof_partition_entry);
+    if (!count)
+    {
+        return RT_NULL;
+    }
+
+    pte = rt_malloc(count);
+    if (!pte)
+        return RT_NULL;
+
+    if (read_lba(card, (size_t)(gpt->partition_entry_lba),(uint8_t *)pte, count/512) != RT_EOK)
+    {
+        rt_free(pte);
+        return RT_NULL;
+    }
+    return pte;
+
+}
+
+static gpt_header *alloc_read_gpt_header(struct rt_mmcsd_card *card, size_t lba)
+{
+    gpt_header *gpt;
+    void *buf;
+
+    buf = rt_malloc(512);
+    if (!buf)
+    {
+        return RT_NULL;
+    }
+
+    if (read_lba(card, lba, (uint8_t *)buf, 1) != RT_EOK)
+    {
+        rt_free(buf);
+        return RT_NULL;
+    }
+    gpt = (gpt_header *)buf;
+    
+    return gpt;
+}
+
+static int is_gpt_valid(struct rt_mmcsd_card *card, size_t lba, gpt_header **gpt, gpt_entry **ptes)
+{
+    size_t lastlba;
+    
+    if (!ptes)
+    {
+        return 0;
+    }
+
+    if (!(*gpt = alloc_read_gpt_header(card, lba)))
+    {
+        return 0;
+    }
+
+    /* Check the GUID Partition Table signature */
+    if ((uint64_t)((*gpt)->signature) != GPT_HEADER_SIGNATURE)
+    {
+        printf("GUID Partition Table Header signature is wrong:"
+             "%ld != %ld\n",(uint64_t)((*gpt)->signature),(uint64_t)GPT_HEADER_SIGNATURE);
+        goto fail;
+    }
+
+    /* Check the GUID Partition Table header size is too small */
+    if ((uint32_t)((*gpt)->header_size) < sizeof(gpt_header))
+    {
+        printf("GUID Partition Table Header size is too small: %u < %zu\n",
+            (uint32_t)((*gpt)->header_size),sizeof(gpt_header));
+        goto fail;
+    }
+
+    /* Check that the my_lba entry points to the LBA that contains
+     * the GUID Partition Table */
+    if ((uint64_t)((*gpt)->my_lba) != lba)
+    {
+        printf("GPT my_lba incorrect: %ld != %ld\n",
+             (uint64_t)((*gpt)->my_lba),
+             (uint64_t)lba);
+        goto fail;
+    }
+
+    /* Check the first_usable_lba and last_usable_lba are
+     * within the disk.
+     */
+    lastlba = last_lba(card);
+    if ((uint64_t)((*gpt)->first_usable_lba) > lastlba)
+    {
+        printf("GPT: first_usable_lba incorrect: %ld > %ld\n",
+             ((uint64_t)((*gpt)->first_usable_lba)),
+             (size_t)lastlba);
+        goto fail;
+    }
+
+    if ((uint64_t)((*gpt)->last_usable_lba) > lastlba)
+    {
+        printf("GPT: last_usable_lba incorrect: %ld > %ld\n",
+             (uint64_t)((*gpt)->last_usable_lba),
+             (size_t)lastlba);
+        goto fail;
+    }
+
+    if ((uint64_t)((*gpt)->last_usable_lba) < (uint64_t)((*gpt)->first_usable_lba))
+    {
+        printf("GPT: last_usable_lba incorrect: %ld > %ld\n",
+             (uint64_t)((*gpt)->last_usable_lba),
+             (uint64_t)((*gpt)->first_usable_lba));
+        goto fail;
+    }
+    /* Check that sizeof_partition_entry has the correct value */
+    if ((uint32_t)((*gpt)->sizeof_partition_entry) != sizeof(gpt_entry)) {
+        printf("GUID Partition Entry Size check failed.\n");
+        goto fail;
+    }
+
+    if (!(*ptes = alloc_read_gpt_entries(card, *gpt)))
+    {
+        goto fail;
+    }
+
+    /* We're done, all's well */
+    return 1;
+
+ fail:
+    rt_free(*gpt);
+    *gpt = RT_NULL;
+    return 0;
+}
+
+/**
+ * is_pte_valid() - tests one PTE for validity
+ * @pte:pte to check
+ * @lastlba: last lba of the disk
+ *
+ * Description: returns 1 if valid,  0 on error.
+ */
+static inline int is_pte_valid(const gpt_entry *pte, const size_t lastlba)
+{
+    if ((!efi_guidcmp(pte->partition_type_guid, NULL_GUID)) ||
+        (uint64_t)(pte->starting_lba) > lastlba         ||
+        (uint64_t)(pte->ending_lba)   > lastlba)
+    {
+        return 0;
+    }
+
+    return 1;
+}
+
+/**
+ * compare_gpts() - Search disk for valid GPT headers and PTEs
+ * @pgpt: primary GPT header
+ * @agpt: alternate GPT header
+ * @lastlba: last LBA number
+ *
+ * Description: Returns nothing.  Sanity checks pgpt and agpt fields
+ * and prints warnings on discrepancies.
+ *
+ */
+static void compare_gpts(gpt_header *pgpt, gpt_header *agpt, size_t lastlba)
+{
+    int error_found = 0;
+    if (!pgpt || !agpt)
+    {
+        return;
+    }
+
+    if ((uint64_t)(pgpt->my_lba) != (uint64_t)(agpt->alternate_lba))
+    {
+        LOG_I("GPT:Primary header LBA != Alt. header alternate_lba\n");
+        LOG_I("GPT:%lld != %lld\n",
+               (uint64_t)(pgpt->my_lba),
+                       (uint64_t)(agpt->alternate_lba));
+        error_found++;
+    }
+
+    if ((uint64_t)(pgpt->alternate_lba) != (uint64_t)(agpt->my_lba))
+    {
+        LOG_I("GPT:Primary header alternate_lba != Alt. header my_lba\n");
+        LOG_I("GPT:%lld != %lld\n",
+               (uint64_t)(pgpt->alternate_lba),
+                       (uint64_t)(agpt->my_lba));
+        error_found++;
+    }
+
+    if ((uint64_t)(pgpt->first_usable_lba) != (uint64_t)(agpt->first_usable_lba))
+    {
+        LOG_I("GPT:first_usable_lbas don't match.\n");
+        LOG_I("GPT:%lld != %lld\n",
+               (uint64_t)(pgpt->first_usable_lba),
+                       (uint64_t)(agpt->first_usable_lba));
+        error_found++;
+    }
+
+    if ((uint64_t)(pgpt->last_usable_lba) != (uint64_t)(agpt->last_usable_lba))
+    {
+        LOG_I("GPT:last_usable_lbas don't match.\n");
+        LOG_I("GPT:%lld != %lld\n",
+               (uint64_t)(pgpt->last_usable_lba),
+                       (uint64_t)(agpt->last_usable_lba));
+        error_found++;
+    }
+
+    if (efi_guidcmp(pgpt->disk_guid, agpt->disk_guid))
+    {
+        LOG_I("GPT:disk_guids don't match.\n");
+        error_found++;
+    }
+
+    if ((pgpt->num_partition_entries) != (agpt->num_partition_entries))
+    {
+        LOG_I("GPT:num_partition_entries don't match: "
+               "0x%x != 0x%x\n",
+               (pgpt->num_partition_entries),
+               (agpt->num_partition_entries));
+        error_found++;
+    }
+
+    if ((pgpt->sizeof_partition_entry) != (agpt->sizeof_partition_entry))
+    {
+        LOG_I("GPT:sizeof_partition_entry values don't match: "
+               "0x%x != 0x%x\n",
+                       (pgpt->sizeof_partition_entry),
+               (agpt->sizeof_partition_entry));
+        error_found++;
+    }
+
+    if ((pgpt->partition_entry_array_crc32) != (agpt->partition_entry_array_crc32))
+    {
+        LOG_I("GPT:partition_entry_array_crc32 values don't match: "
+               "0x%x != 0x%x\n",
+                       (pgpt->partition_entry_array_crc32),
+               (agpt->partition_entry_array_crc32));
+        error_found++;
+    }
+
+    if ((pgpt->alternate_lba) != lastlba)
+    {
+        LOG_I("GPT:Primary header thinks Alt. header is not at the end of the disk.\n");
+        LOG_I("GPT:%lld != %lld\n",
+            (uint64_t)(pgpt->alternate_lba),
+            (size_t)lastlba);
+        error_found++;
+    }
+
+    if ((agpt->my_lba) != lastlba)
+    {
+        LOG_I("GPT:Alternate GPT header not at the end of the disk.\n");
+        LOG_I("GPT:%lld != %lld\n",
+            (uint64_t)(agpt->my_lba),
+            (size_t)lastlba);
+        error_found++;
+    }
+
+    if (error_found)
+    {
+        LOG_I("GPT: Use GNU Parted to correct GPT errors.\n");        
+    }
+    return;
+}
+
+/**
+ * find_valid_gpt() - Search disk for valid GPT headers and PTEs
+ * @state: disk parsed partitions
+ * @gpt: GPT header ptr, filled on return.
+ * @ptes: PTEs ptr, filled on return.
+ *
+ * Description: Returns 1 if valid, 0 on error.
+ * If valid, returns pointers to newly allocated GPT header and PTEs.
+ * Validity depends on PMBR being valid (or being overridden by the
+ * 'gpt' kernel command line option) and finding either the Primary
+ * GPT header and PTEs valid, or the Alternate GPT header and PTEs
+ * valid.  If the Primary GPT header is not valid, the Alternate GPT header
+ * is not checked unless the 'gpt' kernel command line option is passed.
+ * This protects against devices which misreport their size, and forces
+ * the user to decide to use the Alternate GPT.
+ */
+static int find_valid_gpt(struct rt_mmcsd_card *card, gpt_header **gpt,
+              gpt_entry **ptes)
+{
+    int good_pgpt = 0, good_agpt = 0, good_pmbr = 0;
+    gpt_header *pgpt = RT_NULL, *agpt = RT_NULL;
+    gpt_entry *pptes = RT_NULL, *aptes = RT_NULL;
+    legacy_mbr *legacymbr;
+    size_t total_sectors = last_lba(card) + 1;
+    size_t lastlba;
+    int status = 0;
+
+    if (!ptes)
+    {
+        return 0;
+    }
+
+    lastlba = last_lba(card);
+    LOG_D("total_sectors:%d, lastlba:%d\n", total_sectors, lastlba);
+    if (!force_gpt)
+    {
+        /* This will be added to the EFI Spec. per Intel after v1.02. */
+        legacymbr = rt_malloc(512);
+        if (!legacymbr)
+        {
+            goto fail;
+        }
+
+        status = read_lba(card, 0, (uint8_t *)legacymbr, 1);
+        if (status)
+        {
+            LOG_I("status:%d\n", status);
+            goto fail;
+        }
+
+        good_pmbr = is_pmbr_valid(legacymbr, total_sectors);
+        rt_free(legacymbr);
+
+        if (!good_pmbr)
+        {
+            goto fail;
+        }
+
+        LOG_D("Device has a %s MBR\n",
+             good_pmbr == GPT_MBR_PROTECTIVE ?
+                        "protective" : "hybrid");
+    }
+
+    good_pgpt = is_gpt_valid(card, GPT_PRIMARY_PARTITION_TABLE_LBA,
+                 &pgpt, &pptes);
+    if (good_pgpt)
+    {
+        good_agpt = is_gpt_valid(card, (pgpt->alternate_lba), &agpt, &aptes);
+        if (!good_agpt && force_gpt)
+        {
+             good_agpt = is_gpt_valid(card, lastlba, &agpt, &aptes);
+        }
+
+        /* The obviously unsuccessful case */
+        if (!good_pgpt && !good_agpt)
+        {
+            goto fail;
+        }
+
+        compare_gpts(pgpt, agpt, lastlba);
+        // legacymbr = rt_malloc(512);
+        // if (!legacymbr)
+        // {
+        //     goto fail;
+        // }
+
+        // status = read_lba(card, 0, (uint8_t *)legacymbr, 1);
+        // if (status)
+        // {
+        //     LOG_I("status:%d\n", status);
+        //     goto fail;
+        // }
+        // rt_free(legacymbr);
+
+        /* The good cases */
+        if (good_pgpt)
+        {
+            *gpt  = pgpt;
+            *ptes = pptes;
+            rt_free(agpt);
+            rt_free(aptes);
+            if (!good_agpt)
+            {
+                LOG_D("Alternate GPT is invalid, using primary GPT.\n");
+            }
+            return 1;
+        }
+        else if (good_agpt)
+        {
+            *gpt  = agpt;
+            *ptes = aptes;
+            rt_free(pgpt);
+            rt_free(pptes);
+            LOG_D("Primary GPT is invalid, using alternate GPT.\n");
+                return 1;
+        }
+    }
+
+ fail:
+        rt_free(pgpt);
+        rt_free(agpt);
+        rt_free(pptes);
+        rt_free(aptes);
+        *gpt = RT_NULL;
+        *ptes = RT_NULL;
+        return 0;
+}
+static gpt_header *_gpt;
+static gpt_entry *_ptes;
+int check_gpt(struct rt_mmcsd_card *card)
+{
+    if (!find_valid_gpt(card, &_gpt, &_ptes) || !_gpt || !_ptes)
+    {
+        rt_free(_gpt);
+        rt_free(_ptes);
+        return 0;
+    }
+    return 1;
+}
+
+int get_partition_param(struct rt_mmcsd_card *card, struct dfs_partition *part, uint32_t pindex)
+{
+    if (!is_pte_valid(&_ptes[pindex], last_lba(card)))
+    {
+        return -1;
+    }
+    part->offset = (off_t)(_ptes[pindex].starting_lba);
+    part->size = (_ptes[pindex].ending_lba) - (_ptes[pindex].starting_lba) + 1ULL;
+
+    rt_kprintf("found part[%d], begin(sector): %d, end(sector):%d size: ",
+             pindex, _ptes[pindex].starting_lba, _ptes[pindex].ending_lba);
+    if ((part->size >> 11) == 0)
+        rt_kprintf("%d%s", part->size >> 1, "KB\n"); /* KB */
+    else
+    {
+        unsigned int part_size;
+        part_size = part->size >> 11;                /* MB */
+        if ((part_size >> 10) == 0)
+            rt_kprintf("%d.%d%s", part_size, (part->size >> 1) & 0x3FF, "MB\n");
+        else
+            rt_kprintf("%d.%d%s", part_size >> 10, part_size & 0x3FF, "GB\n");
+    }
+    return 0;
+}
+
+void gpt_free()
+{
+    rt_free(_ptes);
+    rt_free(_gpt);
+}

+ 3 - 2
components/drivers/sdio/mmc.c

@@ -193,10 +193,11 @@ static int mmc_parse_ext_csd(struct rt_mmcsd_card *card, rt_uint8_t *ext_csd)
   card->hs_max_data_rate = 52000000;
 
   card_capacity = *((rt_uint32_t *)&ext_csd[EXT_CSD_SEC_CNT]);
+  card->card_sec_cnt = card_capacity;
   card_capacity *= card->card_blksize;
   card_capacity >>= 10; /* unit:KB */
   card->card_capacity = card_capacity;
-  LOG_I("emmc card capacity %d KB.", card->card_capacity);
+  LOG_I("emmc card capacity %d KB, card sec count:%d.", card->card_capacity, card->card_sec_cnt);
 
   return 0;
 }
@@ -322,7 +323,7 @@ static int mmc_select_bus_width(struct rt_mmcsd_card *card, rt_uint8_t *ext_csd)
     * set by drivers.
     */
 
-     if (!(((host->flags & MMCSD_BUSWIDTH_8) &&
+    if (!(((host->flags & MMCSD_BUSWIDTH_8) &&
       ext_csd_bits[idx] == EXT_CSD_BUS_WIDTH_8) ||
          ((host->flags & MMCSD_BUSWIDTH_4) &&
       ext_csd_bits[idx] == EXT_CSD_BUS_WIDTH_4) ||

+ 2 - 1
components/drivers/sdio/sd.c

@@ -117,8 +117,9 @@ static rt_int32_t mmcsd_parse_csd(struct rt_mmcsd_card *card)
         csd->wr_blk_partial = GET_BITS(resp, 21, 1);
         csd->csd_crc = GET_BITS(resp, 1, 7);
 
-        card->card_blksize = 512;
+        card->card_blksize = 512;       
         card->card_capacity = (csd->c_size + 1) * 512;  /* unit:KB */
+        card->card_sec_cnt = card->card_capacity * 2;
         card->tacc_clks = 0;
         card->tacc_ns = 0;
         card->max_data_rate = tran_unit[csd->tran_speed&0x07] * tran_value[(csd->tran_speed&0x78)>>3];