项目地址https://github.com/belowthetree/Make-a-systemgithub.com
进程切换在本项目中其实不是什么重要的部分,因为没有打算加入执行外部程序的功能(主要是懒)。那么为了让这个系统看起来更炫酷(在外行面前装13),就需要把交互性做好。
硬盘IO
在bootloader
部分已经用汇编完成了一个文件的读取,现在需要加入到C内核的功能里面,方便调用读取文件。
#define PORT_DISK0_DATA 0x1f0
#define PORT_DISK0_ERR_FEATURE 0x1f1
#define PORT_DISK0_SECTOR_CNT 0x1f2
#define PORT_DISK0_SECTOR_LOW 0x1f3
#define PORT_DISK0_SECTOR_MID 0x1f4
#define PORT_DISK0_SECTOR_HIGH 0x1f5
#define PORT_DISK0_DEVICE 0x1f6
#define PORT_DISK0_STATUS_CMD 0x1f7
#define DISK_STATUS_BUSY (1 << 7)
#define DISK_STATUS_READY (1 << 6)
#define DISK_STATUS_SEEK (1 << 4)
#define DISK_STATUS_REQ (1 << 3)
#define DISK_STATUS_ERROR (1 << 0)
以上是预设的一些量,在发送命令之后检查状态的第三位,确认硬盘数据是否发送完毕
void read_one_sector(int n, unsigned char* cx){
finish = 0;
reader = cx;
io_out8(PORT_DISK0_ALT_STA_CTL, 0);
io_out8(PORT_DISK0_SECTOR_CNT, 1);
io_out8(PORT_DISK1_ERR_FEATURE, 0);
io_out8(PORT_DISK0_SECTOR_LOW, (unsigned char)(n & 0xff));
io_out8(PORT_DISK0_SECTOR_MID, (unsigned char)((n >> 8) & 0xff));
io_out8(PORT_DISK0_SECTOR_HIGH, (unsigned char)((n >> 16) & 0xff));
io_out8(PORT_DISK0_DEVICE, 0xe0 | (unsigned char)((n >> 24) & 0x0f));
io_out8(PORT_DISK0_STATUS_CMD, 0x20);
// 直接检测数据是否抵达端口
while (!(io_in8(PORT_DISK0_STATUS_CMD) & DISK_STATUS_REQ));
port_insw(PORT_DISK0_DATA, reader, 256);
finish = 1;
}
这个函数对外作为读取磁盘的接口,一次读取一个扇区。
#define port_insw(port,buffer,nr)
__asm__ __volatile__("cld;rep;insw;mfence;"::"d"(port),"D"(buffer),"c"(nr):"memory")
文件读取
struct DIR{
char filename[11];
unsigned char attr;
unsigned char rev[10];
unsigned short wtime;
unsigned short wdate;
unsigned short stcluster;
unsigned int filesize;
}__attribute__((packed));
struct DIR dirs[16];
DIR
是FAT12
目录项结构,一个扇区16个目录项。
void scanf_files(){
filecnt = 0;
int i, j;
for (j = 0;j < 14;j++){
read_one_sector(19 + j, dirs);
while (!finish);
for (i = 0; i < 0x10; i++){
if (dirs[i].attr != 0x20)
continue;
files[filecnt++] = dirs[i];
printf_color(BLACK, YELLOW, "%sn", dirs[i].filename);
}
}
printf_color(BLACK, RED, "scanf finishn");
}
void list_files(){
int i;
for (i = 0;i < filecnt; i++){
printf_color(BLACK, INDIGO, "%st", files[i].filename);
}
printf("n");
}
通过扫描读取完所有的目录项,保存已有的文件信息。方便之后使用。
交互
交互目前提供以下指令
char *ins[] = {
"ls",
"cls",
"help help me",
};
char *helpinfo[] = {
"list files",
"clear screen",
"list help info",
};
void help(){
int i;
for (i = 0; i < 3;i++)
printf_color(BLACK, GREEN, "%s: %sn", ins[i], helpinfo[i]);
}
为了进行字符串对比,写了一个strcmp
。curcmd
是键盘解码时保存的当前输入 ,cls
是新增的清屏函数
while(1){
hlt();
decode_keyboard();
if (cmd){
cmd = 0;
if (strcmp(curcmd, "ls"))
list_files();
else if(strcmp(curcmd, "cls"))
cls();
else if (strcmp(curcmd, "help help me"))
help();
else
printf_color(BLACK, RED, "no cmdn");
}
}
这样就完成简单的交互了