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