uint32_t size;
uint32_t mod_start;
uint32_t mod_end;
- char cmdline[0];
+ char string[0];
};
struct multiboot_mmap_entry {
char* strcpy(char* dest, const char* src);
void* memset(void* ptr, int value, size_t num);
void* memcpy(void* dst, const void* src, size_t n);
+char* strcpy(char* dest, const char* src);
// Reverse a string (helper for itoa)
void reverse(char* str, int length);
#include "initrd.h"
-#include "heap.h"
#include "utils.h"
+#include "heap.h"
#include "uart_console.h"
-// The raw initrd header
-typedef struct {
- uint32_t nfiles;
-} initrd_header_t;
-
-initrd_header_t* initrd_header;
initrd_file_header_t* file_headers;
fs_node_t* initrd_root;
fs_node_t* root_nodes; // Array of file nodes
int n_root_nodes;
-// Read operation for a specific file
uint32_t initrd_read(fs_node_t* node, uint32_t offset, uint32_t size, uint8_t* buffer) {
initrd_file_header_t header = file_headers[node->inode];
- if (offset > header.length)
- return 0;
-
+ if (offset > header.length) return 0;
if (offset + size > header.length)
size = header.length - offset;
- // Calculate physical address of data
- // Data starts after nfiles + headers
- // location + header.offset
- // But header.offset is relative to start of data area or start of file?
- // Let's assume absolute offset from initrd start for simplicity.
+ // Calculate memory location: location_of_headers + sizeof(headers) + offset_in_file
+ // Wait, our simple format:
+ // [n_files] [header 0] [header 1] ... [data]
+ // The 'offset' in header is relative to the START of the initrd or the data region?
+ // Let's assume relative to START of InitRD location.
- uint8_t* data = (uint8_t*)((uint32_t)initrd_header + header.offset);
+ // We need to know the base address of InitRD. Let's store it globally or in node.
+ // Hack: Assuming offset in header is absolute address for now (patched during build)
+ // OR: offset is relative to initrd start.
- memcpy(buffer, data + offset, size);
+ // Let's refine the format logic in initrd_init.
+ return 0; // Placeholder until init logic fixed below
+}
+
+// Fixed read function
+// We need to store the base address somewhere.
+static uint32_t initrd_location_base = 0;
+
+uint32_t initrd_read_impl(fs_node_t* node, uint32_t offset, uint32_t size, uint8_t* buffer) {
+ initrd_file_header_t header = file_headers[node->inode];
+ if (offset > header.length) return 0;
+ if (offset + size > header.length)
+ size = header.length - offset;
+
+ // Address = Base + Header_Offset + Read_Offset
+ uint8_t* src = (uint8_t*)(initrd_location_base + header.offset + offset);
+
+ memcpy(buffer, src, size);
return size;
}
-// Directory listing (Find file by name)
-fs_node_t* initrd_finddir(fs_node_t* node, char* name) {
- (void)node; // Root only has flat files
-
+struct fs_node* initrd_finddir(struct fs_node* node, char* name) {
+ (void)node;
for (int i = 0; i < n_root_nodes; i++) {
- if (strcmp(name, root_nodes[i].name) == 0) {
+ if (strcmp(name, root_nodes[i].name) == 0)
return &root_nodes[i];
- }
}
- return NULL;
+ return 0;
}
fs_node_t* initrd_init(uint32_t location) {
- uart_print("[INITRD] Initializing at address: ");
- // TODO: Print hex location
- uart_print("\n");
+ initrd_location_base = location;
- initrd_header = (initrd_header_t*)location;
- file_headers = (initrd_file_header_t*)(location + sizeof(initrd_header_t));
+ // Read number of files (first 4 bytes)
+ uint32_t* n_files_ptr = (uint32_t*)location;
+ n_root_nodes = *n_files_ptr;
- // Check sanity (assuming nfiles < 100)
- if (initrd_header->nfiles > 100) {
- uart_print("[INITRD] Warning: Suspicious file count. Corrupt image?\n");
- return NULL;
- }
-
- n_root_nodes = initrd_header->nfiles;
+ uart_print("[INITRD] Found ");
+ char buf[16]; itoa(n_root_nodes, buf, 10);
+ uart_print(buf);
+ uart_print(" files.\n");
- // Create Root Directory Node
- initrd_root = (fs_node_t*)kmalloc(sizeof(fs_node_t));
- strcpy(initrd_root->name, "initrd");
- initrd_root->flags = FS_DIRECTORY;
- initrd_root->finddir = &initrd_finddir;
- initrd_root->inode = 0;
+ // Headers start right after n_files
+ file_headers = (initrd_file_header_t*)(location + sizeof(uint32_t));
- // Create File Nodes
+ // Allocate nodes for files
root_nodes = (fs_node_t*)kmalloc(sizeof(fs_node_t) * n_root_nodes);
for (int i = 0; i < n_root_nodes; i++) {
- file_headers[i].offset += location; // Relocate offset to absolute address
+ file_headers[i].offset += location; // Fixup offset to be absolute address
strcpy(root_nodes[i].name, file_headers[i].name);
- root_nodes[i].length = file_headers[i].length;
root_nodes[i].inode = i;
+ root_nodes[i].length = file_headers[i].length;
root_nodes[i].flags = FS_FILE;
- root_nodes[i].read = &initrd_read;
-
- // Debug
- uart_print(" Found file: ");
- uart_print(root_nodes[i].name);
- uart_print("\n");
+ root_nodes[i].read = &initrd_read_impl;
+ root_nodes[i].write = 0;
+ root_nodes[i].open = 0;
+ root_nodes[i].close = 0;
+ root_nodes[i].finddir = 0;
}
+ // Create Root Directory Node
+ initrd_root = (fs_node_t*)kmalloc(sizeof(fs_node_t));
+ strcpy(initrd_root->name, "initrd");
+ initrd_root->flags = FS_DIRECTORY;
+ initrd_root->finddir = &initrd_finddir;
+
return initrd_root;
}
#include "shell.h"
#include "heap.h"
#include "timer.h"
-#include "fs.h"
-#include "initrd.h"
#include "multiboot2.h"
+#include "initrd.h"
+#include "fs.h"
/* Check if the compiler thinks we are targeting the wrong operating system. */
#if defined(__linux__)
// 1. Initialize Console (UART works everywhere)
uart_init();
uart_print("\n[AdrOS] Booting...\n");
-
- uint32_t initrd_location = 0;
#if defined(__i386__) || defined(__x86_64__)
vga_init();
uart_print("[ERR] Invalid Multiboot2 Magic!\n");
} else {
uart_print("[OK] Multiboot2 Magic Confirmed.\n");
-
- // Search for InitRD Module
- struct multiboot_tag *tag;
- // Addr is physical. We need to access it.
- // Bootloader puts it in low memory. We have identity map.
- // But let's be safe.
- // Assuming addr is accessible.
-
- for (tag = (struct multiboot_tag *)(addr + 8);
- tag->type != MULTIBOOT_TAG_TYPE_END;
- tag = (struct multiboot_tag *)((uint8_t *)tag + ((tag->size + 7) & ~7)))
- {
- if (tag->type == MULTIBOOT_TAG_TYPE_MODULE) {
- struct multiboot_tag_module *mod = (struct multiboot_tag_module *)tag;
- initrd_location = mod->mod_start; // Physical
- uart_print("[BOOT] Found InitRD module!\n");
- }
- }
}
#endif
// 4. Initialize Kernel Heap
kheap_init();
- // 5. Initialize FS (if InitRD found)
- if (initrd_location) {
- // Convert physical to virtual (Higher Half)
- // P2V macro is in vmm.h or locally defined?
- // Let's assume PMM/VMM setup allows access via P2V
- // We need to define P2V here or include it
- #define P2V(x) ((uintptr_t)(x) + 0xC0000000)
-
- uint32_t virt_loc = P2V(initrd_location);
- fs_root = initrd_init(virt_loc);
- } else {
- uart_print("[WARN] No InitRD found. Filesystem will be empty.\n");
- }
-
- // 6. Initialize Interrupts (x86)
+ // 5. Initialize Interrupts (x86)
uart_print("[AdrOS] Initializing IDT...\n");
idt_init();
- // 7. Initialize Drivers
+ // 6. Initialize Drivers
keyboard_init();
- // 8. Initialize Multitasking
+ // 7. Initialize Multitasking
uart_print("[AdrOS] Initializing Scheduler...\n");
process_init();
- // 9. Start Timer (Preemption!) - 50Hz
+ // 8. Start Timer (Preemption!) - 50Hz
timer_init(50);
+
+ // 9. Load InitRD (if available)
+ struct multiboot_tag *tag;
+ // addr is physical. In Higher Half, we might need to convert it?
+ // boot.S mapped 0-4MB identity, so if multiboot struct is there, we are good.
+ // Let's assume addr is accessible.
+
+ for (tag = (struct multiboot_tag *)((uint8_t *)addr + 8);
+ tag->type != MULTIBOOT_TAG_TYPE_END;
+ tag = (struct multiboot_tag *)((uint8_t *)tag + ((tag->size + 7) & ~7)))
+ {
+ if (tag->type == MULTIBOOT_TAG_TYPE_MODULE) {
+ struct multiboot_tag_module *mod = (struct multiboot_tag_module *)tag;
+
+ uart_print("[INITRD] Module found at: ");
+ // TODO: Print Hex
+ uart_print("\n");
+
+ // mod->mod_start is Physical Address.
+ // We need to access it. Assuming Identity Map covers it or we use P2V logic.
+ // Let's rely on P2V macro logic if it was available here, or just cast.
+ // For now, let's assume it's low memory and identity mapped.
+
+ fs_root = initrd_init(mod->mod_start);
+ }
+ }
// Start Shell as the main interaction loop
shell_init();
// Infinite loop acting as Idle Task
for(;;) {
- // HLT puts CPU to sleep until next interrupt (Timer or Keyboard)
#if defined(__i386__) || defined(__x86_64__)
__asm__("hlt");
#elif defined(__aarch64__)
#include "utils.h"
#include "pmm.h"
#include "vga_console.h"
-#include "process.h"
+#include "process.h"
#include "fs.h"
+#include "heap.h"
#define MAX_CMD_LEN 256
static char cmd_buffer[MAX_CMD_LEN];
static int cmd_index = 0;
-// HACK: To list files since we lack readdir
-extern int n_root_nodes;
-extern fs_node_t* root_nodes;
-
void print_prompt(void) {
uart_print("\nAdrOS $> ");
}
uart_print("Available commands:\n");
uart_print(" help - Show this list\n");
uart_print(" clear - Clear screen\n");
+ uart_print(" ls - List files (Dummy)\n");
+ uart_print(" cat <file> - Read file content\n");
uart_print(" mem - Show memory stats\n");
uart_print(" panic - Trigger kernel panic\n");
uart_print(" reboot - Restart system\n");
uart_print(" sleep <num> - Sleep for N ticks\n");
- uart_print(" ls - List files\n");
- uart_print(" cat <file> - Print file content\n");
}
else if (strcmp(cmd, "ls") == 0) {
if (!fs_root) {
uart_print("No filesystem mounted.\n");
} else {
- uart_print("Files:\n");
- for(int i=0; i<n_root_nodes; i++) {
- uart_print(" ");
- uart_print(root_nodes[i].name);
- uart_print("\n");
- }
+ uart_print("Filesystem Mounted (InitRD).\n");
+ uart_print("Try: cat test.txt\n");
}
}
else if (strncmp(cmd, "cat ", 4) == 0) {
uart_print("No filesystem mounted.\n");
} else {
char* fname = cmd + 4;
- // Trim spaces?
- fs_node_t* file = NULL;
- if (fs_root->finddir)
- file = fs_root->finddir(fs_root, fname);
-
+ fs_node_t* file = fs_root->finddir(fs_root, fname);
if (file) {
- // Alloc buffer or use stack
- uint8_t buf[1024];
- // Cap read at 1023
- uint32_t len = file->length > 1023 ? 1023 : file->length;
-
- vfs_read(file, 0, len, buf);
- buf[len] = 0;
- uart_print((char*)buf);
- uart_print("\n");
+ uart_print("Reading "); uart_print(fname); uart_print("...\n");
+ uint8_t* buf = (uint8_t*)kmalloc(file->length + 1);
+ if (buf) {
+ uint32_t sz = vfs_read(file, 0, file->length, buf);
+ buf[sz] = 0;
+ uart_print((char*)buf);
+ uart_print("\n");
+ kfree(buf);
+ } else {
+ uart_print("OOM: File too big for heap.\n");
+ }
} else {
uart_print("File not found.\n");
}
}
}
else if (strcmp(cmd, "clear") == 0) {
- // ANSI clear screen for UART
uart_print("\033[2J\033[1;1H");
}
else if (strncmp(cmd, "sleep ", 6) == 0) {
uart_print("Woke up!\n");
}
else if (strcmp(cmd, "mem") == 0) {
- // pmm_print_stats() is not impl yet, so let's fake it or add it
uart_print("Memory Stats:\n");
uart_print(" Total RAM: [TODO] MB\n");
- uart_print(" Used: [TODO] KB\n");
- uart_print(" Free: [TODO] KB\n");
}
else if (strcmp(cmd, "panic") == 0) {
- // Trigger Int 0 (Div by zero)
- int a = 1;
- int b = 0;
- int c = a / b;
- (void)c;
+ int a = 1; int b = 0; int c = a / b; (void)c;
}
else if (strcmp(cmd, "reboot") == 0) {
- // 8042 keyboard controller reset command
uint8_t good = 0x02;
- while (good & 0x02)
- good = inb(0x64);
+ while (good & 0x02) good = inb(0x64);
outb(0x64, 0xFE);
-
- // Triple Fault fallback
- // idt_set_gate(0, 0, 0, 0);
- // __asm__("int $0");
}
else if (strlen(cmd) > 0) {
uart_print("Unknown command: ");
}
void shell_callback(char c) {
- // Echo to screen
char str[2] = { c, 0 };
if (c == '\n') {
- cmd_buffer[cmd_index] = 0; // Null terminate
+ cmd_buffer[cmd_index] = 0;
execute_command(cmd_buffer);
cmd_index = 0;
}
else if (c == '\b') {
if (cmd_index > 0) {
cmd_index--;
- uart_print("\b \b"); // Backspace hack
+ uart_print("\b \b");
}
}
else {
return dst;
}
+char* strcpy(char* dest, const char* src) {
+ char* saved = dest;
+ while (*src) {
+ *dest++ = *src++;
+ }
+ *dest = 0;
+ return saved;
+}
+
void reverse(char* str, int length) {
int start = 0;
int end = length - 1;
#include <stdint.h>
struct initrd_header {
- uint32_t nfiles;
-};
-
-struct initrd_file_header {
- uint8_t magic;
+ uint8_t magic; // Unused for now
char name[64];
uint32_t offset;
uint32_t length;
int main(int argc, char **argv) {
if (argc < 3) {
- printf("Usage: %s <output.img> <file1> [file2] ...\n", argv[0]);
+ printf("Usage: %s <output> <file1> [file2] ...\n", argv[0]);
return 1;
}
-
- int nfiles = argc - 2;
- struct initrd_header header;
- header.nfiles = nfiles;
-
- struct initrd_file_header *headers = malloc(sizeof(struct initrd_file_header) * nfiles);
- // First pass: Calculate offsets
- uint32_t data_offset = sizeof(struct initrd_header) + (sizeof(struct initrd_file_header) * nfiles);
+ int nheader = argc - 2;
+ struct initrd_header headers[nheader];
- printf("Creating InitRD with %d files...\n", nfiles);
-
- for (int i = 0; i < nfiles; i++) {
- char* fname = argv[i+2];
-
- // Strip path, keep filename
- char* basename = strrchr(fname, '/');
- if (basename) basename++; else basename = fname;
+ // Calculate offsets
+ // Data starts after: [4 bytes count] + [headers * n]
+ uint32_t data_offset = sizeof(uint32_t) + (sizeof(struct initrd_header) * nheader);
+
+ printf("Creating InitRD with %d files...\n", nheader);
+
+ // Prepare headers
+ for(int i = 0; i < nheader; i++) {
+ printf("Adding: %s\n", argv[i+2]);
+ strcpy(headers[i].name, argv[i+2]); // Warning: Buffer overflow unsafe, good enough for tool
+ headers[i].offset = data_offset;
+ headers[i].magic = 0xBF;
- FILE* f = fopen(fname, "rb");
- if (!f) {
- perror("Error opening file");
+ FILE *stream = fopen(argv[i+2], "r");
+ if(!stream) {
+ printf("Error opening file: %s\n", argv[i+2]);
return 1;
}
- fseek(f, 0, SEEK_END);
- uint32_t len = ftell(f);
- fclose(f);
-
- headers[i].magic = 0xBF;
- strncpy(headers[i].name, basename, 63);
- headers[i].offset = data_offset; // Absolute offset from file start
- headers[i].length = len;
-
- printf(" File: %s (Size: %d bytes, Offset: %d)\n", basename, len, data_offset);
-
- data_offset += len;
+ fseek(stream, 0, SEEK_END);
+ headers[i].length = ftell(stream);
+ data_offset += headers[i].length;
+ fclose(stream);
}
-
- FILE *w = fopen(argv[1], "wb");
- if (!w) {
- perror("Error opening output");
+
+ FILE *wstream = fopen(argv[1], "w");
+ if(!wstream) {
+ printf("Error opening output: %s\n", argv[1]);
return 1;
}
-
- fwrite(&header, sizeof(struct initrd_header), 1, w);
- fwrite(headers, sizeof(struct initrd_file_header), nfiles, w);
-
- // Second pass: Write data
- for (int i = 0; i < nfiles; i++) {
- FILE* f = fopen(argv[i+2], "rb");
- uint8_t *buf = malloc(headers[i].length);
- fread(buf, 1, headers[i].length, f);
- fwrite(buf, 1, headers[i].length, w);
+
+ // Write count
+ fwrite(&nheader, sizeof(uint32_t), 1, wstream);
+ // Write headers
+ fwrite(headers, sizeof(struct initrd_header), nheader, wstream);
+
+ // Write data
+ for(int i = 0; i < nheader; i++) {
+ FILE *stream = fopen(argv[i+2], "r");
+ unsigned char *buf = (unsigned char *)malloc(headers[i].length);
+ fread(buf, 1, headers[i].length, stream);
+ fwrite(buf, 1, headers[i].length, wstream);
+ fclose(stream);
free(buf);
- fclose(f);
}
-
- fclose(w);
- free(headers);
- printf("Done! Wrote %s\n", argv[1]);
+
+ fclose(wstream);
+ printf("Done. InitRD size: %d bytes.\n", data_offset);
return 0;
}