在文件系统章节我们已经学过硬盘分区的相关知识,在这里我们只是利用磁盘读写来对硬盘进行分区和操作。首先来看一下硬盘的扇区规划:1G大小的磁盘空间需要0x200000个扇区,一个字节的每一个bit位表示一个扇区,则需要0x200000/8=0x40000个字节,40000个字节本身需要使用0x40000 / 0x200 = 0x200个扇区来存储,所以bitmap的大小为0x200,HDA_BITMAP_SIZE+2是因为0号扇区为启动扇区,1号扇区为分区表扇区。
//hda1 bitmap为0x200个扇区,可表示1GB #define HDA1_BITMAP_START (2) #define HDA1_SIZE (0x200000) #define HDA1_START (HDA1_BITMAP_START + (HDA1_SIZE / 8 / 0x200)) //hda2 bitmap为0x400个扇区,可表示2GB #define HDA2_BITMAP_START (HDA1_START + HDA1_SIZE) #define HDA2_SIZE (0x400000) #define HDA2_START (HDA2_BITMAP_START + (HDA2_SIZE / 8 / 200)) //hda3 swap交换分区 bitmap为0x100个扇区,每个bit表示8个连续扇区,共可表示4GB #define HDA3_BITMAP_START (HDA2_START + HDA2_SIZE) #define HDA3_SIZE (0x800000) #define HDA3_START (HDA3_BITMAP_START + 0x100)
创建分区表,并将其写入磁盘。其中type为0表示普通分区用于存储长期数据,type为0表示swap分区,用于数据交换。写入分区表的操作只要做一次,写入成功以后就直接从硬盘中读入分区表即可,而不需要每次都重写分区表:
//hda1 data type == 0x00
sys_var->pts[0].device = 0x01;
sys_var->pts[0].boot = 0x01;
sys_var->pts[0].id = 0x01;
sys_var->pts[0].type = 0x00;
sys_var->pts[0].bitmap_start = HDA1_BITMAP_START;
sys_var->pts[0].start = HDA1_START;
sys_var->pts[0].size = HDA1_SIZE;
//hda2 data type == 0x00
sys_var->pts[1].device = 0x02;
sys_var->pts[1].boot = 0x00;
sys_var->pts[1].id = 0x02;
sys_var->pts[1].type = 0x00;
sys_var->pts[1].bitmap_start = HDA2_BITMAP_START;
sys_var->pts[1].start = HDA2_START;
sys_var->pts[1].size = HDA2_SIZE;
//hda3 swap type == 0x1
sys_var->pts[2].device = 0x03;
sys_var->pts[2].boot = 0x00;
sys_var->pts[2].id = 0x03;
sys_var->pts[2].type = 0x1;
sys_var->pts[2].bitmap_start = HDA3_BITMAP_START;
sys_var->pts[2].start = HDA3_START;
sys_var->pts[2].size = HDA3_SIZE;
write_sector(1, (u8*) sys_var->pts);
printf("[ OK ] Create hda partition table.\n");
载入分区表:
read_sector(1, (u8*) sys_var->pts);
printf("[ OK ] Load hda partition table.\n");
printf("\tDevice Boot Id Type Start End Sectors\n");
sys_var->pt_count = 0;
for (int i = 0; i < HD_PT_COUT; i++)
{
if (sys_var->pts[i].device == 0)
{
break;
}
sys_var->pt_count++;
printf("\thda%d %d %d %d %x %x %x\n", sys_var->pts[i].device, sys_var->pts[i].boot,
sys_var->pts[i].id,
sys_var->pts[i].type,
sys_var->pts[i].start,
sys_var->pts[i].start + sys_var->pts[i].size - 1,
sys_var->sys_var->pts[i].boot,
sys_var->pts[i].id,
sys_var->pts[i].type,
sys_var->pts[i].start,
sys_var->pts[i].start + sys_var->pts[i].size - 1,
sys_var->pts[i].size);
}
格式化分区,清空每个分区头部位图的值,与写入分区表一样只需要格式化一次即可,除非在以后的使用过程中有特殊需要才对分区重新格式化:
u8* empty = malloc(0x200);
for (int i = 0; i < 0x200; i++)
{
empty[i] = 0;
}
for (int i = 0; i < sys_var->pt_count; i++)
{
if (sys_var->pts[i].type != 0x1)
{
u32 bitmap_size = sys_var->pts[i].size / 8 / 0x200;
for (int j = 0; j < bitmap_size / 0x200; j++)
{
write_sector(sys_var->pts[i].bitmap_start + j, empty);
}
s_fs fs_root;
u8 *p = (u8*) &fs_root;
for (int i = 0; i < 0x200; i++)
{
p[i] = 0;
}
fs_root.owner = uid;
fs_root.group = gid;
fs_root.mode = mode;
fs_root.dot = hda_alloc(sys_var->pts[i].device);
fs_root.dotdot = fs_root.dot;
str_copy("/", fs_root.name);
write_sector(fs_root.dot, (u8 *) &fs_root);
printf("[ OK ] Format hda%d start: %d size: %d sectors.\n",
sys_var->pts[i].device,
sys_var->pts[i].start,
sys_var->pts[i].size);
}
}
free(empty);
值得注意的是在格式化分区时,需要对其写入根目录“/”。这样在内核程序mount此分区时才能找到其根目录并将其挂载到挂载点上。
最后编译运行程序并查看运行结果:

源代码的下载地址为:
https https://github.com/magicworldos/lidqos.git git git@github.com:magicworldos/lidqos.git subverion https://github.com/magicworldos/lidqos branch v0.28
Copyright © 2015-2023 问渠网 辽ICP备15013245号