From 3debf9908291586cddb70d3a4d8efb57c8d80bc6 Mon Sep 17 00:00:00 2001 From: Bas Wijnen Date: Thu, 31 Dec 2009 11:22:25 +0100 Subject: [PATCH] towards a usb filesystem --- Makefile | 4 ++ bootstrap/init.ccp | 135 ++++++++++++++++++++++++++++++++++-- iris.hhp | 32 +++++++++ mips/nanonote/Makefile.arch | 3 + 4 files changed, 167 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 62ea604..a193bfc 100644 --- a/Makefile +++ b/Makefile @@ -49,5 +49,9 @@ PYPP = /usr/bin/pypp clean: rm -f *.o boot-programs/*.o $(BUILT_SOURCES) $(ARCH_CLEAN_FILES) +debug: + stty -F /dev/ttyS0 raw 9600 + cat /dev/ttyS0 + .PHONY: clean .PRECIOUS: iris.hh kernel.hh boot-programs/crt0.o diff --git a/bootstrap/init.ccp b/bootstrap/init.ccp index 3f050c2..a70fb3c 100644 --- a/bootstrap/init.ccp +++ b/bootstrap/init.ccp @@ -30,8 +30,10 @@ static unsigned num_files static file *files static unsigned index static Kernel::Memory top_memory +static unsigned slot static unsigned max_pages static char *mapping +static unsigned current_thread // Get the initial block device and filesystem. static Directory receive_devices (): @@ -112,25 +114,144 @@ static void sort (): index[i + 1] = index[i] index[i + 1] = f -static void run (file *f): +static void run (file *f, bool priv): Kernel::Memory mem = top_memory.create_memory () unsigned num_pages = (f->size + PAGE_SIZE - 1) & PAGE_MASK for unsigned p = 0; p < num_pages; ++p: - pages[p] = f->string.get_page (p << PAGE_BITS, mem.create_page ()) - Kernel::my_memory.map (pages[p], (unsigned)&mapping[p << PAGE_BITS]) - // TODO: parse elf file. + Kernel::set_recv_arg (Kernel::Cap (slot, p)) + mem.create_page () + f->string.get_page (p << PAGE_BITS, Kernel::Cap (slot, p)) + Kernel::my_memory.map (Kernel::Cap (slot, p), (unsigned)&mapping[p << PAGE_BITS]) + Kernel::Thread *thread = mem.create_thread (NUM_SLOTS) + if priv: + thread.make_priv () + Elf32_Ehdr *header = (Elf32_Ehdr *)mapping + for unsigned j = 0; j < SELFMAG; ++j: + if header->e_ident[j] != ELFMAG[j]: + kdebug ("invalid ELF magic\n") + Kernel::panic (0) + return + if header->e_ident[EI_CLASS] != ELFCLASS32: + kdebug ("invalid ELF class\n") + Kernel::panic (0) + return + if header->e_ident[EI_DATA] != ELFDATA2LSB: + kdebug ("invalid ELF data\n") + Kernel::panic (0) + return + if header->e_ident[EI_VERSION] != EV_CURRENT: + kdebug ("invalid ELF version\n") + Kernel::panic (0) + return + if header->e_type != ET_EXEC: + kdebug ("invalid ELF type\n") + Kernel::panic (0) + return + if header->e_machine != EM_MIPS_RS3_LE && header->e_machine != EM_MIPS: + kdebug ("invalid ELF machine\n") + Kernel::panic (0) + return + thread.set_pc (header->e_entry) + thread.set_sp (0x80000000) + for unsigned section = 0; section < header->e_shnum; ++section: + Elf32_Shdr *shdr = (Elf32_Shdr *)(thread_start[i] + header->e_shoff + section * header->e_shentsize) + if ~shdr->sh_flags & SHF_ALLOC: + continue + bool readonly = !(shdr->sh_flags & SHF_WRITE) + //bool executable = shdr->sh_flags & SHF_EXEC_INSTR + if shdr->sh_type != SHT_NOBITS: + unsigned file_offset = shdr->sh_offset >> PAGE_BITS + if (file_offset + ((shdr->sh_size + PAGE_SIZE - 1) >> PAGE_BITS)) >= (PAGE_SIZE >> 2): + kdebug ("thread too large\n") + Kernel::panic (0) + return + for unsigned p = (shdr->sh_addr & PAGE_MASK); p < shdr->sh_addr + shdr->sh_size; p += PAGE_SIZE: + unsigned section_offset = (p - (shdr->sh_addr & PAGE_MASK)) >> PAGE_BITS + unsigned idx = file_offset + section_offset + Kernel::Page page = mem.mapping (p) + if page: + // The address already has a mapping; assume that it is correct. + Kernel::free_cap (page) + continue + page = mem.create_page () + Kernel::Cap (slot, idx).share (page, 0) + if !mem.map (page, p, readonly): + kdebug ("unable to map page\n") + Kernel::panic (0) + return + Kernel::free_cap (page) + else: + if readonly: + kdebug ("unwritable bss section\n") + Kernel::panic (0) + return + for unsigned p = (shdr->sh_addr & PAGE_MASK); p < shdr->sh_addr + shdr->sh_size; p += PAGE_SIZE: + kPage *page = mem->get_mapping (p) + if !page: + page = mem.create_page () + if !page: + kdebug ("out of memory\n") + Kernel::panic (0) + return + if !page.set_flags (Kernel::Page::PAYING | Kernel::Page::FRAME, Kernel::Page::PAYING | Kernel::Page::FRAME): + kdebug ("out of memory\n") + Kernel::panic (0) + return + if !mem.map (page, p): + kdebug ("unable to map bss page\n") + Kernel::panic (0) + return + Kernel::free_cap (page) + else: + for unsigned a = p; a < ((p + PAGE_SIZE) & PAGE_MASK); a += 4: + if a >= shdr->sh_addr + shdr->sh_size: + break + if a < shdr->sh_addr: + continue + ((unsigned *)&mapping[idx << PAGE_BITS])[(a & ~PAGE_MASK) >> 2] = 0 + for unsigned p = 0; p <= num_pages; ++p: + mem.destroy (Kernel::Cap (slot, p)) + Kernel::Page stackpage = mem.create_page () + stackpage.set_flags (Kernel::Page::PAYING | Kernel::Page::FRAME, Kernel::Page::PAYING | Kernel::Page::FRAME) + if !stackpage || !mem.map (stackpage, 0x7ffff000): + kdebug ("unable to map initial stack page\n") + Kernel::panic (0) + return + Kernel::free_cap (stackpage) + Kernel::Caps caps = mem.create_caps (NUM_CAPS) + thread.use (caps, 0) + thread.set_info (Kernel::Thread::A0, NUM_SLOTS) + thread.set_info (Kernel::Thread::A1, NUM_CAPS) + Kernel::Receiver receiver = mem.create_receiver () + receiver.set_owner (thread.copy ()) + Kernel::Cap call = receiver.create_call_capability () + Kernel::Cap parent = Kernel::my_receiver.create_capability (++current_thread) + caps.set (__receiver_num, receiver.copy ()) + caps.set (__thread_num, thread.copy ()) + caps.set (__memory_num, mem.copy ()) + caps.set (__call_num, call.copy ()) + caps.set (__parent_num, parent.copy ()) + thread.run () + Kernel::free_cap (receiver) + Kernel::free_cap (thread) + Kernel::free_cap (mem) + Kernel::free_cap (call) + Kernel::free_cap (parent) Kernel::Num start (): - top_memory = Kernel::get_top_memory () // Wait for the debugging device to be active, in case there is one. Kernel::schedule () + top_memory = Kernel::get_top_memory () Directory root = receive_devices () root.lock_ro () list_files (root) sort () - pages = new Kernel::Page[max_pages] + Kernel::Caps caps = Kernel::my_memory.create_caps (max_pages) + slot = caps.use () mapping = alloc_space (max_pages) for unsigned i = 0; i < num_files; ++i: - run (files[i]) + run (files[i], files[i].name[0] == '#') root.unlock_ro () + Kernel::free_slot (slot) + Kernel::my_memory.destroy (caps) return 0 diff --git a/iris.hhp b/iris.hhp index 4a63138..272aad1 100644 --- a/iris.hhp +++ b/iris.hhp @@ -323,6 +323,38 @@ namespace Kernel: PC = ~0 SP = ~1 FLAGS = ~2 + // These are arch-specific. + AT = 1 + V0 + V1 + A0 + A1 + A2 + A3 + T0 + T1 + T2 + T3 + T4 + T5 + T6 + T7 + S0 + S1 + S2 + S3 + S4 + S5 + S6 + S7 + T8 + T9 + K0 + K1 + GP + SP_ + FP + RA enum flags: PRIV = 1 << 31 WAITING = 1 << 30 diff --git a/mips/nanonote/Makefile.arch b/mips/nanonote/Makefile.arch index 81c5f36..4b62551 100644 --- a/mips/nanonote/Makefile.arch +++ b/mips/nanonote/Makefile.arch @@ -71,6 +71,9 @@ iris.elf: mips/entry.o $(subst .cc,.o,$(iris_sources)) mips/nanonote/threadlist. server: while mips/nanonote/server/usb-server ; do : ; done +servers: + while : ; do $(MAKE) server ; done + ARCH_CLEAN_FILES = $(boot_sources) $(addsuffix .elf,$(boot_threads)) $(arch_headers) devices.hh keys.hh mips/*.o mips/nanonote/*.o boot-programs/charset.data iris.elf iris.raw mips/nanonote/sdram-setup.elf mips/nanonote/sdram-setup.raw .PRECIOUS: mips/arch.hh mips/nanonote/jz4740.hh mips/nanonote/board.hh