1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
| /* 格式化分区,也就是初始化分区的元信息,创建文件系统 */ static void partition_format(struct partition* part) { /* 为方便实现,一个块大小是一扇区 */ uint32_t boot_sector_sects = 1; uint32_t super_block_sects = 1; uint32_t inode_bitmap_sects = DIV_ROUND_UP(MAX_FILES_PER_PART, BITS_PER_SECTOR); // I结点位图占用的扇区数.最多支持4096个文件 uint32_t inode_table_sects = DIV_ROUND_UP(((sizeof(struct inode) * MAX_FILES_PER_PART)), SECTOR_SIZE); uint32_t used_sects = boot_sector_sects + super_block_sects + inode_bitmap_sects + inode_table_sects; uint32_t free_sects = part->sec_cnt - used_sects;
/************** 简单处理块位图占据的扇区数 ***************/ uint32_t block_bitmap_sects; block_bitmap_sects = DIV_ROUND_UP(free_sects, BITS_PER_SECTOR); /* block_bitmap_bit_len是位图中位的长度,也是可用块的数量 */ uint32_t block_bitmap_bit_len = free_sects - block_bitmap_sects; block_bitmap_sects = DIV_ROUND_UP(block_bitmap_bit_len, BITS_PER_SECTOR); /*********************************************************/
/* 超级块初始化 */ struct super_block sb; sb.magic = 0x19590318; sb.sec_cnt = part->sec_cnt; sb.inode_cnt = MAX_FILES_PER_PART; sb.part_lba_base = part->start_lba;
sb.block_bitmap_lba = sb.part_lba_base + 2; // 第0块是引导块,第1块是超级块 sb.block_bitmap_sects = block_bitmap_sects;
sb.inode_bitmap_lba = sb.block_bitmap_lba + sb.block_bitmap_sects; sb.inode_bitmap_sects = inode_bitmap_sects;
sb.inode_table_lba = sb.inode_bitmap_lba + sb.inode_bitmap_sects; sb.inode_table_sects = inode_table_sects;
sb.data_start_lba = sb.inode_table_lba + sb.inode_table_sects; sb.root_inode_no = 0; sb.dir_entry_size = sizeof(struct dir_entry);
printk("%s info:\n", part->name); printk(" magic:0x%x\n part_lba_base:0x%x\n all_sectors:0x%x\n inode_cnt:0x%x\n block_bitmap_lba:0x%x\n block_bitmap_sectors:0x%x\n inode_bitmap_lba:0x%x\n inode_bitmap_sectors:0x%x\n inode_table_lba:0x%x\n inode_table_sectors:0x%x\n data_start_lba:0x%x\n", sb.magic, sb.part_lba_base, sb.sec_cnt, sb.inode_cnt, sb.block_bitmap_lba, sb.block_bitmap_sects, sb.inode_bitmap_lba, sb.inode_bitmap_sects, sb.inode_table_lba, sb.inode_table_sects, sb.data_start_lba);
struct disk* hd = part->my_disk; /******************************* * 1 将超级块写入本分区的1扇区 * ******************************/ ide_write(hd, part->start_lba + 1, &sb, 1); printk(" super_block_lba:0x%x\n", part->start_lba + 1);
/* 找出数据量最大的元信息,用其尺寸做存储缓冲区*/ uint32_t buf_size = (sb.block_bitmap_sects >= sb.inode_bitmap_sects ? sb.block_bitmap_sects : sb.inode_bitmap_sects); buf_size = (buf_size >= sb.inode_table_sects ? buf_size : sb.inode_table_sects) * SECTOR_SIZE; uint8_t* buf = (uint8_t*)sys_malloc(buf_size); // 申请的内存由内存管理系统清0后返回
/************************************** * 2 将块位图初始化并写入sb.block_bitmap_lba * *************************************/ /* 初始化块位图block_bitmap */ buf[0] = 0x01; // 第0个块预留给根目录,位图中先占位 uint32_t block_bitmap_last_byte = block_bitmap_bit_len / 8; uint8_t block_bitmap_last_bit = block_bitmap_bit_len % 8; uint32_t last_size = SECTOR_SIZE - (block_bitmap_last_byte % SECTOR_SIZE); // last_size是位图所在最后一个扇区中,不足一扇区的其余部分
/* 1 先将位图最后一字节到其所在的扇区的结束全置为1,即超出实际块数的部分直接置为已占用*/ memset(&buf[block_bitmap_last_byte], 0xff, last_size);
/* 2 再将上一步中覆盖的最后一字节内的有效位重新置0 */ uint8_t bit_idx = 0; while (bit_idx <= block_bitmap_last_bit) { buf[block_bitmap_last_byte] &= ~(1 << bit_idx++); } ide_write(hd, sb.block_bitmap_lba, buf, sb.block_bitmap_sects);
/*************************************** * 3 将inode位图初始化并写入sb.inode_bitmap_lba * ***************************************/ /* 先清空缓冲区*/ memset(buf, 0, buf_size); buf[0] = 0x1; // 第0个inode分给了根目录 /* 由于inode_table中共4096个inode,位图inode_bitmap正好占用1扇区, * 即inode_bitmap_sects等于1, 所以位图中的位全都代表inode_table中的inode, * 无须再像block_bitmap那样单独处理最后一扇区的剩余部分, * inode_bitmap所在的扇区中没有多余的无效位 */ ide_write(hd, sb.inode_bitmap_lba, buf, sb.inode_bitmap_sects);
/*************************************** * 4 将inode数组初始化并写入sb.inode_table_lba * ***************************************/ /* 准备写inode_table中的第0项,即根目录所在的inode */ memset(buf, 0, buf_size); // 先清空缓冲区buf struct inode* i = (struct inode*)buf; i->i_size = sb.dir_entry_size * 2; // .和.. i->i_no = 0; // 根目录占inode数组中第0个inode i->i_sectors[0] = sb.data_start_lba; // 由于上面的memset,i_sectors数组的其它元素都初始化为0 ide_write(hd, sb.inode_table_lba, buf, sb.inode_table_sects);
/*************************************** * 5 将根目录初始化并写入sb.data_start_lba ***************************************/ /* 写入根目录的两个目录项.和.. */ memset(buf, 0, buf_size); struct dir_entry* p_de = (struct dir_entry*)buf;
/* 初始化当前目录"." */ memcpy(p_de->filename, ".", 1); p_de->i_no = 0; p_de->f_type = FT_DIRECTORY; p_de++;
/* 初始化当前目录父目录".." */ memcpy(p_de->filename, "..", 2); p_de->i_no = 0; // 根目录的父目录依然是根目录自己 p_de->f_type = FT_DIRECTORY;
/* sb.data_start_lba已经分配给了根目录,里面是根目录的目录项 */ ide_write(hd, sb.data_start_lba, buf, 1);
printk(" root_dir_lba:0x%x\n", sb.data_start_lba); printk("%s format done\n", part->name); sys_free(buf); }
|