tabs/helpers/make_bin.c

241 lines
5.8 KiB
C

#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;
}