Add fs.h.

This commit is contained in:
Alexander Myltsev 2022-11-18 22:58:49 +03:00
parent 24e807423c
commit 7e678618d1
9 changed files with 179 additions and 20 deletions

View File

@ -19,7 +19,10 @@ debug: image.bin
-ex "break _start" \
-ex "continue"
image.bin: mbr.bin kernel.bin
fs.img: kernel.bin tools/mkfs
tools/mkfs $@ $<
image.bin: mbr.bin fs.img
cat $^ >$@
kernel.bin: kernel.o vga.o string.o drivers/ata.o
@ -29,7 +32,7 @@ kernel.bin: kernel.o vga.o string.o drivers/ata.o
$(CC) -m32 -ffreestanding -c -g $< -o $@
%.o: %.S
$(CC) -m32 $^ -c -g -o $@
$(AS) --32 -g $^ -o $@
mbr.bin: mbr.o
$(LD) -m elf_i386 -Ttext=0x7c00 --oformat=binary $^ -o $@
@ -38,4 +41,7 @@ mbr.elf: mbr.o
$(LD) -m elf_i386 -Ttext=0x7c00 $^ -o $@
clean:
rm -f *.bin *.o
rm -f *.bin *.o tools/mkfs
tools/%: tools/%.c
gcc -Wall -Werror -g $^ -o $@

View File

@ -22,7 +22,7 @@ ERR: a 1 indicates that an error occured. An error code has been placed in the e
#define STATUS_DF 0x20
#define STATUS_ERR 0x01
//This is really specific to out OS now, assuming ATA bus 0 master
//This is really specific to our OS now, assuming ATA bus 0 master
//Source - OsDev wiki
static void ATA_wait_BSY();
static void ATA_wait_DRQ();
@ -30,22 +30,22 @@ void read_sectors_ATA_PIO(uint32_t target_address, uint32_t LBA, uint8_t sector_
{
ATA_wait_BSY();
port_byte_out(0x1F6,0xE0 | ((LBA >>24) & 0xF));
port_byte_out(0x1F2,sector_count);
port_byte_out(0x1F6, 0xE0 | ((LBA >>24) & 0xF));
port_byte_out(0x1F2, sector_count);
port_byte_out(0x1F3, (uint8_t) LBA);
port_byte_out(0x1F4, (uint8_t)(LBA >> 8));
port_byte_out(0x1F5, (uint8_t)(LBA >> 16));
port_byte_out(0x1F7,0x20); //Send the read command
port_byte_out(0x1F7, 0x20); //Send the read command
uint16_t *target = (uint16_t*) target_address;
for (int j =0;j<sector_count;j++)
for (int j = 0; j < sector_count; j++)
{
ATA_wait_BSY();
ATA_wait_DRQ();
for(int i=0;i<256;i++)
for(int i = 0; i < 256; i++)
target[i] = port_word_in(0x1F0);
target+=256;
target += 256;
}
}
@ -72,9 +72,9 @@ void write_sectors_ATA_PIO(uint32_t LBA, uint8_t sector_count, uint32_t* bytes)
static void ATA_wait_BSY() //Wait for bsy to be 0
{
while(port_byte_in(0x1F7)&STATUS_BSY);
while (port_byte_in(0x1F7) & STATUS_BSY);
}
static void ATA_wait_DRQ() //Wait fot drq to be 1
{
while(!(port_byte_in(0x1F7)&STATUS_RDY));
while(!(port_byte_in(0x1F7) & STATUS_RDY));
}

View File

@ -1,2 +1,5 @@
#pragma once
#include <stdint.h>
void read_sectors_ATA_PIO(uint32_t target_address, uint32_t LBA, uint8_t sector_count);
void write_sectors_ATA_PIO(uint32_t LBA, uint8_t sector_count, uint32_t* bytes);

8
drivers/misc.h Normal file
View File

@ -0,0 +1,8 @@
#pragma once
#include "../port.h"
__attribute__((noreturn))
static inline void qemu_shutdown() {
port_word_out(0x604, 0x2000);
while(1);
}

50
fs/fs.h Normal file
View File

@ -0,0 +1,50 @@
#pragma once
#include <stdint.h>
/* Directory structure:
32-byte entries
Reserved
char[32]
OffsetSize ReservedName
uint32uint32uint32 char[20]
...
Offset is in sectors (zero-based),
size is in bytes, name is 0-terminated.
*/
enum {
sector_size = 512,
};
struct dirent {
uint32_t offset_sectors;
uint32_t size_bytes;
uint32_t reserved;
char name[20];
};
struct dir {
char reserved[32];
struct dirent entries[15];
};
struct stat {
uint32_t size;
uint32_t reserved[3];
};
/* Find file by name and fill information in buf.
* Returns zero on success, nonzero on failure. */
int stat(const char* name, struct stat *buf);
/* Find file by name and read it into buffer with size bufsize.
* At most (bufsize & ~511) bytes will be read.
* Return number of bytes read or -1 on failure. */
int read_file(const char* name, void* buf, uint32_t bufsize);

View File

@ -1,8 +1,18 @@
asm(".asciz \"kernel start\"");
#include "vga.h"
#include "drivers/ata.h"
#include "drivers/misc.h"
void _start() {
char buf[512];
vga_clear_screen();
for (int i = 0; i < 24; i++) {
vga_print_string("hello world\n");
}
vga_print_string("YABLOKO\n");
read_sectors_ATA_PIO((uint32_t)buf, 10, 1);
vga_print_string(buf);
asm("hlt");
qemu_shutdown();
}

2
mbr.S
View File

@ -16,7 +16,7 @@ _start:
.equ ELF32_PHDR_FILESZ_OFFSET, 4*4
.equ KERNEL_OFFSET, 0x1000
.equ MBR_SECTORS, 1
.equ MBR_SECTORS, 2
.equ SECTOR_BASE, 1
.equ ELFHDR_SECTORS, 8

8
port.h
View File

@ -13,9 +13,13 @@ static unsigned short port_word_in(unsigned short port) {
}
static void port_byte_out(unsigned short port, unsigned char data) {
__asm__("out %%al, %%dx" : : "a" (data), "d" (port));
__asm__("outb %%al, %%dx" : : "a" (data), "d" (port));
}
static void port_word_out(unsigned short port, unsigned short data) {
__asm__("outw %%ax, %%dx" : : "a" (data), "d" (port));
}
static void port_long_out(unsigned short port, unsigned int data) {
__asm__("out %%eax, %%dx" : : "a" (data), "d" (port));
__asm__("outl %%eax, %%dx" : : "a" (data), "d" (port));
}

78
tools/mkfs.c Normal file
View File

@ -0,0 +1,78 @@
#include "../fs/fs.h"
#include <stdio.h>
#include <string.h>
char* basename(char* path) {
char* c = strrchr(path, '/');
if (c && *c) {
return c + 1;
}
return path;
}
int main(int argc, char* argv[]) {
char sector[sector_size];
struct dir dir = {{0}};
if (argc < 3) {
fprintf(stderr, "Usage: %s OUT.FS KERNEL.BIN [FILES...]\n", argv[0]);
return 1;
}
FILE* image = fopen(argv[1], "wb");
if (!image) {
perror(argv[1]);
return 1;
}
if (fwrite(&dir, sizeof(dir), 1, image) < 1) {
perror("fwrite");
return 1;
}
uint32_t sector_offset = 1;
for (int i = 2; i < argc; ++i) {
char* name = argv[i];
struct dirent *dirent = &dir.entries[i-2];
dirent->offset_sectors = sector_offset;
dirent->size_bytes = 0;
FILE* file = fopen(name, "rb");
if (!file) {
perror(name);
return 1;
}
size_t read_size;
while ((read_size = fread(sector, 1, sizeof(sector), file))) {
if (fwrite(sector, 1, sizeof(sector), image) != sizeof(sector)) {
perror(name);
return 1;
}
sector_offset++;
dirent->size_bytes += read_size;
}
if (fclose(file)) {
perror(name);
return 1;
}
dirent->reserved = 0;
strlcpy(dirent->name, basename(name), sizeof(dirent->name));
}
fseek(image, 0, SEEK_SET);
if (fwrite(&dir, sizeof(dir), 1, image) < 1) {
perror("fwrite");
return 1;
}
if (fclose(image)) {
perror(argv[0]);
return 1;
}
return 0;
}