在文件系统章节我们已经学过硬盘分区的相关知识,在这里我们只是利用磁盘读写来对硬盘进行分区和操作。首先来看一下硬盘的扇区规划: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号