1 /*
2  * Copyright (c) 2006-2023, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2023-02-25     GuEe-GUI     the first version
9  */
10 
11 #define DBG_TAG "blk.part"
12 #define DBG_LVL DBG_INFO
13 #include <rtdbg.h>
14 
15 #include "blk_partition.h"
16 
17 static rt_err_t (*partition_list[])(struct rt_blk_disk *) =
18 {
19 #ifdef RT_BLK_PARTITION_EFI
20     efi_partition,
21 #endif
22 #ifdef RT_BLK_PARTITION_DFS
23     dfs_partition,
24 #endif
25 };
26 
blk_put_partition(struct rt_blk_disk * disk,const char * type,rt_size_t start,rt_size_t count,int partno)27 rt_err_t blk_put_partition(struct rt_blk_disk *disk, const char *type,
28         rt_size_t start, rt_size_t count, int partno)
29 {
30     rt_err_t err;
31 
32     struct rt_blk_device *blk = rt_calloc(1, sizeof(*blk));
33 
34     if (type && rt_strcmp(type, "dfs"))
35     {
36         rt_uint32_t ssz = rt_blk_disk_get_logical_block_size(disk);
37 
38         rt_kprintf("found part[%u], begin: %lu, size: ", partno, start * ssz);
39 
40         if ((count >> 11) == 0)
41         {
42             rt_kprintf("%u%cB\n", count >> 1, 'K'); /* KB */
43         }
44         else
45         {
46             rt_uint32_t size_mb = count >> 11;      /* MB */
47 
48             if ((size_mb >> 10) == 0)
49             {
50                 rt_kprintf("%u.%u%cB\n", size_mb, (count >> 1) & 0x3ff, 'M');
51             }
52             else
53             {
54                 rt_kprintf("%u.%u%cB\n", size_mb >> 10, size_mb & 0x3ff, 'G');
55             }
56         }
57     }
58 
59     if (!blk)
60     {
61         err = -RT_ENOMEM;
62         goto _fail;
63     }
64 
65     err = blk_dev_initialize(blk);
66 
67     if (err)
68     {
69         goto _fail;
70     }
71 
72     blk->partno = partno;
73     blk->sector_start = start;
74     blk->sector_count = count;
75 
76     blk->partition.offset = start;
77     blk->partition.size = count;
78     blk->partition.lock = &disk->usr_lock;
79 
80     err = disk_add_blk_dev(disk, blk);
81 
82     if (err)
83     {
84         goto _fail;
85     }
86 
87     ++disk->partitions;
88 
89     return RT_EOK;
90 
91 _fail:
92     LOG_E("%s: Put partition.%s[%u] start = %lu count = %lu error = %s",
93             to_disk_name(disk), type, partno, start, count, rt_strerror(err));
94 
95     if (blk)
96     {
97         rt_free(blk);
98     }
99 
100     return err;
101 }
102 
rt_blk_disk_probe_partition(struct rt_blk_disk * disk)103 rt_err_t rt_blk_disk_probe_partition(struct rt_blk_disk *disk)
104 {
105     rt_err_t err = RT_EOK;
106 
107     if (!disk)
108     {
109         return -RT_EINVAL;
110     }
111 
112     LOG_D("%s: Probing disk partitions", to_disk_name(disk));
113 
114     if (disk->partitions)
115     {
116         return err;
117     }
118 
119     err = -RT_EEMPTY;
120 
121     if (disk->max_partitions == RT_BLK_PARTITION_NONE)
122     {
123         LOG_D("%s: Unsupported partitions", to_disk_name(disk));
124 
125         return err;
126     }
127 
128     for (int i = 0; i < RT_ARRAY_SIZE(partition_list); ++i)
129     {
130         rt_err_t part_err = partition_list[i](disk);
131 
132         if (part_err == -RT_ENOMEM)
133         {
134             err = part_err;
135             break;
136         }
137 
138         if (!part_err)
139         {
140             err = RT_EOK;
141             break;
142         }
143     }
144 
145     if ((err && err != -RT_ENOMEM) || disk->partitions == 0)
146     {
147         /* No partition found */
148         rt_size_t total_sectors = rt_blk_disk_get_capacity(disk);
149 
150         err = blk_put_partition(disk, RT_NULL, 0, total_sectors, 0);
151     }
152 
153     return err;
154 }
155