hachem.wtf
aboutsummaryrefslogtreecommitdiff
path: root/kernel/proc.rv
blob: 2f8bb2f5c503c14386f7055b7d34b082b3a5fedc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# load an embedded elf into a fresh address space and run it in ring 3

const PT_LOAD = 1
const PAGE_FLAGS = 6 # write | user
const ARG_VADDR = 0x50000000 # where we map the argument string in the new space

fn load_elf(base, arg) do
  if mem_read(base, 4) != 0x464c457f do
    puts("not an ELF\n")
    return :nil
  end
  const entry = mem_read(base + 24, 8)
  const phoff = mem_read(base + 32, 8)
  const phnum = mem_read(base + 56, 2)
  const phentsize = mem_read(base + 54, 2)
  const space = as_create()
  for i in 0..phnum do
    const phdr = base + phoff + i * phentsize
    if mem_read(phdr, 4) == PT_LOAD do
      const offset = mem_read(phdr + 8, 8)
      const vaddr = mem_read(phdr + 16, 8)
      const filesz = mem_read(phdr + 32, 8)
      const memsz = mem_read(phdr + 40, 8)
      let seg_off = 0
      while seg_off < memsz do
        const frame = frame_alloc()
        mem_zero(frame, 4096)
        if seg_off < filesz do
          const left = filesz - seg_off
          mem_copy(frame, base + offset + seg_off, if left > 4096 4096 else left)
        end
        as_map(space, vaddr + seg_off, frame, PAGE_FLAGS)
        seg_off = seg_off + 4096
      end
    end
  end
  const stack_top = 0x7fff0000
  for p in 0..4 do as_map(space, stack_top - (p + 1) * 4096, frame_alloc(), PAGE_FLAGS) end
  let arg_ptr = 0
  const arg_len = arg:len()
  if arg_len > 0 do
    const argframe = frame_alloc()
    mem_zero(argframe, 4096)
    for k in 0..arg_len do mem_write(argframe + k, arg[k]:ascii(), 1) end
    as_map(space, ARG_VADDR, argframe, PAGE_FLAGS)
    arg_ptr = ARG_VADDR
  end
  proc_run(space, entry, stack_top, arg_ptr, arg_len)
end

fn run_prog(name, arg) do
  let n = name
  if n:starts_with?("/bin/") n = n[5..]
  for i in 0..prog_count() do
    if prog_name(i) == n do load_elf(prog_phys(i), arg) return :true end
  end
  puts("no such program: #{name}\n")
  return :false
end

fn list_progs() do
  puts("programs:")
  for i in 0..prog_count() do puts(" #{prog_name(i)}") end
  puts("\n")
end