1 /*
2 * Copyright (c) 2006-2025 RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2005-02-22 Bernard The first version.
9 * 2010-06-30 Bernard Optimize for RT-Thread RTOS
10 * 2011-03-12 Bernard fix the filesystem lookup issue.
11 * 2017-11-30 Bernard fix the filesystem_operation_table issue.
12 * 2017-12-05 Bernard fix the fs type search issue in mkfs.
13 * 2023-05-05 Bernard change to dfs v2.0
14 */
15
16 #include <dfs_fs.h>
17 #include <dfs_file.h>
18 #include <dfs_dentry.h>
19 #include <dfs_mnt.h>
20 #include "dfs_private.h"
21
22 #ifdef RT_USING_PAGECACHE
23 #include "dfs_pcache.h"
24 #endif
25
26 #define DBG_TAG "DFS.fs"
27 #define DBG_LVL DBG_INFO
28 #include <rtdbg.h>
29
30 static struct dfs_filesystem_type *file_systems = NULL;
31 extern rt_list_t _mnt_list;
32
33 /**
34 * @addtogroup group_fs_api
35 */
36 /*@{*/
37
38 /**
39 * @brief Find a filesystem type by name
40 *
41 * This function searches the global filesystem type list for a filesystem
42 * matching the given name. It returns a pointer to the pointer that holds
43 * the matching filesystem type (or the end-of-list pointer if not found).
44 *
45 * @param[in] name The name of the filesystem type to find
46 * @return struct dfs_filesystem_type** Pointer to the pointer containing
47 * the matching filesystem type, or the end-of-list pointer if not found
48 */
_find_filesystem(const char * name)49 static struct dfs_filesystem_type **_find_filesystem(const char *name)
50 {
51 struct dfs_filesystem_type **type;
52 for (type = &file_systems; *type; type = &(*type)->next)
53 {
54 if (strcmp((*type)->fs_ops->name, name) == 0)
55 break;
56 }
57
58 return type;
59 }
60
61 /**
62 * @brief Get the list of registered filesystem types
63 *
64 * This function returns a pointer to the head of the global filesystem type list.
65 *
66 * @return struct dfs_filesystem_type* Pointer to the head of the filesystem type list
67 */
dfs_filesystems(void)68 struct dfs_filesystem_type *dfs_filesystems(void)
69 {
70 return file_systems;
71 }
72
73 /**
74 * @brief Register a filesystem type
75 *
76 * This function registers a new filesystem type with the global filesystem type list.
77 *
78 * @param[in] fs Pointer to the filesystem type to register
79 * @return int 0 on success, or a negative error code on failure
80 */
dfs_register(struct dfs_filesystem_type * fs)81 int dfs_register(struct dfs_filesystem_type *fs)
82 {
83 int ret = 0;
84 struct dfs_filesystem_type **type = _find_filesystem(fs->fs_ops->name);
85
86 LOG_D("register %s file system.", fs->fs_ops->name);
87
88 if (*type)
89 {
90 ret = -EBUSY;
91 }
92 else
93 {
94 *type = fs;
95 }
96
97 return ret;
98 }
99
100 /**
101 * @brief Unregister a filesystem type
102 *
103 * This function unregisters a filesystem type from the global filesystem type list.
104 *
105 * @param[in] fs Pointer to the filesystem type to unregister
106 * @return int 0 on success, or a negative error code on failure
107 */
dfs_unregister(struct dfs_filesystem_type * fs)108 int dfs_unregister(struct dfs_filesystem_type *fs)
109 {
110 int ret = 0;
111 struct dfs_filesystem_type **type;
112
113 if (fs)
114 {
115 LOG_D("unregister %s file system.", fs->fs_ops->name);
116
117 for (type = &file_systems; *type; type = &(*type)->next)
118 {
119 if (strcmp((*type)->fs_ops->name, fs->fs_ops->name) == 0)
120 {
121 *type = (*type)->next;
122 break;
123 }
124 }
125
126 if (!*type) ret = -EINVAL;
127 }
128
129 return ret;
130 }
131
132 #define REMNT_UNSUPP_FLAGS (~(MS_REMOUNT | MS_RMT_MASK)) /* remount unsupported flags */
133
134 /**
135 * @brief Remount a filesystem
136 *
137 * This function remounts a filesystem at the specified path with the given flags.
138 *
139 * @param[in] path The path of the filesystem to remount
140 * @param[in] flags The remount flags (see MS_REMOUNT and MS_RMT_MASK)
141 * @param[in] data Pointer to additional data required for remounting
142 * @return int 0 on success, or a negative error code on failure
143 */
dfs_remount(const char * path,rt_ubase_t flags,void * data)144 int dfs_remount(const char *path, rt_ubase_t flags, void *data)
145 {
146 int rc = 0;
147 char *fullpath = RT_NULL;
148 struct dfs_mnt *mnt = RT_NULL;
149
150 if (flags & REMNT_UNSUPP_FLAGS)
151 {
152 return -EINVAL;
153 }
154
155 fullpath = dfs_normalize_path(RT_NULL, path);
156 if (!fullpath)
157 {
158 rc = -ENOENT;
159 }
160 else
161 {
162 DLOG(msg, "dfs", "mnt", DLOG_MSG, "mnt = dfs_mnt_lookup(%s)", fullpath);
163 mnt = dfs_mnt_lookup(fullpath);
164 if (mnt)
165 {
166 dfs_lock();
167 dfs_mnt_setflags(mnt, flags);
168 dfs_unlock();
169 }
170 else
171 {
172 struct stat buf = {0};
173 if (dfs_file_stat(fullpath, &buf) == 0 && S_ISBLK(buf.st_mode))
174 {
175 /* path was not already mounted on target */
176 rc = -EINVAL;
177 }
178 else
179 {
180 /* path is not a directory */
181 rc = -ENOTDIR;
182 }
183 }
184 }
185
186 return rc;
187 }
188
189 /*
190 * parent(mount path)
191 * mnt_parent <- - - - - - - +
192 * | |
193 * |- mnt_child <- - - - - -+ (1 refcount)
194 * | |
195 * |- parent - - + (1 refcount)
196 */
197
198 /**
199 * @brief Mount a filesystem at the specified path
200 *
201 * This function mounts a filesystem of the specified type at the given path with optional device.
202 * It handles both root filesystem mounting and regular filesystem mounting scenarios.
203 *
204 * @param[in] device_name The name of the device to mount (optional)
205 * @param[in] path The path of the mount point
206 * @param[in] filesystemtype The type of the filesystem to mount
207 * @param[in] rwflag The read/write flags (see MS_RDONLY, MS_RDWR, etc.)
208 * @param[in] data Pointer to additional data required for mounting
209 *
210 * @return int RT_EOK on success, negative error code on failure:
211 * - EPERM: Path normalization failed or mount operation failed
212 * - ENODEV: Filesystem type not found or device not available
213 * - ENOMEM: Memory allocation failure
214 * - EIO: Filesystem lacks mount method
215 * - ENOTDIR: Mount point doesn't exist
216 * - EEXIST: Mount point already mounted
217 *
218 * @note Special handling for root filesystem ("/")
219 * @note Automatic reference counting management for mount points
220 */
dfs_mount(const char * device_name,const char * path,const char * filesystemtype,unsigned long rwflag,const void * data)221 int dfs_mount(const char *device_name,
222 const char *path,
223 const char *filesystemtype,
224 unsigned long rwflag,
225 const void *data)
226 {
227 int ret = RT_EOK;
228 char *fullpath = RT_NULL;
229 rt_device_t dev_id = RT_NULL;
230 struct dfs_mnt *mnt_parent = RT_NULL, *mnt_child = RT_NULL;
231 struct dfs_dentry *mntpoint_dentry = RT_NULL;
232 struct dfs_filesystem_type *type = *_find_filesystem(filesystemtype);
233
234 /* normalize the mount path */
235 if (type)
236 {
237 fullpath = dfs_normalize_path(RT_NULL, path);
238 if (!fullpath)
239 {
240 rt_set_errno(EPERM);
241 ret = -1;
242 }
243 }
244 else
245 {
246 rt_set_errno(ENODEV);
247 ret = -1;
248 }
249
250 /* Main mounting procedure */
251 if (fullpath)
252 {
253 DLOG(note, "mnt", "mount %s(%s) on path: %s", device_name, filesystemtype, fullpath);
254
255 /* open specific device */
256 if (device_name) dev_id = rt_device_find(device_name);
257
258 /* Check device requirements */
259 if (!(type->fs_ops->flags & FS_NEED_DEVICE) ||
260 ((type->fs_ops->flags & FS_NEED_DEVICE) && dev_id))
261 {
262 DLOG(msg, "dfs", "mnt", DLOG_MSG, "mnt_parent = dfs_mnt_lookup(%s)", fullpath);
263 mnt_parent = dfs_mnt_lookup(fullpath); /* Find parent mount point */
264
265 /* Handle root filesystem mounting */
266 if ((!mnt_parent && (strcmp(fullpath, "/") == 0 || strcmp(fullpath, "/dev") == 0))
267 || (mnt_parent && strcmp(fullpath, "/") == 0 && strcmp(mnt_parent->fullpath, fullpath) != 0))
268 {
269 LOG_D("no mnt found @ mount point %s, should be root.", fullpath);
270 DLOG(msg, "mnt", "dfs", DLOG_MSG_RET, "no mnt");
271
272 /* it's the root file system */
273 /* the mount point dentry is the same as root dentry. */
274 /* Create root filesystem mount point */
275 DLOG(msg, "dfs", "mnt", DLOG_MSG, "mnt_parent = dfs_mnt_create(path)");
276 mnt_parent = dfs_mnt_create(fullpath); /* mnt->ref_count should be 1. */
277 if (mnt_parent)
278 {
279 DLOG(msg, "mnt", "dfs", DLOG_MSG_RET, "return mnt, ref_count=1");
280
281 mnt_parent->fs_ops = type->fs_ops;
282 mnt_parent->dev_id = dev_id;
283 if (mnt_parent->fs_ops->mount)
284 {
285 DLOG(msg, "dfs", type->fs_ops->name, DLOG_MSG, "fs_ops->mount(mnt_parent, rwflag, data)");
286 ret = mnt_parent->fs_ops->mount(mnt_parent, rwflag, data);
287 if (ret == RT_EOK)
288 {
289 DLOG(msg, type->fs_ops->name, "dfs", DLOG_MSG_RET, "mount OK, ret root_dentry");
290
291 /* Mark as mounted and insert into mount table */
292 mnt_child = mnt_parent;
293 mnt_child->flags |= MNT_IS_MOUNTED;
294
295 DLOG(note_right, "mnt", "mount sucessfully");
296 DLOG(msg, "dfs", "mnt", DLOG_MSG, "dfs_mnt_insert(, mnt_child)");
297 dfs_mnt_insert(RT_NULL, mnt_child);
298
299 /* unref it, because the ref_count = 1 when create */
300 DLOG(msg, "dfs", "mnt", DLOG_MSG, "dfs_mnt_unref(mnt_parent)");
301 dfs_mnt_unref(mnt_parent);
302
303 /*
304 * About root mnt:
305 * There are two ref_count:
306 * 1. the gobal root reference.
307 * 1. the mnt->parent reference.
308 */
309 }
310 else
311 {
312 LOG_W("mount %s failed with file system type: %s", fullpath, type->fs_ops->name);
313 DLOG(msg, "dfs", "mnt", DLOG_MSG, "dfs_mnt_destroy(mnt_parent)");
314 dfs_mnt_destroy(mnt_parent);
315 mnt_parent = RT_NULL;
316 rt_set_errno(EPERM);
317 ret = -1;
318 }
319 }
320 else
321 {
322 LOG_W("no mount method on file system type: %s", type->fs_ops->name);
323 DLOG(msg, "dfs", "mnt", DLOG_MSG, "dfs_mnt_destroy(mnt_parent), no mount method");
324 dfs_mnt_destroy(mnt_parent);
325 mnt_parent = RT_NULL;
326 rt_set_errno(EIO);
327 ret = -1;
328 }
329 }
330 else
331 {
332 LOG_E("create a mnt point failed.");
333 rt_set_errno(ENOMEM);
334 ret = -1;
335 }
336 }
337 else if (mnt_parent && (strcmp(mnt_parent->fullpath, fullpath) != 0)) /* Handle regular filesystem mounting */
338 {
339 DLOG(msg, "dfs", "dentry", DLOG_MSG, "mntpoint_dentry = dfs_dentry_lookup(mnt_parent, %s, 0)", fullpath);
340 mntpoint_dentry = dfs_dentry_lookup(mnt_parent, fullpath, 0); /* Find mount point directory entry */
341 if (mntpoint_dentry)
342 {
343 DLOG(msg, "dentry", "dfs", DLOG_MSG_RET, "dentry exist");
344 DLOG(msg, "dfs", "mnt", DLOG_MSG, "mnt_child = dfs_mnt_create(path)");
345 mnt_child = dfs_mnt_create(fullpath); /* Create child mount point */
346 if (mnt_child)
347 {
348 LOG_D("create mnt point %p", mnt_child);
349
350 mnt_child->fs_ops = type->fs_ops;
351 mnt_child->dev_id = dev_id;
352
353 if (mnt_child->fs_ops->mount)
354 {
355 DLOG(msg, "dfs", type->fs_ops->name, DLOG_MSG, "root_dentry = fs_ops->mount(mnt_child, rwflag, data)");
356 ret = mnt_child->fs_ops->mount(mnt_child, rwflag, data);
357 if (ret == RT_EOK)
358 {
359 mnt_child->flags |= MNT_IS_MOUNTED;
360
361 LOG_D("mount %s sucessfully", fullpath);
362 DLOG(msg, mnt_child->fs_ops->name, "dfs", DLOG_MSG_RET, "mount OK");
363
364 DLOG(msg, "dfs", "mnt", DLOG_MSG, "dfs_mnt_insert(mnt_parent, mnt_child)");
365 dfs_mnt_insert(mnt_parent, mnt_child);
366
367 /* unref it, because the ref_count = 1 when create */
368 DLOG(msg, "dfs", "mnt", DLOG_MSG, "dfs_mnt_unref(mnt_child)");
369 dfs_mnt_unref(mnt_child);
370 }
371 else
372 {
373 LOG_W("mount %s failed with file system type: %s", fullpath, type->fs_ops->name);
374 DLOG(msg, mnt_child->fs_ops->name, "dfs", DLOG_MSG_RET, "mount failed");
375 dfs_mnt_destroy(mnt_child);
376 rt_set_errno(EPERM);
377 ret = -1;
378 }
379 }
380 else
381 {
382 LOG_W("no mount method on file system type: %s", type->fs_ops->name);
383 dfs_mnt_destroy(mnt_child);
384 rt_set_errno(EIO);
385 ret = -1;
386 }
387 }
388 else
389 {
390 LOG_E("create a mnt point failed.");
391 rt_set_errno(ENOMEM);
392 ret = -1;
393 }
394 dfs_dentry_unref(mntpoint_dentry);
395 }
396 else
397 {
398 LOG_W("no mount point (%s) in file system: %s", fullpath, mnt_parent->fullpath);
399 rt_set_errno(ENOTDIR);
400 ret = -1;
401 }
402 }
403 else
404 {
405 LOG_E("mount point (%s) already mounted!", fullpath);
406 rt_set_errno(EEXIST);
407 ret = -1;
408 }
409 }
410 else
411 {
412 LOG_E("No device found for this file system.");
413 rt_set_errno(ENODEV);
414 ret = -1;
415 }
416 rt_free(fullpath);
417 }
418
419 return ret;
420 }
421
422 /**
423 * @brief Unmount a filesystem from the specified path
424 *
425 * This function unmounts a filesystem from the given path. It performs the following operations:
426 * 1. Normalizes the target path
427 * 2. Looks up the mount point
428 * 3. Checks if the filesystem can be safely unmounted
429 * 4. Performs cleanup operations if unmounting is successful
430 *
431 * @param[in] specialfile The path of the filesystem to unmount
432 * @param[in] flags Unmount flags (MNT_FORCE for forced unmount)
433 *
434 * @return int RT_EOK on success, negative error code on failure:
435 * - EBUSY: Filesystem is busy (in use or has child mounts)
436 * - EINVAL: Path is not a mount point
437 * - ENOTDIR: Invalid path format
438 *
439 * @note Forced unmount (MNT_FORCE) can unmount even if reference count > 1
440 * @note Automatically handles page cache cleanup if RT_USING_PAGECACHE is enabled
441 * @note The function will fail if:
442 * - The mount point is locked (MNT_IS_LOCKED)
443 * - There are child mounts present
444 * - Reference count > 1 and MNT_FORCE not specified
445 */
dfs_umount(const char * specialfile,int flags)446 int dfs_umount(const char *specialfile, int flags)
447 {
448 int ret = -1;
449 char *fullpath = RT_NULL;
450 struct dfs_mnt *mnt = RT_NULL;
451
452 fullpath = dfs_normalize_path(NULL, specialfile);
453 if (fullpath)
454 {
455 DLOG(msg, "dfs", "mnt", DLOG_MSG, "mnt = dfs_mnt_lookup(%s)", fullpath);
456 mnt = dfs_mnt_lookup(fullpath);
457 if (mnt)
458 {
459 if (strcmp(mnt->fullpath, fullpath) == 0)
460 {
461 /* is the mount point */
462 rt_base_t ref_count = rt_atomic_load(&(mnt->ref_count));
463
464 if (!(mnt->flags & MNT_IS_LOCKED) && rt_list_isempty(&mnt->child) && (ref_count == 1 || (flags & MNT_FORCE)))
465 {
466 #ifdef RT_USING_PAGECACHE
467 dfs_pcache_unmount(mnt);
468 #endif
469 /* destroy this mount point */
470 DLOG(msg, "dfs", "mnt", DLOG_MSG, "dfs_mnt_destroy(mnt)");
471 ret = dfs_mnt_destroy(mnt);
472 }
473 else
474 {
475 LOG_I("the file system is busy!");
476 ret = -EBUSY;
477 }
478 }
479 else
480 {
481 LOG_I("the path:%s is not a mountpoint!", fullpath);
482 ret = -EINVAL;
483 }
484 }
485 else
486 {
487 LOG_I("no filesystem found.");
488 }
489 rt_free(fullpath);
490 }
491 else
492 {
493 rt_set_errno(-ENOTDIR);
494 }
495
496 return ret;
497 }
498
499 /* for compatibility */
dfs_unmount(const char * specialfile)500 int dfs_unmount(const char *specialfile)
501 {
502 return dfs_umount(specialfile, 0);
503 }
504
505 /**
506 * @brief Check if a mount point is mounted
507 *
508 * This function checks if the given mount point is mounted. It returns 0 if the mount point is mounted,
509 * and -1 otherwise.
510 *
511 * @param[in] mnt The mount point to check
512 *
513 * @return int 0 if mounted, -1 otherwise
514 */
dfs_is_mounted(struct dfs_mnt * mnt)515 int dfs_is_mounted(struct dfs_mnt *mnt)
516 {
517 int ret = 0;
518
519 if (mnt && !(mnt->flags & MNT_IS_MOUNTED))
520 {
521 ret = -1;
522 }
523
524 return ret;
525 }
526
527 /**
528 * @brief Create a filesystem on the specified device
529 *
530 * This function creates a filesystem of the specified type on the given device.
531 * It performs the following operations:
532 * 1. Looks up the filesystem type
533 * 2. Validates device requirements
534 * 3. Calls the filesystem-specific mkfs operation
535 * 4. Handles page cache cleanup if successful (when RT_USING_PAGECACHE is enabled)
536 *
537 * @param[in] fs_name Name of the filesystem type to create (e.g., "elm", "romfs")
538 * @param[in] device_name Name of the device to create filesystem on (optional)
539 *
540 * @return int RT_EOK on success, negative error code on failure:
541 * - RT_ERROR: General error
542 * - ENODEV: Filesystem type not found or device not available
543 *
544 * @note For filesystems that don't require a device (FS_NEED_DEVICE not set),
545 * the device_name parameter can be NULL
546 * @note Automatically unmounts any existing filesystem on the device
547 * when RT_USING_PAGECACHE is enabled
548 * @note The function will fail if:
549 * - The filesystem type is not found
550 * - Device is required but not found
551 * - The filesystem doesn't implement mkfs operation
552 */
dfs_mkfs(const char * fs_name,const char * device_name)553 int dfs_mkfs(const char *fs_name, const char *device_name)
554 {
555 rt_device_t dev_id = NULL;
556 struct dfs_filesystem_type *type;
557 int ret = -RT_ERROR;
558
559 type = *_find_filesystem(fs_name);
560 if (!type)
561 {
562 rt_kprintf("no file system: %s found!\n", fs_name);
563 return ret;
564 }
565 else
566 {
567 if (type->fs_ops->flags & FS_NEED_DEVICE)
568 {
569 /* check device name, and it should not be NULL */
570 if (device_name != NULL)
571 dev_id = rt_device_find(device_name);
572
573 if (dev_id == NULL)
574 {
575 rt_set_errno(-ENODEV);
576 rt_kprintf("Device (%s) was not found", device_name);
577 return ret;
578 }
579 }
580 else
581 {
582 dev_id = RT_NULL;
583 }
584 }
585
586 if (type->fs_ops->mkfs)
587 {
588 ret = type->fs_ops->mkfs(dev_id, type->fs_ops->name);
589 #ifdef RT_USING_PAGECACHE
590 if (ret == RT_EOK)
591 {
592 struct dfs_mnt *mnt = RT_NULL;
593
594 mnt = dfs_mnt_dev_lookup(dev_id);
595 if (mnt)
596 {
597 dfs_pcache_unmount(mnt);
598 }
599 }
600 #endif
601 }
602
603 return ret;
604 }
605
606 /**
607 * @brief Get filesystem statistics for the specified path
608 *
609 * This function retrieves filesystem statistics (like total/available space)
610 * for the filesystem containing the given path. It performs the following operations:
611 * 1. Normalizes the input path
612 * 2. Looks up the mount point for the path
613 * 3. Calls the filesystem-specific statfs operation if available
614 *
615 * @param[in] path The path to query filesystem statistics for
616 * @param[out] buffer Pointer to statfs structure to store the results
617 *
618 * @return int RT_EOK on success, negative error code on failure:
619 * - RT_ERROR: General error (invalid path or filesystem not found)
620 *
621 * @note The function will fail if:
622 * - The path cannot be normalized
623 * - No mount point is found for the path
624 * - The filesystem doesn't implement statfs operation
625 * - The filesystem is not currently mounted
626 * @note The buffer parameter must point to valid memory allocated by the caller
627 */
dfs_statfs(const char * path,struct statfs * buffer)628 int dfs_statfs(const char *path, struct statfs *buffer)
629 {
630 struct dfs_mnt *mnt;
631 char *fullpath;
632 int ret = -RT_ERROR;
633
634 fullpath = dfs_normalize_path(NULL, path);
635 if (!fullpath)
636 {
637 return ret;
638 }
639
640 DLOG(msg, "dfs_file", "mnt", DLOG_MSG, "dfs_mnt_lookup(%s)", fullpath);
641 mnt = dfs_mnt_lookup(fullpath);
642 if (mnt)
643 {
644 if (mnt->fs_ops->statfs)
645 {
646 if (dfs_is_mounted(mnt) == 0)
647 {
648 ret = mnt->fs_ops->statfs(mnt, buffer);
649 }
650 }
651 }
652
653 return ret;
654 }
655
656 /**
657 * this function will return the mounted path for specified device.
658 *
659 * @param[in] device the device object which is mounted.
660 *
661 * @return the mounted path or NULL if none device mounted.
662 */
dfs_filesystem_get_mounted_path(struct rt_device * device)663 const char *dfs_filesystem_get_mounted_path(struct rt_device *device)
664 {
665 const char *path = NULL;
666
667 return path;
668 }
669
670 /**
671 * this function will fetch the partition table on specified buffer.
672 *
673 * @param[out] part the returned partition structure.
674 * @param[in] buf the buffer contains partition table.
675 * @param[in] pindex the index of partition table to fetch.
676 *
677 * @return RT_EOK on successful or -RT_ERROR on failed.
678 */
dfs_filesystem_get_partition(struct dfs_partition * part,uint8_t * buf,uint32_t pindex)679 int dfs_filesystem_get_partition(struct dfs_partition *part,
680 uint8_t *buf,
681 uint32_t pindex)
682 {
683 #define DPT_ADDRESS 0x1be /* device partition offset in Boot Sector */
684 #define DPT_ITEM_SIZE 16 /* partition item size */
685
686 uint8_t *dpt;
687 uint8_t type;
688
689 RT_ASSERT(part != NULL);
690 RT_ASSERT(buf != NULL);
691
692 dpt = buf + DPT_ADDRESS + pindex * DPT_ITEM_SIZE;
693
694 /* check if it is a valid partition table */
695 if ((*dpt != 0x80) && (*dpt != 0x00))
696 return -EIO;
697
698 /* get partition type */
699 type = *(dpt + 4);
700 if (type == 0)
701 return -EIO;
702
703 /* set partition information
704 * size is the number of 512-Byte */
705 part->type = type;
706 part->offset = *(dpt + 8) | *(dpt + 9) << 8 | *(dpt + 10) << 16 | *(dpt + 11) << 24;
707 part->size = *(dpt + 12) | *(dpt + 13) << 8 | *(dpt + 14) << 16 | *(dpt + 15) << 24;
708
709 rt_kprintf("found part[%d], begin: %ld, size: ",
710 pindex, part->offset * 512);
711 if ((part->size >> 11) == 0)
712 rt_kprintf("%ld%s", part->size >> 1, "KB\n"); /* KB */
713 else
714 {
715 unsigned int part_size;
716 part_size = part->size >> 11; /* MB */
717 if ((part_size >> 10) == 0)
718 rt_kprintf("%d.%ld%s", part_size, (part->size >> 1) & 0x3FF, "MB\n");
719 else
720 rt_kprintf("%d.%d%s", part_size >> 10, part_size & 0x3FF, "GB\n");
721 }
722
723 return RT_EOK;
724 }
725
726 /* @} */