blob: 3d178df339379d045e7b4dbc0cebcae28d87e04c [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001/*
2 * initfs.c
3 *
4 * TFFS_mount TFFS_mkfs implementation.
5 * implementation file.
6 *
7 * Copyright (C) knightray@gmail.com
8 *
9 * SPDX-License-Identifier: GPL-2.0+
10 */
11#include "initfs.h"
12#include "debug.h"
13#include "tffs.h"
14#include "hai.h"
15#include "fat.h"
16#include "dir.h"
17
18#ifndef DBG_INITFS
19#undef DBG
20#define DBG nulldbg
21#endif
22
23int32
24TFFS_mount(
25 IN byte * dev,
26 OUT tffs_handle_t * phtffs)
27{
28 int32 ret;
29 tffs_t * tffs;
30 boot_sector_t * pbs = NULL;
31 tdev_handle_t hdev;
32 tdir_t * proot_dir = NULL;
33 tdir_t * pcur_dir = NULL;
34 uint32 rootdir_clus;
35 tfat_t * pfat = NULL;
36 tcache_t * pcache = NULL;
37
38 if (!dev || !phtffs)
39 return ERR_TFFS_INVALID_PARAM;
40
41 ret = TFFS_OK;
42 tffs = (tffs_t *)Malloc(sizeof(tffs_t));
43 Memset(tffs, 0, sizeof(tffs_t));
44 pbs = (boot_sector_t *)Malloc(sizeof(boot_sector_t));
45 Memset(pbs, 0, sizeof(boot_sector_t));
46
47 /* Marvell fixed: sizeof(boot_sector_t) is actualy 514 but only
48 due to sub-struct size alignment to 32-bit.
49 This only affects bs_sig offset, and it is unused
50 ASSERT(sizeof(boot_sector_t) == 512);
51 */
52
53 hdev = HAI_initdevice(dev, 512);
54 if (hdev == NULL) {
55 ret = ERR_TFFS_DEVICE_FAIL;
56 goto _release;
57 }
58 tffs->hdev = hdev;
59
60 if (HAI_readsector(hdev, 0, (ubyte *)pbs) != HAI_OK) {
61 ret = ERR_TFFS_DEVICE_FAIL;
62 goto _release;
63 }
64
65 if (!_validate_bs(pbs)) {
66 ret = ERR_TFFS_BAD_BOOTSECTOR;
67 goto _release;
68 }
69
70 tffs->pbs = pbs;
71
72 _parse_boot_sector(pbs, tffs);
73 DBG("tffs->fat_type:%d\n", tffs->fat_type);
74 DBG("tffs->sec_fat:%d\n", tffs->sec_fat);
75 DBG("tffs->sec_root_dir:%d\n", tffs->sec_root_dir);
76 DBG("tffs->sec_first_data:%d\n", tffs->sec_first_data);
77
78 /* Marvell fixed */
79#ifdef TFFS_FAT_CACHE
80 if ((pcache = cache_init(hdev, TFFS_FAT_CACHE, tffs->pbs->byts_per_sec)) == NULL) {
81 WARN("TFFS: cache is disable.\n");
82 pcache = cache_init(hdev, 0, tffs->pbs->byts_per_sec);
83 }
84 tffs->pfatcache = pcache;
85#endif
86 if ((pfat = fat_init(tffs)) == NULL) {
87 ret = ERR_TFFS_BAD_FAT;
88 goto _release;
89 }
90 tffs->pfat = pfat;
91
92 /* Marvell fixed: TFFS_FILE_CACHE instead of 32 hard-coded */
93 if ((pcache = cache_init(hdev, TFFS_FILE_CACHE, tffs->pbs->byts_per_sec)) == NULL) {
94 WARN("TFFS: cache is disable.\n");
95 pcache = cache_init(hdev, 0, tffs->pbs->byts_per_sec);
96 }
97 tffs->pcache = pcache;
98
99 rootdir_clus = tffs->fat_type == FT_FAT32 ? tffs->pbs->bh32.root_clus : ROOT_DIR_CLUS_FAT16;
100
101 if (dir_init_by_clus(tffs, rootdir_clus, &proot_dir) != DIR_OK ||
102 dir_init_by_clus(tffs, rootdir_clus, &pcur_dir) != DIR_OK) {
103 ret = ERR_TFFS_DEVICE_FAIL;
104 goto _release;
105 }
106
107 tffs->root_dir = proot_dir;
108 tffs->cur_dir = pcur_dir;
109
110 *phtffs = (tffs_handle_t)tffs;
111 INFO("tiny fat file system mount OK.\n");
112
113 return ret;
114
115_release:
116 if (pfat)
117 fat_destroy(pfat);
118 if (proot_dir)
119 dir_destroy(proot_dir);
120 if (pcur_dir)
121 dir_destroy(pcur_dir);
122 if (HAI_closedevice(tffs->hdev) != HAI_OK)
123 ret = ERR_TFFS_DEVICE_FAIL;
124 Free(pbs);
125 Free(tffs);
126
127 return ret;
128}
129
130int32
131TFFS_fs_flush(
132 IN tffs_handle_t htffs)
133{
134 tffs_t * ptffs;
135 int32 ret;
136
137 if (!htffs)
138 return ERR_TFFS_INVALID_PARAM;
139
140 ptffs = (tffs_t *)htffs;
141 ret = TFFS_OK;
142
143 if (ptffs->pfat)
144 fat_flush(ptffs->pfat);
145 if (ptffs->pcache)
146 ret = cache_flush(ptffs->pcache);
147#ifdef TFFS_FAT_CACHE
148 if (ptffs->pfatcache)
149 ret = cache_flush(ptffs->pfatcache);
150#endif
151 return ret;
152}
153
154int32
155TFFS_umount(
156 IN tffs_handle_t htffs)
157{
158 tffs_t * ptffs;
159 int32 ret;
160
161 if (!htffs)
162 return ERR_TFFS_INVALID_PARAM;
163
164 ptffs = (tffs_t *)htffs;
165 ret = TFFS_OK;
166
167 if (ptffs->pbs)
168 Free(ptffs->pbs);
169
170 if (ptffs->pfat)
171 fat_destroy(ptffs->pfat);
172
173 if (ptffs->root_dir)
174 dir_destroy(ptffs->root_dir);
175
176 if (ptffs->cur_dir)
177 dir_destroy(ptffs->cur_dir);
178
179 if (ptffs->pcache)
180 ret = cache_destroy(ptffs->pcache);
181 /* Marvell fixed */
182#ifdef TFFS_FAT_CACHE
183 if (ptffs->pfatcache)
184 ret = cache_destroy(ptffs->pfatcache);
185#endif
186 if (ret > 0 && (HAI_closedevice(ptffs->hdev) != HAI_OK))
187 ret = ERR_TFFS_DEVICE_FAIL;
188
189 Free(ptffs);
190
191 return ret;
192}
193
194int32
195_validate_bs(
196 IN boot_sector_t * pbs)
197{
198 INFO("=================Boot sector====================\n");
199 INFO("oem_name: %s\n", pbs->oem_name);
200 INFO("byts_per_sec: %d\n", pbs->byts_per_sec);
201 INFO("resvd_sec_cnt: %d\n", pbs->resvd_sec_cnt);
202 INFO("sec_per_clus: %d\n", pbs->sec_per_clus);
203 INFO("num_fats: %d\n", pbs->num_fats);
204 INFO("================================================\n");
205 /* Marvell fixed: check basic parameters are sane */
206 if ((pbs->byts_per_sec == 0) || (pbs->sec_per_clus == 0) ||
207 (pbs->num_fats < 1) || (pbs->num_fats > 2))
208 return FALSE;
209 return TRUE;
210}
211
212void
213_parse_boot_sector(
214 IN boot_sector_t * pbs,
215 OUT tffs_t * tffs)
216{
217 uint32 totsec;
218 uint32 count_of_clusters;
219 uint32 datasec;
220
221 tffs->root_dir_sectors = ((pbs->root_ent_cnt * 32) + (pbs->byts_per_sec - 1)) / pbs->byts_per_sec;
222
223 if (pbs->fatsz16 != 0) {
224 tffs->fatsz = pbs->fatsz16;
225 }
226 else {
227 tffs->fatsz = pbs->bh32.fatsz32;
228 }
229
230 if (pbs->tot_sec16 != 0) {
231 totsec = pbs->tot_sec16;
232 }
233 else {
234 totsec = pbs->tot_sec32;
235 }
236
237 datasec = totsec - (pbs->resvd_sec_cnt + (pbs->num_fats * tffs->fatsz) + tffs->root_dir_sectors);
238 count_of_clusters = datasec / pbs->sec_per_clus;
239 tffs->total_clusters = count_of_clusters;
240
241 DBG("count_of_clusters = %d\n", count_of_clusters);
242
243 //FIXME. I should find another to determine the fat type.
244 if (count_of_clusters < 4085) {
245 tffs->fat_type = FT_FAT12;
246 }
247 else if (count_of_clusters < 65525 && pbs->fatsz16 != 0){
248 tffs->fat_type = FT_FAT16;
249 }
250 else {
251 tffs->fat_type = FT_FAT32;
252 }
253
254 tffs->sec_fat = pbs->resvd_sec_cnt;
255 tffs->sec_root_dir = tffs->sec_fat + pbs->num_fats * tffs->fatsz;
256 tffs->sec_first_data = tffs->sec_root_dir + tffs->root_dir_sectors;
257 /* Marvell fixed */
258 tffs->num_fats = pbs->num_fats;
259}
260