241 lines
No EOL
5.8 KiB
C
241 lines
No EOL
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;
|
|
} |