Add fs.h.
This commit is contained in:
parent
24e807423c
commit
7e678618d1
12
Makefile
12
Makefile
@ -19,7 +19,10 @@ debug: image.bin
|
|||||||
-ex "break _start" \
|
-ex "break _start" \
|
||||||
-ex "continue"
|
-ex "continue"
|
||||||
|
|
||||||
image.bin: mbr.bin kernel.bin
|
fs.img: kernel.bin tools/mkfs
|
||||||
|
tools/mkfs $@ $<
|
||||||
|
|
||||||
|
image.bin: mbr.bin fs.img
|
||||||
cat $^ >$@
|
cat $^ >$@
|
||||||
|
|
||||||
kernel.bin: kernel.o vga.o string.o drivers/ata.o
|
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 $@
|
$(CC) -m32 -ffreestanding -c -g $< -o $@
|
||||||
|
|
||||||
%.o: %.S
|
%.o: %.S
|
||||||
$(CC) -m32 $^ -c -g -o $@
|
$(AS) --32 -g $^ -o $@
|
||||||
|
|
||||||
mbr.bin: mbr.o
|
mbr.bin: mbr.o
|
||||||
$(LD) -m elf_i386 -Ttext=0x7c00 --oformat=binary $^ -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 $@
|
$(LD) -m elf_i386 -Ttext=0x7c00 $^ -o $@
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f *.bin *.o
|
rm -f *.bin *.o tools/mkfs
|
||||||
|
|
||||||
|
tools/%: tools/%.c
|
||||||
|
gcc -Wall -Werror -g $^ -o $@
|
||||||
|
|||||||
@ -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_DF 0x20
|
||||||
#define STATUS_ERR 0x01
|
#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
|
//Source - OsDev wiki
|
||||||
static void ATA_wait_BSY();
|
static void ATA_wait_BSY();
|
||||||
static void ATA_wait_DRQ();
|
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();
|
ATA_wait_BSY();
|
||||||
port_byte_out(0x1F6,0xE0 | ((LBA >>24) & 0xF));
|
port_byte_out(0x1F6, 0xE0 | ((LBA >>24) & 0xF));
|
||||||
port_byte_out(0x1F2,sector_count);
|
port_byte_out(0x1F2, sector_count);
|
||||||
port_byte_out(0x1F3, (uint8_t) LBA);
|
port_byte_out(0x1F3, (uint8_t) LBA);
|
||||||
port_byte_out(0x1F4, (uint8_t)(LBA >> 8));
|
port_byte_out(0x1F4, (uint8_t)(LBA >> 8));
|
||||||
port_byte_out(0x1F5, (uint8_t)(LBA >> 16));
|
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;
|
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_BSY();
|
||||||
ATA_wait_DRQ();
|
ATA_wait_DRQ();
|
||||||
for(int i=0;i<256;i++)
|
for(int i = 0; i < 256; i++)
|
||||||
target[i] = port_word_in(0x1F0);
|
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
|
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
|
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));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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 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);
|
void write_sectors_ATA_PIO(uint32_t LBA, uint8_t sector_count, uint32_t* bytes);
|
||||||
|
|||||||
8
drivers/misc.h
Normal file
8
drivers/misc.h
Normal 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
50
fs/fs.h
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/* 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);
|
||||||
16
kernel.c
16
kernel.c
@ -1,8 +1,18 @@
|
|||||||
|
asm(".asciz \"kernel start\"");
|
||||||
|
|
||||||
#include "vga.h"
|
#include "vga.h"
|
||||||
|
#include "drivers/ata.h"
|
||||||
|
#include "drivers/misc.h"
|
||||||
|
|
||||||
void _start() {
|
void _start() {
|
||||||
|
char buf[512];
|
||||||
|
|
||||||
vga_clear_screen();
|
vga_clear_screen();
|
||||||
for (int i = 0; i < 24; i++) {
|
vga_print_string("YABLOKO\n");
|
||||||
vga_print_string("hello world\n");
|
|
||||||
}
|
read_sectors_ATA_PIO((uint32_t)buf, 10, 1);
|
||||||
|
vga_print_string(buf);
|
||||||
|
|
||||||
|
asm("hlt");
|
||||||
|
qemu_shutdown();
|
||||||
}
|
}
|
||||||
|
|||||||
2
mbr.S
2
mbr.S
@ -16,7 +16,7 @@ _start:
|
|||||||
.equ ELF32_PHDR_FILESZ_OFFSET, 4*4
|
.equ ELF32_PHDR_FILESZ_OFFSET, 4*4
|
||||||
.equ KERNEL_OFFSET, 0x1000
|
.equ KERNEL_OFFSET, 0x1000
|
||||||
|
|
||||||
.equ MBR_SECTORS, 1
|
.equ MBR_SECTORS, 2
|
||||||
.equ SECTOR_BASE, 1
|
.equ SECTOR_BASE, 1
|
||||||
.equ ELFHDR_SECTORS, 8
|
.equ ELFHDR_SECTORS, 8
|
||||||
|
|
||||||
|
|||||||
8
port.h
8
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) {
|
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) {
|
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
78
tools/mkfs.c
Normal 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;
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user