mirror of
git://projects.qi-hardware.com/iris.git
synced 2025-02-06 20:21:56 +02:00
towards a usb filesystem
This commit is contained in:
parent
dc1bbc1f5f
commit
3debf99082
4
Makefile
4
Makefile
@ -49,5 +49,9 @@ PYPP = /usr/bin/pypp
|
|||||||
clean:
|
clean:
|
||||||
rm -f *.o boot-programs/*.o $(BUILT_SOURCES) $(ARCH_CLEAN_FILES)
|
rm -f *.o boot-programs/*.o $(BUILT_SOURCES) $(ARCH_CLEAN_FILES)
|
||||||
|
|
||||||
|
debug:
|
||||||
|
stty -F /dev/ttyS0 raw 9600
|
||||||
|
cat /dev/ttyS0
|
||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
.PRECIOUS: iris.hh kernel.hh boot-programs/crt0.o
|
.PRECIOUS: iris.hh kernel.hh boot-programs/crt0.o
|
||||||
|
@ -30,8 +30,10 @@ static unsigned num_files
|
|||||||
static file *files
|
static file *files
|
||||||
static unsigned index
|
static unsigned index
|
||||||
static Kernel::Memory top_memory
|
static Kernel::Memory top_memory
|
||||||
|
static unsigned slot
|
||||||
static unsigned max_pages
|
static unsigned max_pages
|
||||||
static char *mapping
|
static char *mapping
|
||||||
|
static unsigned current_thread
|
||||||
|
|
||||||
// Get the initial block device and filesystem.
|
// Get the initial block device and filesystem.
|
||||||
static Directory receive_devices ():
|
static Directory receive_devices ():
|
||||||
@ -112,25 +114,144 @@ static void sort ():
|
|||||||
index[i + 1] = index[i]
|
index[i + 1] = index[i]
|
||||||
index[i + 1] = f
|
index[i + 1] = f
|
||||||
|
|
||||||
static void run (file *f):
|
static void run (file *f, bool priv):
|
||||||
Kernel::Memory mem = top_memory.create_memory ()
|
Kernel::Memory mem = top_memory.create_memory ()
|
||||||
unsigned num_pages = (f->size + PAGE_SIZE - 1) & PAGE_MASK
|
unsigned num_pages = (f->size + PAGE_SIZE - 1) & PAGE_MASK
|
||||||
for unsigned p = 0; p < num_pages; ++p:
|
for unsigned p = 0; p < num_pages; ++p:
|
||||||
pages[p] = f->string.get_page (p << PAGE_BITS, mem.create_page ())
|
Kernel::set_recv_arg (Kernel::Cap (slot, p))
|
||||||
Kernel::my_memory.map (pages[p], (unsigned)&mapping[p << PAGE_BITS])
|
mem.create_page ()
|
||||||
// TODO: parse elf file.
|
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 ():
|
Kernel::Num start ():
|
||||||
top_memory = Kernel::get_top_memory ()
|
|
||||||
// Wait for the debugging device to be active, in case there is one.
|
// Wait for the debugging device to be active, in case there is one.
|
||||||
Kernel::schedule ()
|
Kernel::schedule ()
|
||||||
|
top_memory = Kernel::get_top_memory ()
|
||||||
Directory root = receive_devices ()
|
Directory root = receive_devices ()
|
||||||
root.lock_ro ()
|
root.lock_ro ()
|
||||||
list_files (root)
|
list_files (root)
|
||||||
sort ()
|
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)
|
mapping = alloc_space (max_pages)
|
||||||
for unsigned i = 0; i < num_files; ++i:
|
for unsigned i = 0; i < num_files; ++i:
|
||||||
run (files[i])
|
run (files[i], files[i].name[0] == '#')
|
||||||
root.unlock_ro ()
|
root.unlock_ro ()
|
||||||
|
Kernel::free_slot (slot)
|
||||||
|
Kernel::my_memory.destroy (caps)
|
||||||
return 0
|
return 0
|
||||||
|
32
iris.hhp
32
iris.hhp
@ -323,6 +323,38 @@ namespace Kernel:
|
|||||||
PC = ~0
|
PC = ~0
|
||||||
SP = ~1
|
SP = ~1
|
||||||
FLAGS = ~2
|
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:
|
enum flags:
|
||||||
PRIV = 1 << 31
|
PRIV = 1 << 31
|
||||||
WAITING = 1 << 30
|
WAITING = 1 << 30
|
||||||
|
@ -71,6 +71,9 @@ iris.elf: mips/entry.o $(subst .cc,.o,$(iris_sources)) mips/nanonote/threadlist.
|
|||||||
server:
|
server:
|
||||||
while mips/nanonote/server/usb-server ; do : ; done
|
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
|
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
|
.PRECIOUS: mips/arch.hh mips/nanonote/jz4740.hh mips/nanonote/board.hh
|
||||||
|
Loading…
x
Reference in New Issue
Block a user