File indexing completed on 2025-05-11 08:24:18
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038 #ifdef HAVE_CONFIG_H
0039 #include "config.h"
0040 #endif
0041
0042 #include <string.h>
0043 #include <stdlib.h>
0044 #include <stdio.h>
0045 #include <inttypes.h>
0046
0047 #include <rtems/rfs/rtems-rfs-data.h>
0048 #include <rtems/rfs/rtems-rfs-file-system.h>
0049 #include <rtems/rfs/rtems-rfs-inode.h>
0050 #include <rtems/rtems-rfs-format.h>
0051 #include <rtems/rfs/rtems-rfs-dir.h>
0052
0053
0054
0055
0056 #define GIGS(_g) (((uint64_t)(_g)) * 1024 * 1024)
0057
0058
0059
0060
0061 static int
0062 rtems_rfs_bits_per_block (rtems_rfs_file_system* fs)
0063 {
0064 return rtems_rfs_bitmap_numof_bits (rtems_rfs_fs_block_size (fs));
0065 }
0066
0067
0068
0069
0070
0071 static int
0072 rtems_rfs_rup_quotient (uint32_t dividend, uint32_t divisor)
0073 {
0074 if (dividend == 0)
0075 return 1;
0076 return ((dividend - 1) / divisor) + 1;
0077 }
0078
0079
0080
0081
0082
0083 static int
0084 rtems_rfs_inodes_from_percent (rtems_rfs_file_system* fs,
0085 int percentage)
0086 {
0087 int blocks;
0088 blocks = ((rtems_rfs_fs_blocks (fs) -
0089 RTEMS_RFS_SUPERBLOCK_SIZE) * percentage) / 100;
0090 blocks = rtems_rfs_rup_quotient (blocks, fs->group_count);
0091 return blocks * (rtems_rfs_fs_block_size (fs) / RTEMS_RFS_INODE_SIZE);
0092 }
0093
0094
0095
0096
0097 static int
0098 rtems_rfs_inode_overhead (rtems_rfs_file_system* fs)
0099 {
0100 int blocks;
0101 int bits_per_block;
0102 blocks = rtems_rfs_rup_quotient(fs->group_inodes * RTEMS_RFS_INODE_SIZE,
0103 rtems_rfs_fs_block_size (fs));
0104 bits_per_block = rtems_rfs_bits_per_block (fs);
0105
0106
0107
0108 if (bits_per_block > (rtems_rfs_fs_blocks (fs) - RTEMS_RFS_SUPERBLOCK_SIZE))
0109 bits_per_block = rtems_rfs_fs_blocks (fs) - RTEMS_RFS_SUPERBLOCK_SIZE;
0110 return ((blocks + 1) * 100 * 10) / bits_per_block;
0111 }
0112
0113 static bool
0114 rtems_rfs_check_config (rtems_rfs_file_system* fs,
0115 const rtems_rfs_format_config* config)
0116 {
0117 fs->block_size = config->block_size;
0118 if (!fs->block_size)
0119 {
0120 uint64_t total_size = rtems_rfs_fs_media_size (fs);
0121
0122 if (total_size >= GIGS (1))
0123 {
0124 uint32_t gigs = (total_size + GIGS (1)) / GIGS (1);
0125 int b;
0126 for (b = 31; b > 0; b--)
0127 if ((gigs & (1 << b)) != 0)
0128 break;
0129 fs->block_size = 1 << b;
0130 }
0131
0132 if (fs->block_size < 512)
0133 fs->block_size = 512;
0134
0135 if (fs->block_size > (4 * 1024))
0136 fs->block_size = (4 * 1024);
0137 }
0138
0139 if ((fs->block_size % rtems_rfs_fs_media_block_size (fs)) != 0)
0140 {
0141 printf ("block size (%zd) is not a multiple of media block size (%" PRId32 ")\n",
0142 fs->block_size, rtems_rfs_fs_media_block_size (fs));
0143 return false;
0144 }
0145
0146 fs->group_blocks = config->group_blocks;
0147 if (!fs->group_blocks)
0148 {
0149
0150
0151
0152
0153 fs->group_blocks = rtems_rfs_bitmap_numof_bits (fs->block_size);
0154 }
0155
0156 if (fs->group_blocks > rtems_rfs_bitmap_numof_bits (fs->block_size))
0157 {
0158 printf ("group block count is higher than bits in block\n");
0159 return false;
0160 }
0161
0162 fs->blocks = rtems_rfs_fs_media_size (fs) / fs->block_size;
0163
0164
0165
0166
0167
0168
0169 fs->group_count = rtems_rfs_rup_quotient (rtems_rfs_fs_blocks (fs),
0170 rtems_rfs_bits_per_block (fs));
0171
0172 fs->group_inodes = config->group_inodes;
0173 if (!fs->group_inodes)
0174 {
0175 int inode_overhead = RTEMS_RFS_INODE_OVERHEAD_PERCENTAGE;
0176
0177
0178
0179
0180 if (config->inode_overhead)
0181 inode_overhead = config->inode_overhead;
0182
0183 fs->group_inodes = rtems_rfs_inodes_from_percent (fs, inode_overhead);
0184 }
0185
0186
0187
0188
0189 fs->inodes_per_block = rtems_rfs_fs_block_size (fs) / RTEMS_RFS_INODE_SIZE;
0190 fs->group_inodes =
0191 rtems_rfs_rup_quotient (fs->group_inodes,
0192 fs->inodes_per_block) * fs->inodes_per_block;
0193
0194 if (fs->group_inodes > rtems_rfs_bitmap_numof_bits (fs->block_size))
0195 fs->group_inodes = rtems_rfs_bitmap_numof_bits (fs->block_size);
0196
0197 fs->max_name_length = config->max_name_length;
0198 if (!fs->max_name_length)
0199 {
0200 fs->max_name_length = 512;
0201 }
0202
0203 return true;
0204 }
0205
0206 static bool
0207 rtems_rfs_write_group (rtems_rfs_file_system* fs,
0208 int group,
0209 bool initialise_inodes,
0210 bool verbose)
0211 {
0212 rtems_rfs_buffer_handle handle;
0213 rtems_rfs_bitmap_control bitmap;
0214 rtems_rfs_buffer_block group_base;
0215 size_t group_size;
0216 int blocks;
0217 int b;
0218 int rc;
0219
0220 group_base = rtems_rfs_fs_block (fs, group, 0);
0221
0222 if (group_base > rtems_rfs_fs_blocks (fs))
0223 {
0224 printf ("rtems-rfs: write-group: group %d base beyond disk limit\n",
0225 group);
0226 return false;
0227 }
0228
0229 group_size = fs->group_blocks;
0230
0231
0232
0233
0234
0235
0236 if ((group_base + group_size) > rtems_rfs_fs_blocks (fs))
0237 group_size = rtems_rfs_fs_blocks (fs) - group_base;
0238
0239 if (verbose)
0240 printf ("\rrtems-rfs: format: group %3d: base = %" PRId32 ", size = %zd",
0241 group, group_base, group_size);
0242
0243
0244
0245
0246 rc = rtems_rfs_buffer_handle_open (fs, &handle);
0247 if (rc > 0)
0248 {
0249 printf ("\nrtems-rfs: write-group: handle open failed: %d: %s\n",
0250 rc, strerror (rc));
0251 return false;
0252 }
0253
0254 if (verbose)
0255 printf (", blocks");
0256
0257
0258
0259
0260 rc = rtems_rfs_bitmap_open (&bitmap, fs, &handle, group_size,
0261 group_base + RTEMS_RFS_GROUP_BLOCK_BITMAP_BLOCK);
0262 if (rc > 0)
0263 {
0264 rtems_rfs_buffer_handle_close (fs, &handle);
0265 printf ("\nrtems-rfs: write-group: group %3d: open block bitmap failed: %d: %s\n",
0266 group, rc, strerror (rc));
0267 return false;
0268 }
0269
0270
0271
0272
0273
0274 memset (rtems_rfs_buffer_data (&handle), 0xff, rtems_rfs_fs_block_size (fs));
0275
0276
0277
0278
0279 rc = rtems_rfs_bitmap_map_clear_all (&bitmap);
0280 if (rc > 0)
0281 {
0282 rtems_rfs_bitmap_close (&bitmap);
0283 rtems_rfs_buffer_handle_close (fs, &handle);
0284 printf ("\nrtems-rfs: write-group: group %3d: block bitmap clear all failed: %d: %s\n",
0285 group, rc, strerror (rc));
0286 return false;
0287 }
0288
0289
0290
0291
0292 rtems_rfs_bitmap_map_set (&bitmap, RTEMS_RFS_GROUP_BLOCK_BITMAP_BLOCK);
0293
0294
0295
0296
0297 rtems_rfs_bitmap_map_set (&bitmap, RTEMS_RFS_GROUP_INODE_BITMAP_BLOCK);
0298
0299
0300
0301
0302 blocks = rtems_rfs_rup_quotient (fs->group_inodes, fs->inodes_per_block);
0303
0304
0305
0306
0307 for (b = 0; b < blocks; b++)
0308 rtems_rfs_bitmap_map_set (&bitmap, b + RTEMS_RFS_GROUP_INODE_BLOCK);
0309
0310
0311
0312
0313 rc = rtems_rfs_bitmap_close (&bitmap);
0314 if (rc > 0)
0315 {
0316 rtems_rfs_buffer_handle_close (fs, &handle);
0317 printf ("\nrtems-rfs: write-group: group %3d: close block bitmap failed: %d: %s\n",
0318 group, rc, strerror (rc));
0319 return false;
0320 }
0321
0322 rtems_rfs_buffer_mark_dirty (&handle);
0323
0324 if (verbose)
0325 printf (", inodes");
0326
0327
0328
0329
0330 rc = rtems_rfs_bitmap_open (&bitmap, fs, &handle, group_size,
0331 group_base + RTEMS_RFS_GROUP_INODE_BITMAP_BLOCK);
0332 if (rc > 0)
0333 {
0334 rtems_rfs_buffer_handle_close (fs, &handle);
0335 printf ("\nrtems-rfs: write-group: group %3d: open inode bitmap failed: %d: %s\n",
0336 group, rc, strerror (rc));
0337 return false;
0338 }
0339
0340
0341
0342
0343
0344 memset (rtems_rfs_buffer_data (&handle), 0x00, rtems_rfs_fs_block_size (fs));
0345
0346
0347
0348
0349 rc = rtems_rfs_bitmap_map_clear_all (&bitmap);
0350 if (rc > 0)
0351 {
0352 rtems_rfs_bitmap_close (&bitmap);
0353 rtems_rfs_buffer_handle_close (fs, &handle);
0354 printf ("\nrtems-rfs: write-group: group %3d: inode bitmap" \
0355 " clear all failed: %d: %s\n", group, rc, strerror (rc));
0356 return false;
0357 }
0358
0359
0360
0361
0362 rc = rtems_rfs_bitmap_close (&bitmap);
0363 if (rc > 0)
0364 {
0365 rtems_rfs_buffer_handle_close (fs, &handle);
0366 printf ("\nrtems-rfs: write-group: group %3d: close inode" \
0367 " bitmap failed: %d: %s\n", group, rc, strerror (rc));
0368 return false;
0369 }
0370
0371 rtems_rfs_buffer_mark_dirty (&handle);
0372
0373
0374
0375
0376 if (initialise_inodes)
0377 {
0378 for (b = 0; b < blocks; b++)
0379 {
0380 rc = rtems_rfs_buffer_handle_request (fs, &handle,
0381 group_base + b + RTEMS_RFS_GROUP_INODE_BLOCK,
0382 false);
0383 if (rc > 0)
0384 {
0385 rtems_rfs_buffer_handle_close (fs, &handle);
0386 printf ("\nrtems-rfs: write-group: group %3d: block %" PRId32 " request failed: %d: %s\n",
0387 group, group_base + b + RTEMS_RFS_GROUP_INODE_BLOCK,
0388 rc, strerror (rc));
0389 return false;
0390 }
0391
0392
0393
0394
0395
0396 memset (rtems_rfs_buffer_data (&handle), 0xff, rtems_rfs_fs_block_size (fs));
0397
0398 rtems_rfs_buffer_mark_dirty (&handle);
0399 }
0400 }
0401
0402 rc = rtems_rfs_buffer_handle_close (fs, &handle);
0403 if (rc > 0)
0404 {
0405 printf ("\nrtems-rfs: write-group: buffer handle close failed: %d: %s\n",
0406 rc, strerror (rc));
0407 return false;
0408 }
0409
0410 return true;
0411 }
0412
0413 static bool
0414 rtems_rfs_write_superblock (rtems_rfs_file_system* fs)
0415 {
0416 rtems_rfs_buffer_handle handle;
0417 uint8_t* sb;
0418 int rc;
0419
0420 rc = rtems_rfs_buffer_handle_open (fs, &handle);
0421 if (rc > 0)
0422 {
0423 printf ("rtems-rfs: write-superblock: handle open failed: %d: %s\n",
0424 rc, strerror (rc));
0425 return false;
0426 }
0427
0428 rc = rtems_rfs_buffer_handle_request (fs, &handle, 0, false);
0429 if (rc > 0)
0430 {
0431 rtems_rfs_buffer_handle_close (fs, &handle);
0432 printf ("rtems-rfs: write-superblock: request failed: %d: %s\n",
0433 rc, strerror (rc));
0434 return false;
0435 }
0436
0437 sb = rtems_rfs_buffer_data (&handle);
0438
0439 #define write_sb(_o, _d) rtems_rfs_write_u32(sb + (_o), _d)
0440
0441 memset (sb, 0xff, rtems_rfs_fs_block_size (fs));
0442
0443 write_sb (RTEMS_RFS_SB_OFFSET_MAGIC, RTEMS_RFS_SB_MAGIC);
0444 write_sb (RTEMS_RFS_SB_OFFSET_VERSION, RTEMS_RFS_VERSION);
0445 write_sb (RTEMS_RFS_SB_OFFSET_BLOCKS, rtems_rfs_fs_blocks (fs));
0446 write_sb (RTEMS_RFS_SB_OFFSET_BLOCK_SIZE, rtems_rfs_fs_block_size (fs));
0447 write_sb (RTEMS_RFS_SB_OFFSET_BAD_BLOCKS, fs->bad_blocks);
0448 write_sb (RTEMS_RFS_SB_OFFSET_MAX_NAME_LENGTH, fs->max_name_length);
0449 write_sb (RTEMS_RFS_SB_OFFSET_GROUPS, fs->group_count);
0450 write_sb (RTEMS_RFS_SB_OFFSET_GROUP_BLOCKS, fs->group_blocks);
0451 write_sb (RTEMS_RFS_SB_OFFSET_GROUP_INODES, fs->group_inodes);
0452 write_sb (RTEMS_RFS_SB_OFFSET_INODE_SIZE, RTEMS_RFS_INODE_SIZE);
0453
0454 rtems_rfs_buffer_mark_dirty (&handle);
0455
0456 rc = rtems_rfs_buffer_handle_release (fs, &handle);
0457 if (rc > 0)
0458 {
0459 rtems_rfs_buffer_handle_close (fs, &handle);
0460 printf ("rtems-rfs: write-superblock: buffer release failed: %d: %s\n",
0461 rc, strerror (rc));
0462 return false;
0463 }
0464
0465 rc = rtems_rfs_buffer_handle_close (fs, &handle);
0466 if (rc > 0)
0467 {
0468 printf ("rtems-rfs: write-superblock: buffer handle close failed: %d: %s\n",
0469 rc, strerror (rc));
0470 return false;
0471 }
0472
0473 return true;
0474 }
0475
0476 static int
0477 rtems_rfs_write_root_dir (const char* name)
0478 {
0479 rtems_rfs_file_system* fs;
0480 rtems_rfs_inode_handle inode;
0481 rtems_rfs_ino ino;
0482 int rc;
0483
0484
0485
0486
0487 rc = rtems_rfs_fs_open (name, NULL,
0488 RTEMS_RFS_FS_FORCE_OPEN | RTEMS_RFS_FS_NO_LOCAL_CACHE,
0489 0, &fs);
0490 if (rc != 0)
0491 {
0492 rc = errno;
0493
0494 printf ("rtems-rfs: format: file system open failed: %d: %s\n",
0495 rc, strerror (rc));
0496
0497 return rc;
0498 }
0499
0500 rc = rtems_rfs_inode_alloc (fs, RTEMS_RFS_ROOT_INO, &ino);
0501 if (rc != 0)
0502 {
0503 printf ("rtems-rfs: format: inode allocation failed: %d: %s\n",
0504 rc, strerror (rc));
0505 rtems_rfs_fs_close (fs);
0506 return rc;
0507 }
0508
0509 if (ino != RTEMS_RFS_ROOT_INO)
0510 {
0511 printf ("rtems-rfs: format: allocated inode not root ino: %" PRId32 "\n", ino);
0512 rtems_rfs_fs_close (fs);
0513 return EINVAL;
0514 }
0515
0516 rc = rtems_rfs_inode_open (fs, ino, &inode, true);
0517 if (rc != 0)
0518 {
0519 printf ("rtems-rfs: format: inode open failed: %d: %s\n",
0520 rc, strerror (rc));
0521 rtems_rfs_group_bitmap_free (fs, true, ino);
0522 rtems_rfs_fs_close (fs);
0523 return rc;
0524 }
0525
0526 rc = rtems_rfs_inode_initialise (&inode, 0,
0527 (RTEMS_RFS_S_IFDIR | RTEMS_RFS_S_IRWXU |
0528 RTEMS_RFS_S_IXGRP | RTEMS_RFS_S_IXOTH),
0529 0, 0);
0530 if (rc != 0)
0531 printf ("rtems-rfs: format: inode initialise failed: %d: %s\n",
0532 rc, strerror (rc));
0533
0534 rc = rtems_rfs_dir_add_entry (fs, &inode, ".", 1, ino);
0535 if (rc != 0)
0536 printf ("rtems-rfs: format: directory add failed: %d: %s\n",
0537 rc, strerror (rc));
0538
0539 rc = rtems_rfs_inode_close (fs, &inode);
0540 if (rc != 0)
0541 printf ("rtems-rfs: format: inode close failed: %d: %s\n",
0542 rc, strerror (rc));
0543
0544 rc = rtems_rfs_fs_close (fs);
0545 if (rc != 0)
0546 {
0547 rc = errno;
0548
0549 printf ("rtems-rfs: format: file system close failed: %d: %s\n",
0550 rc, strerror (rc));
0551
0552 return rc;
0553 }
0554
0555 return 0;
0556 }
0557
0558 int
0559 rtems_rfs_format (const char* name, const rtems_rfs_format_config* config)
0560 {
0561 rtems_rfs_file_system fs;
0562 int group;
0563 int rc;
0564
0565 if (config->verbose)
0566 printf ("rtems-rfs: format: %s\n", name);
0567
0568 memset (&fs, 0, sizeof (rtems_rfs_file_system));
0569
0570 rtems_chain_initialize_empty (&fs.buffers);
0571 rtems_chain_initialize_empty (&fs.release);
0572 rtems_chain_initialize_empty (&fs.release_modified);
0573 rtems_chain_initialize_empty (&fs.file_shares);
0574
0575 fs.max_held_buffers = RTEMS_RFS_FS_MAX_HELD_BUFFERS;
0576
0577 fs.release_count = 0;
0578 fs.release_modified_count = 0;
0579
0580 fs.flags = RTEMS_RFS_FS_NO_LOCAL_CACHE;
0581
0582
0583
0584
0585 rc = rtems_rfs_buffer_open (name, &fs);
0586 if (rc != 0)
0587 {
0588 printf ("rtems-rfs: format: buffer open failed: %d: %s\n",
0589 rc, strerror (rc));
0590
0591 errno = rc;
0592 return -1;
0593 }
0594
0595
0596
0597
0598 if (rtems_rfs_fs_media_block_size (&fs) == 0)
0599 {
0600 printf ("rtems-rfs: media block is invalid: %" PRIu32 "\n",
0601 rtems_rfs_fs_media_block_size (&fs));
0602
0603 errno = EINVAL;
0604 return -1;
0605 }
0606
0607
0608
0609
0610 if (!rtems_rfs_check_config (&fs, config))
0611 {
0612 errno = EINVAL;
0613 return -1;
0614 }
0615
0616 if (config->verbose)
0617 {
0618 printf ("rtems-rfs: format: media size = %" PRIu64 "\n",
0619 rtems_rfs_fs_media_size (&fs));
0620 printf ("rtems-rfs: format: media blocks = %" PRIu32 "\n",
0621 rtems_rfs_fs_media_blocks (&fs));
0622 printf ("rtems-rfs: format: media block size = %" PRIu32 "\n",
0623 rtems_rfs_fs_media_block_size (&fs));
0624 printf ("rtems-rfs: format: size = %" PRIu64 "\n",
0625 rtems_rfs_fs_size (&fs));
0626 printf ("rtems-rfs: format: blocks = %zu\n",
0627 rtems_rfs_fs_blocks (&fs));
0628 printf ("rtems-rfs: format: block size = %zu\n",
0629 rtems_rfs_fs_block_size (&fs));
0630 printf ("rtems-rfs: format: bits per block = %u\n",
0631 rtems_rfs_bits_per_block (&fs));
0632 printf ("rtems-rfs: format: inode size = %zu\n", RTEMS_RFS_INODE_SIZE);
0633 printf ("rtems-rfs: format: inodes = %zu (%d.%d%%)\n",
0634 fs.group_inodes * fs.group_count,
0635 rtems_rfs_inode_overhead (&fs) / 10,
0636 rtems_rfs_inode_overhead (&fs) % 10);
0637 printf ("rtems-rfs: format: groups = %u\n", fs.group_count);
0638 printf ("rtems-rfs: format: group blocks = %zu\n", fs.group_blocks);
0639 printf ("rtems-rfs: format: group inodes = %zu\n", fs.group_inodes);
0640 }
0641
0642 rc = rtems_rfs_buffer_setblksize (&fs, rtems_rfs_fs_block_size (&fs));
0643 if (rc != 0)
0644 {
0645 printf ("rtems-rfs: format: setting block size failed: %d: %s\n",
0646 rc, strerror (rc));
0647
0648 errno = rc;
0649 return -1;
0650 }
0651
0652 if (!rtems_rfs_write_superblock (&fs))
0653 {
0654 printf ("rtems-rfs: format: superblock write failed\n");
0655
0656 errno = EIO;
0657 return -1;
0658 }
0659
0660 for (group = 0; group < fs.group_count; group++)
0661 if (!rtems_rfs_write_group (&fs, group,
0662 config->initialise_inodes, config->verbose))
0663 {
0664 errno = EIO;
0665 return -1;
0666 }
0667
0668 if (config->verbose)
0669 printf ("\n");
0670
0671 rc = rtems_rfs_buffer_close (&fs);
0672 if (rc != 0)
0673 {
0674 printf ("rtems-rfs: format: buffer close failed: %d: %s\n",
0675 rc, strerror (rc));
0676
0677 errno = rc;
0678 return -1;
0679 }
0680
0681 rc = rtems_rfs_write_root_dir (name);
0682 if (rc != 0)
0683 {
0684 printf ("rtems-rfs: format: writing root dir failed: %d: %s\n",
0685 rc, strerror (rc));
0686
0687 errno = rc;
0688 return -1;
0689 }
0690
0691 return 0;
0692 }