From 7e678618d1dcc7c29b7dbdeaa72f699579867d83 Mon Sep 17 00:00:00 2001 From: Alexander Myltsev Date: Fri, 18 Nov 2022 22:58:49 +0300 Subject: [PATCH] Add fs.h. --- Makefile | 12 ++++++-- drivers/ata.c | 22 +++++++------- drivers/ata.h | 3 ++ drivers/misc.h | 8 ++++++ fs/fs.h | 50 ++++++++++++++++++++++++++++++++ kernel.c | 16 +++++++++-- mbr.S | 2 +- port.h | 8 ++++-- tools/mkfs.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 179 insertions(+), 20 deletions(-) create mode 100644 drivers/misc.h create mode 100644 fs/fs.h create mode 100644 tools/mkfs.c diff --git a/Makefile b/Makefile index 826ea27..b780b65 100644 --- a/Makefile +++ b/Makefile @@ -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 $@ diff --git a/drivers/ata.c b/drivers/ata.c index 8574c79..693dac5 100644 --- a/drivers/ata.c +++ b/drivers/ata.c @@ -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(0x1F5, (uint8_t)(LBA >> 16)); + port_byte_out(0x1F7, 0x20); //Send the read command uint16_t *target = (uint16_t*) target_address; - for (int j =0;j> 8)); - port_byte_out(0x1F5, (uint8_t)(LBA >> 16)); + port_byte_out(0x1F5, (uint8_t)(LBA >> 16)); port_byte_out(0x1F7,0x30); //Send the write command for (int j =0;j + 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); diff --git a/drivers/misc.h b/drivers/misc.h new file mode 100644 index 0000000..ff6ee08 --- /dev/null +++ b/drivers/misc.h @@ -0,0 +1,8 @@ +#pragma once +#include "../port.h" + +__attribute__((noreturn)) +static inline void qemu_shutdown() { + port_word_out(0x604, 0x2000); + while(1); +} diff --git a/fs/fs.h b/fs/fs.h new file mode 100644 index 0000000..8de61a3 --- /dev/null +++ b/fs/fs.h @@ -0,0 +1,50 @@ +#pragma once + +#include + +/* Directory structure: + + 32-byte entries +┌───────────────────────────────┐ +│Reserved │ +│char[32] │ +├──────┬──────┬────────┬────────┤ +│Offset│Size │Reserved│Name │ +│uint32│uint32│uint32 │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); diff --git a/kernel.c b/kernel.c index e9959e9..c17ed02 100644 --- a/kernel.c +++ b/kernel.c @@ -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(); } diff --git a/mbr.S b/mbr.S index b4104a8..a2c098a 100644 --- a/mbr.S +++ b/mbr.S @@ -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 diff --git a/port.h b/port.h index 2cbb9d0..283418b 100644 --- a/port.h +++ b/port.h @@ -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)); } diff --git a/tools/mkfs.c b/tools/mkfs.c new file mode 100644 index 0000000..40f0485 --- /dev/null +++ b/tools/mkfs.c @@ -0,0 +1,78 @@ +#include "../fs/fs.h" + +#include +#include + +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; +}