### Criar ISO Bootável (GRUB)
Para x86, precisamos empacotar o kernel numa ISO com GRUB.
-Crie um arquivo `grub.cfg` em `iso_root/boot/grub/`:
+1. Compile o gerador de InitRD:
+```bash
+gcc tools/mkinitrd.c -o mkinitrd
+```
+
+2. Crie arquivos de teste:
+```bash
+echo "Hello from File System!" > test.txt
+echo "AdrOS v0.3" > version.txt
+./mkinitrd initrd.img test.txt version.txt
+```
+
+3. Empacote a ISO:
```bash
mkdir -p iso_root/boot/grub
+cp adros-x86.bin iso_root/boot/
+cp initrd.img iso_root/boot/
+
cat > iso_root/boot/grub/grub.cfg << EOF
menuentry "AdrOS" {
multiboot2 /boot/adros-x86.bin
+ module2 /boot/initrd.img
boot
}
EOF
-cp adros-x86.bin iso_root/boot/
grub-mkrescue -o adros.iso iso_root
```
--- /dev/null
+#ifndef FS_H
+#define FS_H
+
+#include <stdint.h>
+#include <stddef.h>
+
+#define FS_FILE 0x01
+#define FS_DIRECTORY 0x02
+#define FS_CHARDEVICE 0x03
+#define FS_BLOCKDEVICE 0x04
+
+typedef struct fs_node {
+ char name[128];
+ uint32_t flags;
+ uint32_t inode;
+ uint32_t length;
+
+ // Function pointers for operations (Polymorphism in C)
+ uint32_t (*read)(struct fs_node* node, uint32_t offset, uint32_t size, uint8_t* buffer);
+ uint32_t (*write)(struct fs_node* node, uint32_t offset, uint32_t size, uint8_t* buffer);
+ void (*open)(struct fs_node* node);
+ void (*close)(struct fs_node* node);
+ struct fs_node* (*finddir)(struct fs_node* node, char* name);
+} fs_node_t;
+
+// Standard VFS functions
+uint32_t vfs_read(fs_node_t* node, uint32_t offset, uint32_t size, uint8_t* buffer);
+uint32_t vfs_write(fs_node_t* node, uint32_t offset, uint32_t size, uint8_t* buffer);
+void vfs_open(fs_node_t* node);
+void vfs_close(fs_node_t* node);
+
+// Global root of the filesystem
+extern fs_node_t* fs_root;
+
+#endif
--- /dev/null
+#ifndef INITRD_H
+#define INITRD_H
+
+#include "fs.h"
+#include <stdint.h>
+
+typedef struct {
+ uint8_t magic; // Magic number 0xBF
+ char name[64];
+ uint32_t offset; // Offset relative to start of initrd
+ uint32_t length;
+} initrd_file_header_t;
+
+// Initialize InitRD and return the root node (directory)
+fs_node_t* initrd_init(uint32_t location);
+
+#endif
struct multiboot_mmap_entry entries[0];
};
+struct multiboot_tag_module {
+ uint32_t type;
+ uint32_t size;
+ uint32_t mod_start;
+ uint32_t mod_end;
+ char cmdline[0];
+};
+
struct multiboot_mmap_entry {
uint64_t addr;
uint64_t len;
size_t strlen(const char* str);
int strcmp(const char* s1, const char* s2);
int strncmp(const char* s1, const char* s2, size_t n);
+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);
--- /dev/null
+#include "initrd.h"
+#include "heap.h"
+#include "utils.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 + 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.
+
+ uint8_t* data = (uint8_t*)((uint32_t)initrd_header + header.offset);
+
+ memcpy(buffer, data + offset, 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
+
+ for (int i = 0; i < n_root_nodes; i++) {
+ if (strcmp(name, root_nodes[i].name) == 0) {
+ return &root_nodes[i];
+ }
+ }
+ return NULL;
+}
+
+fs_node_t* initrd_init(uint32_t location) {
+ uart_print("[INITRD] Initializing at address: ");
+ // TODO: Print hex location
+ uart_print("\n");
+
+ initrd_header = (initrd_header_t*)location;
+ file_headers = (initrd_file_header_t*)(location + sizeof(initrd_header_t));
+
+ // 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;
+
+ // 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;
+
+ // Create File Nodes
+ 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
+
+ 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].flags = FS_FILE;
+ root_nodes[i].read = &initrd_read;
+
+ // Debug
+ uart_print(" Found file: ");
+ uart_print(root_nodes[i].name);
+ uart_print("\n");
+ }
+
+ return initrd_root;
+}
--- /dev/null
+#include "fs.h"
+
+fs_node_t* fs_root = NULL;
+
+uint32_t vfs_read(fs_node_t* node, uint32_t offset, uint32_t size, uint8_t* buffer) {
+ if (node->read)
+ return node->read(node, offset, size, buffer);
+ return 0;
+}
+
+uint32_t vfs_write(fs_node_t* node, uint32_t offset, uint32_t size, uint8_t* buffer) {
+ if (node->write)
+ return node->write(node, offset, size, buffer);
+ return 0;
+}
+
+void vfs_open(fs_node_t* node) {
+ if (node->open)
+ node->open(node);
+}
+
+void vfs_close(fs_node_t* node) {
+ if (node->close)
+ node->close(node);
+}
#include "shell.h"
#include "heap.h"
#include "timer.h"
+#include "fs.h"
+#include "initrd.h"
+#include "multiboot2.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 Interrupts (x86)
+ // 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)
uart_print("[AdrOS] Initializing IDT...\n");
idt_init();
- // 6. Initialize Drivers
+ // 7. Initialize Drivers
keyboard_init();
- // 7. Initialize Multitasking
+ // 8. Initialize Multitasking
uart_print("[AdrOS] Initializing Scheduler...\n");
process_init();
- // 8. Start Timer (Preemption!) - 50Hz
+ // 9. Start Timer (Preemption!) - 50Hz
timer_init(50);
// Start Shell as the main interaction loop
#include "utils.h"
#include "pmm.h"
#include "vga_console.h"
-#include "process.h" // For sleep
+#include "process.h"
+#include "fs.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 $> ");
}
if (strcmp(cmd, "help") == 0) {
uart_print("Available commands:\n");
uart_print(" help - Show this list\n");
- uart_print(" clear - Clear screen (if VGA)\n");
+ uart_print(" clear - Clear screen\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 (50Hz)\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");
+ }
+ }
+ }
+ else if (strncmp(cmd, "cat ", 4) == 0) {
+ if (!fs_root) {
+ 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);
+
+ 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");
+ } 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");
return sign * res;
}
+char* strcpy(char* dest, const char* src) {
+ char* temp = dest;
+ while ((*dest++ = *src++));
+ return temp;
+}
+
void itoa_hex(uint32_t num, char* str) {
const char hex_chars[] = "0123456789ABCDEF";
str[0] = '0';
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+
+struct initrd_header {
+ uint32_t nfiles;
+};
+
+struct initrd_file_header {
+ uint8_t magic;
+ 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]);
+ 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);
+
+ 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;
+
+ FILE* f = fopen(fname, "rb");
+ if (!f) {
+ perror("Error opening file");
+ 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;
+ }
+
+ FILE *w = fopen(argv[1], "wb");
+ if (!w) {
+ perror("Error opening output");
+ 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);
+ free(buf);
+ fclose(f);
+ }
+
+ fclose(w);
+ free(headers);
+ printf("Done! Wrote %s\n", argv[1]);
+
+ return 0;
+}