Initial commit with Complet_Project contents
This commit is contained in:
commit
8fab4e2015
31 changed files with 610 additions and 0 deletions
20
Makefile
Normal file
20
Makefile
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
|
||||||
|
CC=aarch64-linux-gnu-gcc
|
||||||
|
LD=aarch64-linux-gnu-ld
|
||||||
|
OBJCOPY=aarch64-linux-gnu-objcopy
|
||||||
|
|
||||||
|
CFLAGS=-ffreestanding -O2 -nostdlib -Wall
|
||||||
|
LDFLAGS=-T link.ld
|
||||||
|
|
||||||
|
OBJS=startup.o kernel_main.o uart.o scheduler.o smp.o vfs.o shell.o emmc.o mmc_cmds.o profiler.o proc.o virtio_net_dma.o
|
||||||
|
|
||||||
|
all: kernel.elf
|
||||||
|
|
||||||
|
%.o: %.c
|
||||||
|
$(CC) $(CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
kernel.elf: $(OBJS)
|
||||||
|
$(LD) $(LDFLAGS) -o $@ $(OBJS)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f *.o kernel.elf
|
||||||
27
README.md
Normal file
27
README.md
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
|
||||||
|
# MiniOS
|
||||||
|
|
||||||
|
MiniOS is a simple educational operating system designed for ARM64 (QEMU and Luckfox Lyra B M).
|
||||||
|
It includes:
|
||||||
|
|
||||||
|
- Preemptive multitasking with SMP
|
||||||
|
- UART console with shell
|
||||||
|
- MMU and memory protection
|
||||||
|
- IPC and basic VFS with /proc
|
||||||
|
- Profiler and task inspector
|
||||||
|
- Networking (VirtIO + UDP)
|
||||||
|
- eMMC boot support
|
||||||
|
- ELF loader
|
||||||
|
|
||||||
|
## Build
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make
|
||||||
|
```
|
||||||
|
|
||||||
|
## Boot on Luckfox
|
||||||
|
|
||||||
|
```bash
|
||||||
|
load mmc 0:1 0x40200000 kernel.elf
|
||||||
|
bootelf 0x40200000
|
||||||
|
```
|
||||||
0
boot/boot.its
Normal file
0
boot/boot.its
Normal file
5
boot/load_boot.sh
Normal file
5
boot/load_boot.sh
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
|
||||||
|
#!/bin/sh
|
||||||
|
echo "Loading kernel to 0x40200000..."
|
||||||
|
load mmc 0:1 0x40200000 kernel.elf
|
||||||
|
bootelf 0x40200000
|
||||||
8
src/elf.c
Normal file
8
src/elf.c
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
#include "elf.h"
|
||||||
|
#include "uart.h"
|
||||||
|
|
||||||
|
int elf_load(const void *elf_data) {
|
||||||
|
uart_puts("[ELF] Loading ELF...\n");
|
||||||
|
// Stub - parse headers, map segments
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
6
src/elf.h
Normal file
6
src/elf.h
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
#ifndef ELF_H
|
||||||
|
#define ELF_H
|
||||||
|
|
||||||
|
int elf_load(const void *elf_data);
|
||||||
|
|
||||||
|
#endif
|
||||||
43
src/emmc.c
Normal file
43
src/emmc.c
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
|
||||||
|
#include "emmc.h"
|
||||||
|
#include "uart.h"
|
||||||
|
#include "mmio.h"
|
||||||
|
#include "delay.h"
|
||||||
|
|
||||||
|
#define EMMC_BASE 0x10005000
|
||||||
|
#define EMMC_ARG2 (EMMC_BASE + 0x00)
|
||||||
|
#define EMMC_BLKSZCNT (EMMC_BASE + 0x04)
|
||||||
|
#define EMMC_CMDTM (EMMC_BASE + 0x08)
|
||||||
|
#define EMMC_RESP0 (EMMC_BASE + 0x0C)
|
||||||
|
#define EMMC_DATA (EMMC_BASE + 0x20)
|
||||||
|
#define EMMC_STATUS (EMMC_BASE + 0x24)
|
||||||
|
|
||||||
|
void emmc_init(void) {
|
||||||
|
uart_print("[emmc] Init sequence...\n");
|
||||||
|
mmio_write(EMMC_CMDTM, 0x00000000); // Reset command
|
||||||
|
delay(1000);
|
||||||
|
uart_print("[emmc] Init done\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
int emmc_read_block(uint32_t lba, uint8_t *buffer) {
|
||||||
|
mmio_write(EMMC_ARG2, lba);
|
||||||
|
mmio_write(EMMC_BLKSZCNT, (1 << 16) | 512); // 1 block
|
||||||
|
mmio_write(EMMC_CMDTM, 0x11200010); // CMD17 read single
|
||||||
|
|
||||||
|
while (mmio_read(EMMC_STATUS) & 0x2); // wait for ready
|
||||||
|
|
||||||
|
for (int i = 0; i < 128; i++) {
|
||||||
|
((uint32_t*)buffer)[i] = mmio_read(EMMC_DATA);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int emmc_boot(void) {
|
||||||
|
uart_print("[emmc] Booting...\n");
|
||||||
|
uint8_t *image = (uint8_t *)0x8000000;
|
||||||
|
emmc_read_block(2048, image); // Read first boot block
|
||||||
|
void (*entry)(void) = (void (*)(void))(image);
|
||||||
|
entry();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
11
src/emmc.h
Normal file
11
src/emmc.h
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
|
||||||
|
#ifndef EMMC_H
|
||||||
|
#define EMMC_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
void emmc_init(void);
|
||||||
|
int emmc_read_block(uint32_t lba, uint8_t *buffer);
|
||||||
|
int emmc_boot(void);
|
||||||
|
|
||||||
|
#endif
|
||||||
38
src/ipc.c
Normal file
38
src/ipc.c
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
|
||||||
|
#include "ipc.h"
|
||||||
|
#include "scheduler.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define MAX_MSGS 8
|
||||||
|
#define MAX_TASKS 16
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ipc_msg_t queue[MAX_MSGS];
|
||||||
|
int head, tail, count;
|
||||||
|
} ipc_queue_t;
|
||||||
|
|
||||||
|
static ipc_queue_t ipc_queues[MAX_TASKS];
|
||||||
|
|
||||||
|
void ipc_init(void) {
|
||||||
|
memset(ipc_queues, 0, sizeof(ipc_queues));
|
||||||
|
}
|
||||||
|
|
||||||
|
int ipc_send(uint64_t to_id, ipc_msg_t msg) {
|
||||||
|
if (to_id >= MAX_TASKS) return -1;
|
||||||
|
ipc_queue_t *q = &ipc_queues[to_id];
|
||||||
|
if (q->count >= MAX_MSGS) return -2;
|
||||||
|
q->queue[q->tail] = msg;
|
||||||
|
q->tail = (q->tail + 1) % MAX_MSGS;
|
||||||
|
q->count++;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ipc_recv(ipc_msg_t *msg_out) {
|
||||||
|
uint64_t id = scheduler_get_current()->id;
|
||||||
|
ipc_queue_t *q = &ipc_queues[id];
|
||||||
|
if (q->count == 0) return -3;
|
||||||
|
*msg_out = q->queue[q->head];
|
||||||
|
q->head = (q->head + 1) % MAX_MSGS;
|
||||||
|
q->count--;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
16
src/ipc.h
Normal file
16
src/ipc.h
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
|
||||||
|
#ifndef IPC_H
|
||||||
|
#define IPC_H
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint64_t from;
|
||||||
|
uint32_t type;
|
||||||
|
uint64_t data;
|
||||||
|
} ipc_msg_t;
|
||||||
|
|
||||||
|
int ipc_send(uint64_t to_task_id, ipc_msg_t msg);
|
||||||
|
int ipc_recv(ipc_msg_t *msg_out);
|
||||||
|
void ipc_init(void);
|
||||||
|
|
||||||
|
#endif
|
||||||
13
src/kernel_main.c
Normal file
13
src/kernel_main.c
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
|
||||||
|
#include "uart.h"
|
||||||
|
#include "smp.h"
|
||||||
|
#include "scheduler.h"
|
||||||
|
|
||||||
|
void kernel_main(void) {
|
||||||
|
uart_init();
|
||||||
|
smp_init();
|
||||||
|
scheduler_init();
|
||||||
|
while (1) {
|
||||||
|
scheduler_schedule();
|
||||||
|
}
|
||||||
|
}
|
||||||
9
src/mmc_cmds.c
Normal file
9
src/mmc_cmds.c
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
// Placeholder for MMC commands implementation
|
||||||
|
// To be implemented depending on hardware or simulation platform
|
||||||
|
|
||||||
|
int mmc_send_cmd(uint32_t cmd, uint32_t arg) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
24
src/mmu.c
Normal file
24
src/mmu.c
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define PAGE_SIZE 4096
|
||||||
|
#define PAGE_TABLE_SIZE 4096
|
||||||
|
#define MAIR_VALUE 0xFF
|
||||||
|
|
||||||
|
static uint64_t __attribute__((aligned(PAGE_SIZE))) l1_table[512];
|
||||||
|
|
||||||
|
void mmu_init(void) {
|
||||||
|
for (int i = 0; i < 512; i++) {
|
||||||
|
l1_table[i] = (i << 30) | (0b11 << 0) | (0b01 << 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
asm volatile("msr mair_el1, %0" :: "r"(MAIR_VALUE));
|
||||||
|
uint64_t tcr = (16ULL << 0) | (16ULL << 16);
|
||||||
|
asm volatile("msr tcr_el1, %0" :: "r"(tcr));
|
||||||
|
uint64_t ttbr = (uint64_t)l1_table;
|
||||||
|
asm volatile("msr ttbr0_el1, %0" :: "r"(ttbr));
|
||||||
|
uint64_t sctlr;
|
||||||
|
asm volatile("mrs %0, sctlr_el1" : "=r"(sctlr));
|
||||||
|
sctlr |= (1 << 0) | (1 << 2) | (1 << 12);
|
||||||
|
asm volatile("msr sctlr_el1, %0" :: "r"(sctlr));
|
||||||
|
asm volatile("isb");
|
||||||
|
}
|
||||||
6
src/mmu.h
Normal file
6
src/mmu.h
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
#ifndef MMU_H
|
||||||
|
#define MMU_H
|
||||||
|
|
||||||
|
void mmu_init(void);
|
||||||
|
|
||||||
|
#endif
|
||||||
18
src/proc.c
Normal file
18
src/proc.c
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
|
||||||
|
#include "uart.h"
|
||||||
|
#include "scheduler.h"
|
||||||
|
#include "profiler.h"
|
||||||
|
|
||||||
|
void proc_uptime(void) {
|
||||||
|
extern int global_ticks;
|
||||||
|
uart_print("Uptime: ");
|
||||||
|
uart_print_int(global_ticks / 100);
|
||||||
|
uart_print(" seconds\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void proc_meminfo(void) {
|
||||||
|
extern int free_pages;
|
||||||
|
uart_print("Free memory pages: ");
|
||||||
|
uart_print_int(free_pages);
|
||||||
|
uart_print("\n");
|
||||||
|
}
|
||||||
28
src/profiler.c
Normal file
28
src/profiler.c
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
|
||||||
|
#include "profiler.h"
|
||||||
|
#include "uart.h"
|
||||||
|
|
||||||
|
#define MAX_TASKS 16
|
||||||
|
static int task_ticks[MAX_TASKS];
|
||||||
|
|
||||||
|
void profiler_init(void) {
|
||||||
|
for (int i = 0; i < MAX_TASKS; i++) task_ticks[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void profiler_tick(void) {
|
||||||
|
extern int current_task_id;
|
||||||
|
task_ticks[current_task_id]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void profiler_report(void) {
|
||||||
|
uart_print("CPU Time per Task:\n");
|
||||||
|
for (int i = 0; i < MAX_TASKS; i++) {
|
||||||
|
if (task_ticks[i]) {
|
||||||
|
uart_print("Task ");
|
||||||
|
uart_print_int(i);
|
||||||
|
uart_print(": ");
|
||||||
|
uart_print_int(task_ticks[i]);
|
||||||
|
uart_print(" ticks\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
9
src/profiler.h
Normal file
9
src/profiler.h
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
|
||||||
|
#ifndef PROFILER_H
|
||||||
|
#define PROFILER_H
|
||||||
|
|
||||||
|
void profiler_init(void);
|
||||||
|
void profiler_tick(void);
|
||||||
|
void profiler_report(void);
|
||||||
|
|
||||||
|
#endif
|
||||||
30
src/scheduler.c
Normal file
30
src/scheduler.c
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
|
||||||
|
#include "scheduler.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define MAX_TASKS 16
|
||||||
|
static task_t tasks[MAX_TASKS];
|
||||||
|
static int task_count = 0;
|
||||||
|
static task_t *current = NULL;
|
||||||
|
|
||||||
|
void scheduler_init(void) {
|
||||||
|
memset(tasks, 0, sizeof(tasks));
|
||||||
|
task_count = 0;
|
||||||
|
current = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void scheduler_add(task_t *t) {
|
||||||
|
if (task_count < MAX_TASKS) {
|
||||||
|
tasks[task_count++] = *t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
task_t *scheduler_get_current(void) {
|
||||||
|
return current;
|
||||||
|
}
|
||||||
|
|
||||||
|
void scheduler_schedule(void) {
|
||||||
|
static int i = 0;
|
||||||
|
current = &tasks[i];
|
||||||
|
i = (i + 1) % task_count;
|
||||||
|
}
|
||||||
17
src/scheduler.h
Normal file
17
src/scheduler.h
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
|
||||||
|
#ifndef SCHEDULER_H
|
||||||
|
#define SCHEDULER_H
|
||||||
|
|
||||||
|
typedef struct task {
|
||||||
|
int id;
|
||||||
|
int state;
|
||||||
|
void *stack;
|
||||||
|
void *stack_top;
|
||||||
|
} task_t;
|
||||||
|
|
||||||
|
void scheduler_init(void);
|
||||||
|
void scheduler_add(task_t *t);
|
||||||
|
void scheduler_schedule(void);
|
||||||
|
task_t *scheduler_get_current(void);
|
||||||
|
|
||||||
|
#endif
|
||||||
38
src/shell.c
Normal file
38
src/shell.c
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
|
||||||
|
#include "uart.h"
|
||||||
|
#include "vfs.h"
|
||||||
|
#include "scheduler.h"
|
||||||
|
#include "proc.h"
|
||||||
|
|
||||||
|
void shell_loop(void) {
|
||||||
|
char buf[128];
|
||||||
|
while (1) {
|
||||||
|
uart_print("> ");
|
||||||
|
int i = 0;
|
||||||
|
while (1) {
|
||||||
|
char c = uart_getc();
|
||||||
|
if (c == '\r' || c == '\n') break;
|
||||||
|
if (i < 127) buf[i++] = c;
|
||||||
|
uart_putc(c);
|
||||||
|
}
|
||||||
|
buf[i] = 0;
|
||||||
|
uart_print("\n");
|
||||||
|
|
||||||
|
if (strcmp(buf, "ps") == 0) {
|
||||||
|
extern void scheduler_list_tasks(void);
|
||||||
|
scheduler_list_tasks();
|
||||||
|
} else if (strcmp(buf, "uptime") == 0) {
|
||||||
|
proc_uptime();
|
||||||
|
} else if (strcmp(buf, "meminfo") == 0) {
|
||||||
|
proc_meminfo();
|
||||||
|
} else if (strncmp(buf, "cat ", 4) == 0) {
|
||||||
|
const char *data = vfs_read(buf + 4);
|
||||||
|
if (data)
|
||||||
|
uart_print(data);
|
||||||
|
else
|
||||||
|
uart_print("File not found\n");
|
||||||
|
} else {
|
||||||
|
uart_print("Unknown command\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
26
src/smp.c
Normal file
26
src/smp.c
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
|
||||||
|
#include "uart.h"
|
||||||
|
|
||||||
|
volatile int core_ready[4];
|
||||||
|
|
||||||
|
int get_core_id(void) {
|
||||||
|
uint64_t mpidr;
|
||||||
|
asm volatile("mrs %0, mpidr_el1" : "=r"(mpidr));
|
||||||
|
return mpidr & 0b11;
|
||||||
|
}
|
||||||
|
|
||||||
|
void core_entry(void) {
|
||||||
|
int cid = get_core_id();
|
||||||
|
uart_puts("Core ");
|
||||||
|
uart_putc('0' + cid);
|
||||||
|
uart_puts(" ready\n");
|
||||||
|
core_ready[cid] = 1;
|
||||||
|
while (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void smp_init(void) {
|
||||||
|
for (int i = 1; i < 4; i++) {
|
||||||
|
*(volatile uint64_t *)(0x4000008 + i * 8) = (uint64_t)core_entry;
|
||||||
|
asm volatile("sev");
|
||||||
|
}
|
||||||
|
}
|
||||||
6
src/startup.s
Normal file
6
src/startup.s
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
|
||||||
|
.section .text
|
||||||
|
.global _start
|
||||||
|
_start:
|
||||||
|
bl kernel_main
|
||||||
|
b .
|
||||||
26
src/switch.S
Normal file
26
src/switch.S
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
|
||||||
|
.global context_switch
|
||||||
|
.type context_switch, %function
|
||||||
|
|
||||||
|
context_switch:
|
||||||
|
// Save callee-saved registers
|
||||||
|
stp x19, x20, [x0]
|
||||||
|
stp x21, x22, [x0, #16]
|
||||||
|
stp x23, x24, [x0, #32]
|
||||||
|
stp x25, x26, [x0, #48]
|
||||||
|
stp x27, x28, [x0, #64]
|
||||||
|
str x29, [x0, #80]
|
||||||
|
str x30, [x0, #88]
|
||||||
|
str sp, [x0, #96]
|
||||||
|
|
||||||
|
// Load new task context
|
||||||
|
ldp x19, x20, [x1]
|
||||||
|
ldp x21, x22, [x1, #16]
|
||||||
|
ldp x23, x24, [x1, #32]
|
||||||
|
ldp x25, x26, [x1, #48]
|
||||||
|
ldp x27, x28, [x1, #64]
|
||||||
|
ldr x29, [x1, #80]
|
||||||
|
ldr x30, [x1, #88]
|
||||||
|
ldr sp, [x1, #96]
|
||||||
|
|
||||||
|
ret
|
||||||
32
src/task.c
Normal file
32
src/task.c
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
|
||||||
|
#include "scheduler.h"
|
||||||
|
#include "uart.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define MAX_TASKS 16
|
||||||
|
static task_t tasks[MAX_TASKS];
|
||||||
|
static int task_count = 0;
|
||||||
|
static task_t *current = NULL;
|
||||||
|
|
||||||
|
void scheduler_init(void) {
|
||||||
|
memset(tasks, 0, sizeof(tasks));
|
||||||
|
task_count = 0;
|
||||||
|
current = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void scheduler_add(task_t *t) {
|
||||||
|
if (task_count < MAX_TASKS) {
|
||||||
|
tasks[task_count++] = *t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
task_t *scheduler_get_current(void) {
|
||||||
|
return current;
|
||||||
|
}
|
||||||
|
|
||||||
|
void scheduler_schedule(void) {
|
||||||
|
static int i = 0;
|
||||||
|
current = &tasks[i];
|
||||||
|
i = (i + 1) % task_count;
|
||||||
|
}
|
||||||
35
src/uart.c
Normal file
35
src/uart.c
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define UART0_BASE 0x09000000
|
||||||
|
#define UARTFR (*(volatile uint32_t *)(UART0_BASE + 0x18))
|
||||||
|
#define UARTDR (*(volatile uint32_t *)(UART0_BASE + 0x00))
|
||||||
|
|
||||||
|
void uart_init(void) {}
|
||||||
|
|
||||||
|
void uart_putc(char c) {
|
||||||
|
while (UARTFR & (1 << 5));
|
||||||
|
UARTDR = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
void uart_puts(const char *s) {
|
||||||
|
while (*s) uart_putc(*s++);
|
||||||
|
}
|
||||||
|
|
||||||
|
void uart_print(const char *s) {
|
||||||
|
uart_puts(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
void uart_print_int(int x) {
|
||||||
|
char buf[16];
|
||||||
|
int i = 0;
|
||||||
|
if (x == 0) {
|
||||||
|
uart_putc('0');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
while (x > 0) {
|
||||||
|
buf[i++] = '0' + (x % 10);
|
||||||
|
x /= 10;
|
||||||
|
}
|
||||||
|
while (i--) uart_putc(buf[i]);
|
||||||
|
}
|
||||||
11
src/uart.h
Normal file
11
src/uart.h
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
|
||||||
|
#ifndef UART_H
|
||||||
|
#define UART_H
|
||||||
|
|
||||||
|
void uart_init(void);
|
||||||
|
void uart_putc(char c);
|
||||||
|
void uart_puts(const char *s);
|
||||||
|
void uart_print(const char *s);
|
||||||
|
void uart_print_int(int x);
|
||||||
|
|
||||||
|
#endif
|
||||||
12
src/usb.c
Normal file
12
src/usb.c
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
#include "usb.h"
|
||||||
|
#include "uart.h"
|
||||||
|
|
||||||
|
void usb_init(void) {
|
||||||
|
uart_puts("[USB] Initializing USB Host...\n");
|
||||||
|
// Placeholder logic - real implementation would probe EHCI/OHCI/XHCI
|
||||||
|
}
|
||||||
|
|
||||||
|
int usb_read_bulk(int device, void *buffer, int length) {
|
||||||
|
uart_puts("[USB] Reading bulk data...\n");
|
||||||
|
return -1; // Not implemented
|
||||||
|
}
|
||||||
7
src/usb.h
Normal file
7
src/usb.h
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
#ifndef USB_H
|
||||||
|
#define USB_H
|
||||||
|
|
||||||
|
void usb_init(void);
|
||||||
|
int usb_read_bulk(int device, void *buffer, int length);
|
||||||
|
|
||||||
|
#endif
|
||||||
29
src/vfs.c
Normal file
29
src/vfs.c
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
|
||||||
|
#include "vfs.h"
|
||||||
|
#include "uart.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
static vfs_file_t files[] = {
|
||||||
|
{ "/dev/info.txt", "MiniOS v1.0 - Built July 2025\n" },
|
||||||
|
{ "/proc/version", "MiniOS kernel 1.0\n" },
|
||||||
|
{ NULL, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
void vfs_init(void) {}
|
||||||
|
|
||||||
|
const char *vfs_read(const char *path) {
|
||||||
|
for (int i = 0; files[i].path; i++) {
|
||||||
|
if (strcmp(files[i].path, path) == 0)
|
||||||
|
return files[i].content;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vfs_list(const char *prefix) {
|
||||||
|
size_t len = strlen(prefix);
|
||||||
|
for (int i = 0; files[i].path; i++) {
|
||||||
|
if (strncmp(files[i].path, prefix, len) == 0)
|
||||||
|
uart_puts(files[i].path + len + 1), uart_puts("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
14
src/vfs.h
Normal file
14
src/vfs.h
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
|
||||||
|
#ifndef VFS_H
|
||||||
|
#define VFS_H
|
||||||
|
|
||||||
|
typedef struct vfs_file {
|
||||||
|
const char *path;
|
||||||
|
const char *content;
|
||||||
|
} vfs_file_t;
|
||||||
|
|
||||||
|
const char *vfs_read(const char *path);
|
||||||
|
void vfs_list(const char *prefix);
|
||||||
|
void vfs_init(void);
|
||||||
|
|
||||||
|
#endif
|
||||||
46
src/virtio_net_dma.c
Normal file
46
src/virtio_net_dma.c
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
|
||||||
|
#include "uart.h"
|
||||||
|
#include "pmm.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define VIRTIO_MMIO_BASE 0x10001000
|
||||||
|
#define VIRTIO_NET_Q_TX 1
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint64_t addr;
|
||||||
|
uint32_t len;
|
||||||
|
uint16_t flags;
|
||||||
|
uint16_t next;
|
||||||
|
} __attribute__((packed)) virtq_desc_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint16_t flags;
|
||||||
|
uint16_t idx;
|
||||||
|
struct {
|
||||||
|
uint16_t id;
|
||||||
|
uint16_t len;
|
||||||
|
} ring[8];
|
||||||
|
} __attribute__((packed)) virtq_used_t;
|
||||||
|
|
||||||
|
static void *desc_area;
|
||||||
|
|
||||||
|
void virtio_net_dma_send(const void *data, int len) {
|
||||||
|
volatile uint32_t *mmio = (volatile uint32_t *)VIRTIO_MMIO_BASE;
|
||||||
|
virtq_desc_t *desc = (virtq_desc_t *)desc_area;
|
||||||
|
|
||||||
|
void *packet = pmm_alloc_page();
|
||||||
|
memcpy(packet, data, len);
|
||||||
|
|
||||||
|
desc[0].addr = (uint64_t)(uintptr_t)packet;
|
||||||
|
desc[0].len = len;
|
||||||
|
desc[0].flags = 0;
|
||||||
|
desc[0].next = 0;
|
||||||
|
|
||||||
|
virtq_used_t *used = (virtq_used_t *)((uint8_t *)desc_area + 4096);
|
||||||
|
used->ring[0].id = 0;
|
||||||
|
used->ring[0].len = len;
|
||||||
|
used->idx++;
|
||||||
|
|
||||||
|
mmio[0x070 / 4] |= 0x4; // notify
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue