Merge branch 'sfs'

This commit is contained in:
Robbe Van Herck 2020-01-07 14:08:24 +01:00
commit b5678a0246
No known key found for this signature in database
GPG key ID: A66F76F7B81BD784
7 changed files with 307 additions and 19 deletions

View file

@ -1,15 +1,23 @@
run_bootloader: compile_bootloader
run: bin
qemu-system-i386 -drive format=raw,file=target/boot.bin -monitor stdio
run_kernel: compile_kernel
qemu-system-i386 -kernel target/kernel.bin
clean:
rm -r ./target/
mkdir -p ./target/helpers
mkdir ./target/bootloader
mkdir ./target/kernel
compile_bootloader: compile_kernel
rm -rf target/bootloader.bin
nasm -f bin -o target/bootloader.bin bootloader/main.asm
cat target/bootloader.bin target/kernel.bin > target/boot.bin
bin: compile_bootloader compile_kernel compile_helpers
./target/helpers/make_bin
compile_helpers:
gcc -g -o ./target/helpers/make_bin ./helpers/make_bin.c
compile_bootloader:
rm -rf target/bootloader/bootloader.bin
nasm -f bin -o target/bootloader/bootloader.bin bootloader/main.asm
compile_kernel:
nasm -felf32 kernel/boot.asm -o target/boot.o
i686-elf-gcc -c kernel/kernel.c -o target/kernel.o -std=gnu99 -ffreestanding -O2 -Wall -Wextra
i686-elf-gcc -T kernel/linker.ld -o target/kernel.bin -ffreestanding -O2 -nostdlib target/boot.o target/kernel.o -lgcc
nasm -felf32 kernel/wrapper.asm -o target/kernel/wrapper.o
i686-elf-gcc -c kernel/kernel.c -o target/kernel/kernel.o -std=gnu99 -ffreestanding -O2 -Wall -Wextra
i686-elf-gcc -T kernel/linker.ld -o target/kernel/kernel.bin -ffreestanding -O2 -nostdlib target/kernel/wrapper.o target/kernel/kernel.o -lgcc

View file

@ -293,13 +293,19 @@ jmp .end
.invalid_elf:
mov byte [ds:0x0B8000], 'E'
mov byte [ds:0x0B8001], 0x40
mov byte [ds:0x0B8002], 'L'
mov byte [ds:0x0B8003], 0x40
mov byte [ds:0x0B8004], 'F'
mov byte [ds:0x0B8005], 0x40
jmp .end
; padding for bootloader - SFS superblock
times 404 - ($ - $$) db 0
; room for SFS superblock
times 42 db 0
; padding for SFS superblock - data
times 66 - (.file_end - .data) db 0
.data:
.gdt:
@ -327,8 +333,7 @@ dd .gdt
.entrypoint: dd 0
; print padding nullbytes
times 510 - ($ - $$) db 0
; magic string
dw 0xAA55
; write magic string
dw 0xAA55
.file_end:

View file

@ -14,12 +14,36 @@
| 0x80000 | 0x9ffff | EDBA, partially usable |
| 0xa0000 | 0xfffff | unusable |
## Drive layout
## Bootsector layout
The first 512 bytes are the bootloader, right after that the 32-bit kernel ELF-file, this kernel can be 32KiB big. In the future, this "kernel" can be replaced by a second stage of the bootloader.
(all addresses are offsets from 0x7C00)
| start | end | use |
|--------|--------|-------------------|
| 0x0000 | ? | Bootloader code |
| ? | 0x0193 | _padding_ |
| 0x0194 | 0x01bd | SFS header |
| 0x01be | ? | _padding_ |
| ? | 0x01fd | data |
| 0x01fe | 0x01ff | 0x55AA boot magic |
## Hard Drive layout
| start | end | use |
|------------|------------|--------------------------------------------|
| 0x00000000 | 0x000001ff | Bootloader code (including SFS superblock) |
| 0x00000200 | 0x000081ff | SFS reserved area (kernel ELF file) |
| 0x00008200 | ??? | SFS data area |
| ??? | ??? | SFS free area |
| ??? | 0x00ffffff | SFS index area |
| 0x01000000 | end | Unused (Disk size is set to 16MiB) |
## Known issues
### Stack setup
As I don't quite get how segments work in real mode, there are most likely errors in the way I set up my stack. I'm going on a _it works on my machine_ approach currently.
### Kernel is not a file
I reserve 32KiB of SFS reserved area for the ELF file of the kernel. This is currently for "historic reasons" (a.k.a. I'm too lazy to load the filesystem in the bootloader). The kernel then handles the filesystem.

1
filesystem/test.txt Normal file
View file

@ -0,0 +1 @@
this is a string in a file :O

View file

@ -0,0 +1,9 @@
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Fringilla est ullamcorper eget nulla facilisi etiam dignissim diam quis. Tellus at urna condimentum mattis pellentesque id nibh. Tellus in metus vulputate eu. Malesuada proin libero nunc consequat interdum varius sit amet mattis. Nulla facilisi nullam vehicula ipsum a arcu cursus. Pretium nibh ipsum consequat nisl vel. Placerat orci nulla pellentesque dignissim enim sit amet. Maecenas pharetra convallis posuere morbi. Lobortis feugiat vivamus at augue eget arcu dictum varius duis. Purus sit amet volutpat consequat mauris nunc. Mi tempus imperdiet nulla malesuada pellentesque elit eget. Nisl pretium fusce id velit ut tortor pretium viverra. Pellentesque habitant morbi tristique senectus et.
Ultrices neque ornare aenean euismod elementum. Eget mauris pharetra et ultrices neque ornare. Eu lobortis elementum nibh tellus molestie nunc non blandit. Aenean euismod elementum nisi quis eleifend. Semper auctor neque vitae tempus quam pellentesque. Blandit massa enim nec dui nunc mattis enim. Semper quis lectus nulla at volutpat diam ut venenatis. Semper eget duis at tellus at urna condimentum mattis pellentesque. Et malesuada fames ac turpis egestas. Tristique sollicitudin nibh sit amet commodo nulla facilisi nullam vehicula. Vel fringilla est ullamcorper eget. Ultricies leo integer malesuada nunc vel risus commodo. A lacus vestibulum sed arcu non odio. Condimentum mattis pellentesque id nibh tortor id aliquet.
Nunc pulvinar sapien et ligula ullamcorper malesuada proin libero. At auctor urna nunc id cursus metus aliquam eleifend. Lorem ipsum dolor sit amet consectetur adipiscing elit ut aliquam. Vulputate ut pharetra sit amet. Ultricies lacus sed turpis tincidunt id aliquet risus feugiat. Eget felis eget nunc lobortis mattis aliquam faucibus purus in. Platea dictumst quisque sagittis purus sit amet volutpat. Pellentesque habitant morbi tristique senectus et netus et malesuada. Congue nisi vitae suscipit tellus mauris a diam maecenas. Interdum velit euismod in pellentesque massa. Sed velit dignissim sodales ut eu sem. Sed nisi lacus sed viverra. Pretium nibh ipsum consequat nisl vel pretium. Dolor morbi non arcu risus quis varius quam. Sed arcu non odio euismod lacinia. Laoreet id donec ultrices tincidunt arcu non sodales neque sodales. Imperdiet sed euismod nisi porta lorem.
Massa ultricies mi quis hendrerit dolor magna eget. Viverra vitae congue eu consequat ac felis donec et odio. Consectetur adipiscing elit ut aliquam purus. Volutpat lacus laoreet non curabitur gravida arcu ac. Volutpat odio facilisis mauris sit amet massa vitae. Volutpat maecenas volutpat blandit aliquam. Eleifend mi in nulla posuere. Duis ut diam quam nulla. Bibendum arcu vitae elementum curabitur vitae nunc sed velit. Metus aliquam eleifend mi in nulla posuere sollicitudin. Nisi lacus sed viverra tellus in. Pellentesque id nibh tortor id aliquet lectus proin nibh. Ornare suspendisse sed nisi lacus sed viverra tellus in hac. Sed pulvinar proin gravida hendrerit lectus. Quis lectus nulla at volutpat. Cursus mattis molestie a iaculis. Etiam erat velit scelerisque in dictum non.
Enim nulla aliquet porttitor lacus luctus accumsan tortor posuere ac. Elementum tempus egestas sed sed risus. Odio facilisis mauris sit amet massa vitae. Morbi blandit cursus risus at ultrices mi. Scelerisque fermentum dui faucibus in ornare. Consectetur libero id faucibus nisl tincidunt eget nullam. Neque egestas congue quisque egestas diam in arcu cursus. Faucibus scelerisque eleifend donec pretium vulputate. Imperdiet nulla malesuada pellentesque elit eget gravida cum sociis. At consectetur lorem donec massa sapien faucibus et. Consectetur adipiscing elit ut aliquam purus. Gravida quis blandit turpis cursus in hac. Egestas tellus rutrum tellus pellentesque eu tincidunt. Lacus sed turpis tincidunt id. Ultricies integer quis auctor elit sed. Aliquet nec ullamcorper sit amet risus. Eu feugiat pretium nibh ipsum consequat nisl vel pretium lectus. Sem et tortor consequat id porta nibh venenatis.

241
helpers/make_bin.c Normal file
View file

@ -0,0 +1,241 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <time.h>
#define KERNEL_SECTORS 64
#define KiB 1024
#define MiB (1024 * KiB)
#define GiB (1024 * MiB)
#define DISK_SIZE (16 * MiB)
#define BLOCK_SIZE_ARG 1
#define BLOCK_SIZE (1 << (BLOCK_SIZE_ARG + 7)) // 256 bytes
#define RESERVED_SIZE (32 * KiB)
#define NUM_RESERVED_BLOCKS (RESERVED_SIZE / BLOCK_SIZE)
#define DISK_NAME "RobUSB"
uint8_t* buffer;
long buffer_index = 0;
uint8_t* index_start;
int index_entries = 0;
int block_entries = 0;
void add_directory(const char* directory_name) {
printf("Writing directory %s...\n", directory_name);
index_start[0x00] = 0x11; // It's a folder
uint8_t num_continuations;
if (strlen(directory_name) < 30) {
num_continuations = 0; // No continuation needed
} else {
num_continuations = ((strlen(directory_name) - 30) / 64) + 1;
}
index_start[0x01] = num_continuations;
time_t current_time = time(NULL);
uint64_t sfs_timestamp = (uint64_t) current_time * 65536;
*(uint64_t*) (index_start + 0x02) = sfs_timestamp; // Add time
int pos = 0x0A;
for (int i = 0; i < strlen(directory_name); i++) {
index_start[pos] = directory_name[i];
pos++;
if (pos >= 64) {
pos = 0;
index_start -= 64;
index_entries++;
}
}
index_start -= 64;
index_entries++;
}
void add_file(const char* filename) {
printf("Writing file %s...\n", filename);
FILE* source = fopen(filename, "rb");
// Add to Index area
index_start[0x00] = 0x12; // It's a file
uint8_t num_continuations;
if (strlen(filename) < 30) {
num_continuations = 0; // No continuation needed
} else {
num_continuations = ((strlen(filename) - 30) / 64) + 1;
}
index_start[0x01] = num_continuations;
time_t current_time = time(NULL);
uint64_t sfs_timestamp = (uint64_t) current_time * 65536;
*(uint64_t*) (index_start + 0x02) = sfs_timestamp; // Add time
*(uint64_t*) (index_start + 0x0a) = *(uint64_t*) (buffer + 0x019C); // Data block start
// Add to Data area
char curr_char;
int i = 0;
long size = 0;
while((curr_char = fgetc(source)) != EOF) {
buffer[buffer_index] = (uint8_t) curr_char;
buffer_index++;
size++;
if (i >= 255) {
i = 0;
(*(uint64_t*) (buffer + 0x019C))++;
} else {
i++;
}
}
buffer[0x019C]++;
buffer_index += (BLOCK_SIZE - (buffer_index % BLOCK_SIZE));
// Rest of Index area
*(uint64_t*) (index_start + 0x12) = *(uint64_t*) (buffer + 0x019C); // Data block end
*(uint64_t*) (index_start + 0x1A) = (uint64_t) size;
int pos = 0x22;
for (int i = 0; i < strlen(filename); i++) {
index_start[pos] = filename[i];
pos++;
if (pos >= 64) {
pos = 0;
index_start -= 64;
index_entries++;
}
}
index_start -= 64;
index_entries++;
fclose(source);
}
void add_files() {
add_directory("filesystem");
add_file("filesystem/test.txt");
add_directory("filesystem/test_folder_with_long_name_that_is_actually_quite_unpractical_to_type");
add_file("filesystem/test_folder_with_long_name_that_is_actually_quite_unpractical_to_type/test_file_with_very_VERY_long_name");
}
int main(int argc, char** argv) {
buffer = calloc(DISK_SIZE, sizeof(uint8_t));
puts("Writing bootloader...");
FILE* bootloader_file = fopen("./target/bootloader/bootloader.bin", "rb");
// ------- BOOTLOADER + SFS HEADER -------
int curr_byte;
while ((curr_byte = fgetc(bootloader_file)) != EOF) {
buffer[buffer_index] = (uint8_t) curr_byte;
buffer_index++;
}
// SFS Superblock
time_t current_time = time(NULL);
uint64_t sfs_timestamp = (uint64_t) current_time * 65536;
(*(uint64_t*) (buffer + 0x194)) = sfs_timestamp;
(*(uint64_t*) (buffer + 0x19C)) = 0; // Start off with empty Data-area
(*(uint64_t*) (buffer + 0x1A4)) = 0; // Start off with basic Index-area
(*(uint32_t*) (buffer + 0x1AC)) = 0x10534653; // SFS magic + version
(*(uint64_t*) (buffer + 0x1B0)) = ((uint64_t) DISK_SIZE) / BLOCK_SIZE;
// The superblock may be bigger than one block
if (BLOCK_SIZE < 512) {
(*(uint32_t*) (buffer + 0x1B8)) = NUM_RESERVED_BLOCKS + 2;
} else {
(*(uint32_t*) (buffer + 0x1B8)) = NUM_RESERVED_BLOCKS + 1;
}
buffer[0x1BC] = BLOCK_SIZE_ARG;
uint8_t sum = 0;
for (int i = 0x1AC; i < 0x1BD; i++) {
sum += buffer[i];
}
buffer[0x1BD] = -sum;
fclose(bootloader_file);
// ------- KERNEL -------
puts("Writing kernel...");
FILE* kernel_file = fopen("./target/kernel/kernel.bin", "rb");
int bytes_written = 0;
while ((curr_byte = fgetc(kernel_file)) != EOF) {
buffer[buffer_index] = (char) curr_byte;
buffer_index++;
}
buffer_index = ((KERNEL_SECTORS + 1) * 512);
fclose(kernel_file);
// ------- FILESYSTEM -------
puts("Writing filesystem...");
// Volume identifier
index_start = buffer + DISK_SIZE - 64;
index_start[0x00] = 0x01; // It's a volume identifier
(*(uint64_t*) (index_start + 0x04)) = sfs_timestamp;
for (int i = 0; i < strlen(DISK_NAME); i++)
{
index_start[0x0c + i] = DISK_NAME[i];
}
index_start -= 64; // next entry
index_entries++;
// Files
add_files();
// Starting marker
index_start[0x00] = 0x02; // It's a starting marker
index_start -= 64; // next entry
index_entries++;
// ------- WRITE BIN -------
FILE* result_file = fopen("./target/boot.bin", "w+b");
fwrite(buffer, sizeof(uint8_t), DISK_SIZE, result_file);
fclose(result_file);
free(buffer);
return EXIT_SUCCESS;
}