aboutsummaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/bootinfo/multiboot.dats288
-rw-r--r--kernel/bootinfo/multiboot.sats29
-rw-r--r--kernel/main.dats46
-rw-r--r--kernel/memory/frame.dats258
-rw-r--r--kernel/memory/frame.sats50
-rw-r--r--kernel/prelude/DATS/print.dats24
6 files changed, 362 insertions, 333 deletions
diff --git a/kernel/bootinfo/multiboot.dats b/kernel/bootinfo/multiboot.dats
index 9eee595..0653184 100644
--- a/kernel/bootinfo/multiboot.dats
+++ b/kernel/bootinfo/multiboot.dats
@@ -3,150 +3,186 @@
#define ATS_DYNLOADFLAG 0
staload "./multiboot.sats"
+staload "lib/SATS/init.sats"
+staload "lib/DATS/init.dats"
staload UN = "prelude/SATS/unsafe.sats"
local
-var boot_info : boot_info_t
+ extern castfn ui2sz (n : uint) :<> [n : nat] size_t n
+ extern fn _get_memory_mappings_n(boot_info : !boot_info_t):<> [n:nat] size_t n
+ extern fn _get_memory_mapping(boot_info : !boot_info_t,n : size_t):<> memory_area_t
+ extern fn _print_memory_mappings(boot_info : !boot_info_t):<!wrt> void
in
-implement boot_info_init (p : Ptr1) = let
- extern praxi __assert{l:addr} (ptr: ptr (l)): vtakeout0 (boot_info_t@l) // takeout proof UNSAFE:
- prval (pf, fpf) = __assert (addr@boot_info)
- val total_size = $UN.ptr0_get<uint>(p)
-
- fun loop {l : agz} (pf : !boot_info_t@l | boot_p : ptr l , p : ptr): void = let
- val type = $UN.ptr0_get<uint>(p)
- val size = $UN.ptr0_get<uint>(ptr_succ<uint>(p))
- val next = (if (size % 8u != 0) then size + 8u - (size % 8u) else size) : uint
- in
- case+ type of
- | 6u => (
- boot_p->memory_map := $UN.ptr0_get<memory_areas_t>(p);
- boot_p->memory_map.entries := ptr_add<uint32>(p,4)
- )
- | 9u => (
- boot_p->elf_tag := $UN.ptr0_get<elf_tag_t>(p);
- boot_p->elf_tag.headers := ptr_add<uint32>(p,5);
- )
- | _ => ();
-
- if (type != 0u) then
- loop(pf | boot_p, ptr_add<uint8>(p, next))
- end
-
-in
- boot_info.total_size := total_size;
- loop(pf | addr@boot_info, ptr_add<uint32>(p,2));
-
- (pf , fpf | addr@boot_info)
-end
-
-end
-
-extern castfn ui2sz (n : uint) :<> [n : nat] size_t n
-
-//------------Memory------------------------
-
-implement get_memory_mappings_n(pf | p) = let
- val size = p->memory_map.tag.size
- val n_entries = (if(size >= 16u) then (size - 16u) / p->memory_map.entry_size else 0u) : uint
-in
- ui2sz n_entries
-end
-
-// TODO: here use optional datatype (fix runtime alloc)
+ local
+ // Static variable
+ var _v : boot_info_t?
+ prval () = opt_none _v
+ var v = uninitialized<boot_info_t>(_v)
+ // Reference to writer
+ val bootinfo_ref = ref_make_viewptr{initializable boot_info_t} (view@v | addr@v)
+ in
-implement get_memory_mapping(pf | p,n) = (
- (* assertloc(n < get_memory_mappings_n(pf | p)); *)
- $UN.ptr0_get<memory_area_t>(ptr_add<memory_area_t>(p->memory_map.entries,n))
-)
+ implement init (p : Ptr1) = let
+ extern castfn unsafe_init(x : &boot_info_t? >> boot_info_t) :<> void
+ val total_size = $UN.ptr0_get<uint>(p)
+
+ fun loop (boot_info : &boot_info_t? >> boot_info_t, p : ptr):<!wrt,!ntm> void = let
+ val type = $UN.ptr0_get<uint>(p)
+ val size = $UN.ptr0_get<uint>(ptr_succ<uint>(p))
+ val next = (if (size % 8u != 0) then size + 8u - (size % 8u) else size) : uint
+ in
+ case+ type of
+ | 6u => (
+ boot_info.memory_map := $UN.ptr0_get<memory_areas_t>(p);
+ boot_info.memory_map.entries := ptr_add<uint32>(p,4)
+ )
+ | 9u => (
+ boot_info.elf_tag := $UN.ptr0_get<elf_tag_t>(p);
+ boot_info.elf_tag.headers := ptr_add<uint32>(p,5);
+ )
+ | _ => ();
+
+ if (type != 0u) then
+ loop(boot_info,ptr_add<uint8>(p, next))
+ else
+ unsafe_init(boot_info)
+ end
+
+ val (vbox pf | boot_p) = ref_get_viewptr(bootinfo_ref)
+ in
+ if (not boot_p->initialized) then
+ let
+ prval () = opt_unnone boot_p->obj
+ val () = boot_p->obj.total_size := total_size
+ val () = loop(boot_p->obj, ptr_add<uint32>(p,2))
+ val () = boot_p->initialized := true
+ prval () = opt_some boot_p->obj
+ in end
+ end
+
+ implement get_memory_mappings_n() = let
+ implement exec$fwork<boot_info_t><size_t>(v,_) = _get_memory_mappings_n(v)
+ in
+ exec<boot_info_t>(bootinfo_ref,i2sz(0))
+ end
+
+ implement get_memory_mapping(n) = let
+ implement exec$fwork<boot_info_t><memory_area_t>(v,_) = _get_memory_mapping(v,n)
+ in
+ exec<boot_info_t><memory_area_t>(bootinfo_ref,invalid_area)
+ end
+
+ implement print_memory_mappings() = let
+ implement exec_void$fwork<boot_info_t>(v) = _print_memory_mappings(v)
+ in
+ exec_void<boot_info_t>(bootinfo_ref)
+ end
-//TODO: use foreach with fwork to loop through memory maps
-implement print_memory_mappings(p) = let
- val length = get_memory_mappings_n(p.0 | p.2)
- fun loop {n,i : nat | i < n} .<n-i>. (p : !bootptr, i : size_t i, n : size_t n) : void = let
- val entry = get_memory_mapping(p.0 | p.2 ,i)
- in
- if (entry.type = 1) then (
- print(" Start Address: ");
- print_hex(entry.base_addr);
- print(", Length: ");
- println_hex(entry.length);
- );
- if (i < n-1) then
- loop (p,succ(i),n)
end
-in
- if (length > 0) then (
- println!("Memory areas:");
- loop(p,i2sz(0),length))
- else
- println!("No memory mappings")
-end
-//----------------------------------------------
+ //------------Memory------------------------
-//---------------------ELF----------------------
-
-implement get_elf_headers_n(p) = ui2sz p.2->elf_tag.num
-
-implement get_elf_header (p,n) = (
- assertloc(n < get_elf_headers_n(p));
- $UN.ptr0_get<elf64_shdr_t>(ptr_add<elf64_shdr_t>(p.2->elf_tag.headers,n))
-)
-
-implement get_kernel_ranges(p) = let
- val length = get_elf_headers_n(p)
- fun loop {n,i : nat | i < n} .<n-i>. (p : !bootptr, i : size_t i,n : size_t n, min : Ptr, max : Ptr) : (Ptr,Ptr) = let
- val header = get_elf_header(p,i)
- val new_min = (if ((header.addr < min || min = the_null_ptr) && header.size != 0) then header.addr else min)
- val end_p = ptr_add<uint8>(header.addr,header.size)
- val new_max = (
- if (end_p > max && header.size != 0)
- then $UN.cast2Ptr1(end_p)
- else max
- )
+ implement _get_memory_mappings_n(boot_info) = let
+ val size = boot_info.memory_map.tag.size
+ val n_entries = (if(size >= 16u) then (size - 16u) / boot_info.memory_map.entry_size else 0u) : uint
in
- if (i < n - 1) then
- loop(p,succ(i),n,new_min,new_max)
- else
- (new_min,new_max)
+ ui2sz n_entries
end
-in
- if (length > 0) then
- loop(p,i2sz(0),length,the_null_ptr,the_null_ptr)
- else
- (the_null_ptr,the_null_ptr)
-end
-
-implement get_multiboot_ranges(p) = (p.2, $UN.cast2Ptr1(ptr_add<uint8>(p.2,p.2->total_size)))
-
-implement print_elf_headers(p) = let
- val length = get_elf_headers_n(p)
- fun loop {n,i : nat | i < n} .<n-i>. (p : !bootptr, i : size_t i, n : size_t n) : void = let
- val header = get_elf_header(p,i)
+ implement _get_memory_mapping(boot_info,n) = (
+ (* assertloc(n < get_memory_mappings_n(pf | p)); *)
+ $UN.ptr0_get<memory_area_t>(ptr_add<memory_area_t>(boot_info.memory_map.entries,n))
+ )
+
+ //TODO: use foreach with fwork to loop through memory maps
+ implement _print_memory_mappings(boot_info) = let
+ val length = _get_memory_mappings_n(boot_info)
+ fun loop {n,i : nat | i < n} .<n-i>. (i : size_t i, n : size_t n):<!wrt> void = let
+ val entry = _get_memory_mapping(boot_info,i)
+ in
+ if (entry.type = 1) then (
+ print(" Start Address: ");
+ print_hex(entry.base_addr);
+ print(", Length: ");
+ println_hex(entry.length);
+ );
+ if (i < n-1) then
+ loop (succ(i),n)
+ end
in
- print(" addr: ");
- print_hex(header.addr);
- print(", size: ");
- print_hex(header.size);
- print(", flags: ");
- println_hex(header.flags);
-
- if (i < n - 1) then
- loop(p,succ(i),n)
-
+ if (length > 0) then (
+ println!("Memory areas:");
+ loop(i2sz(0),length))
+ else
+ println!("No memory mappings")
end
-in
- if (length > 0) then (
- println!("Elf section headers: ");
- loop(p,i2sz(0),length))
- else
- println!("No elf section headers")
+
end
//----------------------------------------------
+(* //---------------------ELF---------------------- *)
+(**)
+(* implement get_elf_headers_n(p) = ui2sz p.2->elf_tag.num *)
+(**)
+(* implement get_elf_header (p,n) = ( *)
+(* assertloc(n < get_elf_headers_n(p)); *)
+(* $UN.ptr0_get<elf64_shdr_t>(ptr_add<elf64_shdr_t>(p.2->elf_tag.headers,n)) *)
+(* ) *)
+(**)
+(* implement get_kernel_ranges(p) = let *)
+(* val length = get_elf_headers_n(p) *)
+(* fun loop {n,i : nat | i < n} .<n-i>. (p : !bootptr, i : size_t i,n : size_t n, min : Ptr, max : Ptr) : (Ptr,Ptr) = let *)
+(* val header = get_elf_header(p,i) *)
+(* val new_min = (if ((header.addr < min || min = the_null_ptr) && header.size != 0) then header.addr else min) *)
+(* val end_p = ptr_add<uint8>(header.addr,header.size) *)
+(* val new_max = ( *)
+(* if (end_p > max && header.size != 0) *)
+(* then $UN.cast2Ptr1(end_p) *)
+(* else max *)
+(* ) *)
+(* in *)
+(* if (i < n - 1) then *)
+(* loop(p,succ(i),n,new_min,new_max) *)
+(* else *)
+(* (new_min,new_max) *)
+(* end *)
+(**)
+(* in *)
+(* if (length > 0) then *)
+(* loop(p,i2sz(0),length,the_null_ptr,the_null_ptr) *)
+(* else *)
+(* (the_null_ptr,the_null_ptr) *)
+(* end *)
+(**)
+(* implement get_multiboot_ranges(p) = (p.2, $UN.cast2Ptr1(ptr_add<uint8>(p.2,p.2->total_size))) *)
+(**)
+(* implement print_elf_headers(p) = let *)
+(* val length = get_elf_headers_n(p) *)
+(* fun loop {n,i : nat | i < n} .<n-i>. (p : !bootptr, i : size_t i, n : size_t n) : void = let *)
+(* val header = get_elf_header(p,i) *)
+(* in *)
+(* print(" addr: "); *)
+(* print_hex(header.addr); *)
+(* print(", size: "); *)
+(* print_hex(header.size); *)
+(* print(", flags: "); *)
+(* println_hex(header.flags); *)
+(* *)
+(* if (i < n - 1) then *)
+(* loop(p,succ(i),n) *)
+(**)
+(* end *)
+(* in *)
+(* if (length > 0) then ( *)
+(* println!("Elf section headers: "); *)
+(* loop(p,i2sz(0),length)) *)
+(* else *)
+(* println!("No elf section headers") *)
+(* end *)
+(**)
+(* //---------------------------------------------- *)
+(**)
diff --git a/kernel/bootinfo/multiboot.sats b/kernel/bootinfo/multiboot.sats
index 1a2e6db..cab885a 100644
--- a/kernel/bootinfo/multiboot.sats
+++ b/kernel/bootinfo/multiboot.sats
@@ -45,24 +45,23 @@ typedef boot_info_t = @{
elf_tag = elf_tag_t
}
-vtypedef bootptr = [l : agz] (boot_info_t@l , boot_info_t@l -<lin,prf> void | ptr l)
-
-fun boot_info_init(p : Ptr1) : bootptr
-
-fn get_memory_mappings_n {l : agz} (pf : !boot_info_t@l | p : ptr l) :<> [n:nat] size_t n
-fn get_memory_mapping {l:agz} (pf : !boot_info_t @ l | p : ptr l, n : size_t) :<> memory_area_t
-fn print_memory_mappings (p : !bootptr) : void // Print all available memory area's
-
-fn get_elf_headers_n (p : !bootptr) : [n:nat] size_t n
-fn get_elf_header (p : !bootptr, n : size_t) : elf64_shdr_t
-fn print_elf_headers (p : !bootptr) : void
-
-fn get_kernel_ranges (p : !bootptr) : (Ptr,Ptr) // (kernel start, kernel end)
-fn get_multiboot_ranges (p : !bootptr) : (Ptr0,Ptr0) // (bootinfo start, bootinfo end)
-
macdef invalid_area = @{
base_addr = the_null_ptr,
length = i2sz(1),
type = 0u,
reserved = 0u
}
+
+fun init(p : Ptr1) :void
+
+fn get_memory_mappings_n () : [n:nat] size_t n
+fn get_memory_mapping (n : size_t) : memory_area_t
+fn print_memory_mappings () : void // Print all available memory area's
+
+(* fn get_elf_headers_n () : [n:nat] size_t n *)
+(* fn get_elf_header (n : size_t) : elf64_shdr_t *)
+(* fn print_elf_headers () : void *)
+(**)
+(* fn get_kernel_ranges () : (Ptr,Ptr) // (kernel start, kernel end) *)
+(* fn get_multiboot_ranges () : (Ptr0,Ptr0) // (bootinfo start, bootinfo end) *)
+
diff --git a/kernel/main.dats b/kernel/main.dats
index dadcd2d..4c7d49a 100644
--- a/kernel/main.dats
+++ b/kernel/main.dats
@@ -1,7 +1,7 @@
#include "./prelude/kernel_prelude.hats"
staload "kernel/interrupts/idt.sats"
-staload "kernel/bootinfo/multiboot.sats"
+staload BOOT = "kernel/bootinfo/multiboot.sats"
staload "kernel/memory/frame.sats"
staload "lib/SATS/writer.sats"
@@ -13,17 +13,17 @@ staload "lib/SATS/writer.sats"
//NOTE: how to make sure ats checks 2 contstraints in one if statement?
//TODO: put in seperate utils module (just generic size function)
-fn kernel_size(kernel_start : Ptr, kernel_end : Ptr) : size_t = let
- extern castfn Ptr12size (a : Ptr1): size_t
-in
- if (kernel_end > the_null_ptr) then
- if (kernel_start > the_null_ptr) then
- Ptr12size(kernel_end) - Ptr12size(kernel_start)
- else
- i2sz(0)
- else
- i2sz(0)
-end
+(* fn kernel_size(kernel_start : Ptr, kernel_end : Ptr) : size_t = let *)
+(* extern castfn Ptr12size (a : Ptr1): size_t *)
+(* in *)
+(* if (kernel_end > the_null_ptr) then *)
+(* if (kernel_start > the_null_ptr) then *)
+(* Ptr12size(kernel_end) - Ptr12size(kernel_start) *)
+(* else *)
+(* i2sz(0) *)
+(* else *)
+(* i2sz(0) *)
+(* end *)
(* fn test(allocptr : !allocptr, bootptr : !bootptr) : void = let *)
(* fun loop(i : int) : void = if (i < 160) then( let val _ = allocate_frame(allocptr.0, bootptr.0 | allocptr.2, bootptr.2) in end; loop(succ(i))) *)
@@ -37,19 +37,20 @@ extern fun breakpoint() :void = "mac#"
extern fun entry(p : Ptr1) : void = "ext#"
implement entry(p) = let
- val () = clear_screen()
// Initialize boot info struct
- val bootptr = boot_info_init(p)
- val (kernel_start,kernel_end) = get_kernel_ranges(bootptr)
- val (multiboot_start,multiboot_end) = get_multiboot_ranges(bootptr)
+ val () = $BOOT.init(p)
+
+ (* val (kernel_start,kernel_end) = get_kernel_ranges(bootptr) *)
+ (* val (multiboot_start,multiboot_end) = get_multiboot_ranges(bootptr) *)
(* val allocptr = frame_allocator_init(kernel_start,kernel_end,multiboot_start,multiboot_end,bootptr) *)
in
- print_memory_mappings(bootptr);
+ clear_screen();
+ $BOOT.print_memory_mappings();
- print_elf_headers(bootptr);
- println!("Kernel Size: ", kernel_size(kernel_start,kernel_end));
+ (* print_elf_headers(bootptr); *)
+ (* println!("Kernel Size: ", kernel_size(kernel_start,kernel_end)); *)
(* test(allocptr,bootptr); *)
(* let *)
(* val frame = allocate_frame(allocptr.0, bootptr.0 | allocptr.2, bootptr.2) *)
@@ -65,13 +66,6 @@ in
println!("End");
-
- let
- prval () = bootptr.1(bootptr.0)
- (* prval () = allocptr.1(allocptr.0) *)
- in end
-
-
end
// Satisfy ats compiler. Should be called once to dynload files
diff --git a/kernel/memory/frame.dats b/kernel/memory/frame.dats
index 5a950ad..8a9160b 100644
--- a/kernel/memory/frame.dats
+++ b/kernel/memory/frame.dats
@@ -1,131 +1,131 @@
-#include "kernel/prelude/kernel_prelude.hats"
-
+(* #include "kernel/prelude/kernel_prelude.hats" *)
+(**)
#define ATS_DYNLOADFLAG 0
-
-staload "./frame.sats"
-staload "kernel/bootinfo/multiboot.sats"
-staload "lib/SATS/init.sats"
-
-staload UN = "prelude/SATS/unsafe.sats"
-
-assume frame_allocator = frame_allocator_t
-
-implement containing_address(address): frame_t =
- @{
- counter = $UN.cast{size_t}(address) / i2sz(PAGE_SIZE)
- }
-
-fn containing_area(area : memory_area_t) :<> frame_t = containing_address(ptr_add<uint8>(area.base_addr,area.length - i2sz(1)))
-
-//FIX: function doesn't handle no frames left
-fn choose_next_area{k : agz}(bf : !boot_info_t @ k | b : ptr k, allocator : &frame_allocator_t) :<!wrt> void = let
- val length = get_memory_mappings_n(bf | b)
- val next_free_frame = allocator.next_free_frame
- fun loop {n,i : nat | i < n} {l : agz} .<n-i>. (bf : !boot_info_t @ l | b : ptr l, i : size_t i, n : size_t n) :<> memory_area_t = let
- val entry = get_memory_mapping(bf | b ,i)
- val fr = containing_area(entry)
- in
- if (entry.type = 1 && fr.num >= next_free_frame.num) then
- entry
- else if (i < n-1) then
- loop (bf | b,succ(i),n)
- else
- entry //TODO: fix
- end
-in
- if (length > 0) then //TODO: fix
- allocator.current_area := loop(bf | b, i2sz(0), length);
-
- if (allocator.current_area.length > 1) then
- let
- val start_frame = containing_address(allocator.current_area.base_addr)
- in
- if (allocator.next_free_frame.num < start_frame.num) then
- allocator.next_free_frame := start_frame
- end
-end
-
-local
-
-var allocator_static : frame_allocator_t?
-prval () = opt_none allocator_static
-var allocator = uninitialized<frame_allocator_t>(allocator_static)
-val allocator_ref = ref_make_viewptr{initializable frame_allocator_t} (view@allocator | addr@allocator)
-
-in
-
- implement frame_allocator_init(kernel_start, kernel_end, multiboot_start, multiboot_end, b) : void = let
- val allocator = @{
- next_free_frame = containing_address(the_null_ptr),
- current_area = invalid_area,
- kernel_start = containing_address(kernel_start),
- kernel_end = containing_address(kernel_end),
- multiboot_start = containing_address(multiboot_start),
- multiboot_end = containing_address(multiboot_end)
- } : frame_allocator_t
- val (vbox pf | p) = ref_get_viewptr(allocator_ref)
- in
- if not p->initialized then let
- prval () = opt_unnone p->obj
- in
- p->obj := allocator;
- p->initialized := true;
- (* choose_next_area(b.0 | b.2, !p); *)
- let prval () = opt_some p->obj in end;
- end
- end
-
-implement allocate_frame(bf | b) : frame_t = let
- val (vbox pf | p) = ref_get_viewptr(allocator_ref)
- in
- if p->initialized then let
- (* var allocator = p->obj *)
- prval () = opt_unsome p->obj
- in
- (* if (allocator.current_area.type != 0u) then let *)
- (* val area = allocator.current_area *)
- (* val frame = @{ num = allocator.next_free_frame.num } *)
- (**)
- (* // last frame of current area *)
- (* val last_frame_area = containing_area(area) *)
- (* in *)
- (* if (frame.num > last_frame_area.num) then ( *)
- (* // all frames of current area are used, switch to next area *)
- (* choose_next_area(bf | b, allocator); *)
- (* let prval () = opt_some allocator in end; *)
- (* allocate_frame(bf | b) *)
- (* ) else if (frame.num >= allocator.kernel_start.num && frame.num <= allocator.kernel_end.num) then ( *)
- (* // frame is used by kernel *)
- (* allocator.next_free_frame := @{num = allocator.kernel_end.num + 1}; *)
- (* let prval () = opt_some allocator in end; *)
- (* allocate_frame(bf | b) *)
- (* ) else if (frame.num >= allocator.multiboot_start.num && frame.num <= allocator.multiboot_end.num) then ( *)
- (* // frame is used by multiboot info structure *)
- (* allocator.next_free_frame := @{num = allocator.multiboot_end.num + 1}; *)
- (* let prval () = opt_some allocator in end; *)
- (* allocate_frame(bf | b) *)
- (* ) else ( *)
- (* // frame is unused, increment `next_free_frame` and return it *)
- (* allocator.next_free_frame.num := succ(allocator.next_free_frame.num); *)
- (* let prval () = opt_some allocator in end; *)
- (* frame *)
- (* ); *)
- (* end *)
- (* else *)
- (* let prval () = opt_some allocator in end; *)
- (* @{num = i2sz(0)} // No free frames left *)
- let prval () = opt_some p->obj in end;
- @{num = i2sz(0)}
- end
- else
- @{num = i2sz(0)} // No free frames left
-
-end
-
-end
-
-implement deallocate_frame(p) : void = let
-in
-
-end
+(**)
+(* staload "./frame.sats" *)
+(* staload "kernel/bootinfo/multiboot.sats" *)
+(* staload "lib/SATS/init.sats" *)
+(**)
+(* staload UN = "prelude/SATS/unsafe.sats" *)
+(**)
+(* assume frame_allocator = frame_allocator_t *)
+(**)
+(* implement containing_address(address): frame_t = *)
+(* @{ *)
+(* counter = $UN.cast{size_t}(address) / i2sz(PAGE_SIZE) *)
+(* } *)
+(**)
+(* fn containing_area(area : memory_area_t) :<> frame_t = containing_address(ptr_add<uint8>(area.base_addr,area.length - i2sz(1))) *)
+(**)
+(* //FIX: function doesn't handle no frames left *)
+(* fn choose_next_area{k : agz}(bf : !boot_info_t @ k | b : ptr k, allocator : &frame_allocator_t) :<!wrt> void = let *)
+(* val length = get_memory_mappings_n(bf | b) *)
+(* val next_free_frame = allocator.next_free_frame *)
+(* fun loop {n,i : nat | i < n} {l : agz} .<n-i>. (bf : !boot_info_t @ l | b : ptr l, i : size_t i, n : size_t n) :<> memory_area_t = let *)
+(* val entry = get_memory_mapping(bf | b ,i) *)
+(* val fr = containing_area(entry) *)
+(* in *)
+(* if (entry.type = 1 && fr.num >= next_free_frame.num) then *)
+(* entry *)
+(* else if (i < n-1) then *)
+(* loop (bf | b,succ(i),n) *)
+(* else *)
+(* entry //TODO: fix *)
+(* end *)
+(* in *)
+(* if (length > 0) then //TODO: fix *)
+(* allocator.current_area := loop(bf | b, i2sz(0), length); *)
+(**)
+(* if (allocator.current_area.length > 1) then *)
+(* let *)
+(* val start_frame = containing_address(allocator.current_area.base_addr) *)
+(* in *)
+(* if (allocator.next_free_frame.num < start_frame.num) then *)
+(* allocator.next_free_frame := start_frame *)
+(* end *)
+(* end *)
+(**)
+(* local *)
+(**)
+(* var allocator_static : frame_allocator_t? *)
+(* prval () = opt_none allocator_static *)
+(* var allocator = uninitialized<frame_allocator_t>(allocator_static) *)
+(* val allocator_ref = ref_make_viewptr{initializable frame_allocator_t} (view@allocator | addr@allocator) *)
+(**)
+(* in *)
+(**)
+(* implement frame_allocator_init(kernel_start, kernel_end, multiboot_start, multiboot_end, b) : void = let *)
+(* val allocator = @{ *)
+(* next_free_frame = containing_address(the_null_ptr), *)
+(* current_area = invalid_area, *)
+(* kernel_start = containing_address(kernel_start), *)
+(* kernel_end = containing_address(kernel_end), *)
+(* multiboot_start = containing_address(multiboot_start), *)
+(* multiboot_end = containing_address(multiboot_end) *)
+(* } : frame_allocator_t *)
+(* val (vbox pf | p) = ref_get_viewptr(allocator_ref) *)
+(* in *)
+(* if not p->initialized then let *)
+(* prval () = opt_unnone p->obj *)
+(* in *)
+(* p->obj := allocator; *)
+(* p->initialized := true; *)
+(* (* choose_next_area(b.0 | b.2, !p); *) *)
+(* let prval () = opt_some p->obj in end; *)
+(* end *)
+(* end *)
+(**)
+(* implement allocate_frame(bf | b) : frame_t = let *)
+(* val (vbox pf | p) = ref_get_viewptr(allocator_ref) *)
+(* in *)
+(* if p->initialized then let *)
+(* (* var allocator = p->obj *) *)
+(* prval () = opt_unsome p->obj *)
+(* in *)
+(* (* if (allocator.current_area.type != 0u) then let *) *)
+(* (* val area = allocator.current_area *) *)
+(* (* val frame = @{ num = allocator.next_free_frame.num } *) *)
+(* (**) *)
+(* (* // last frame of current area *) *)
+(* (* val last_frame_area = containing_area(area) *) *)
+(* (* in *) *)
+(* (* if (frame.num > last_frame_area.num) then ( *) *)
+(* (* // all frames of current area are used, switch to next area *) *)
+(* (* choose_next_area(bf | b, allocator); *) *)
+(* (* let prval () = opt_some allocator in end; *) *)
+(* (* allocate_frame(bf | b) *) *)
+(* (* ) else if (frame.num >= allocator.kernel_start.num && frame.num <= allocator.kernel_end.num) then ( *) *)
+(* (* // frame is used by kernel *) *)
+(* (* allocator.next_free_frame := @{num = allocator.kernel_end.num + 1}; *) *)
+(* (* let prval () = opt_some allocator in end; *) *)
+(* (* allocate_frame(bf | b) *) *)
+(* (* ) else if (frame.num >= allocator.multiboot_start.num && frame.num <= allocator.multiboot_end.num) then ( *) *)
+(* (* // frame is used by multiboot info structure *) *)
+(* (* allocator.next_free_frame := @{num = allocator.multiboot_end.num + 1}; *) *)
+(* (* let prval () = opt_some allocator in end; *) *)
+(* (* allocate_frame(bf | b) *) *)
+(* (* ) else ( *) *)
+(* (* // frame is unused, increment `next_free_frame` and return it *) *)
+(* (* allocator.next_free_frame.num := succ(allocator.next_free_frame.num); *) *)
+(* (* let prval () = opt_some allocator in end; *) *)
+(* (* frame *) *)
+(* (* ); *) *)
+(* (* end *) *)
+(* (* else *) *)
+(* (* let prval () = opt_some allocator in end; *) *)
+(* (* @{num = i2sz(0)} // No free frames left *) *)
+(* let prval () = opt_some p->obj in end; *)
+(* @{num = i2sz(0)} *)
+(* end *)
+(* else *)
+(* @{num = i2sz(0)} // No free frames left *)
+(* *)
+(* end *)
+(**)
+(* end *)
+(**)
+(* implement deallocate_frame(p) : void = let *)
+(* in *)
+(* *)
+(* end *)
diff --git a/kernel/memory/frame.sats b/kernel/memory/frame.sats
index 0de5056..0926e6c 100644
--- a/kernel/memory/frame.sats
+++ b/kernel/memory/frame.sats
@@ -1,25 +1,25 @@
-#define PAGE_SIZE 4096
-
-staload "kernel/bootinfo/multiboot.sats"
-
-typedef frame_t = @{
- num = size_t
-}
-
-typedef frame_allocator_t = @{
- next_free_frame = frame_t,
- current_area = memory_area_t,
- kernel_start = frame_t,
- kernel_end = frame_t,
- multiboot_start = frame_t,
- multiboot_end = frame_t
-}
-
-vtypedef allocptr = [l : agz] (frame_allocator_t@l , frame_allocator_t@l -<lin,prf> void | ptr l)
-
-abst@ype frame_allocator = frame_allocator_t
-
-fn containing_address {l : addr} (address : ptr l) :<> frame_t
-fn allocate_frame {l : agz}{k : agz} (bf : !boot_info_t @ k | b : ptr k) :<!ref,!wrt> frame_t
-fn deallocate_frame (p : !allocptr) : void
-fn frame_allocator_init(kernel_start: Ptr, kernel_end: Ptr, multiboot_start:Ptr, multiboot_end: Ptr, b : !bootptr) : void
+(* #define PAGE_SIZE 4096 *)
+(**)
+(* staload "kernel/bootinfo/multiboot.sats" *)
+(**)
+(* typedef frame_t = @{ *)
+(* num = size_t *)
+(* } *)
+(**)
+(* typedef frame_allocator_t = @{ *)
+(* next_free_frame = frame_t, *)
+(* current_area = memory_area_t, *)
+(* kernel_start = frame_t, *)
+(* kernel_end = frame_t, *)
+(* multiboot_start = frame_t, *)
+(* multiboot_end = frame_t *)
+(* } *)
+(**)
+(* vtypedef allocptr = [l : agz] (frame_allocator_t@l , frame_allocator_t@l -<lin,prf> void | ptr l) *)
+(**)
+(* abst@ype frame_allocator = frame_allocator_t *)
+(**)
+(* fn containing_address {l : addr} (address : ptr l) :<> frame_t *)
+(* fn allocate_frame {l : agz}{k : agz} (bf : !boot_info_t @ k | b : ptr k) :<!ref,!wrt> frame_t *)
+(* fn deallocate_frame (p : !allocptr) : void *)
+(* (* fn frame_allocator_init(kernel_start: Ptr, kernel_end: Ptr, multiboot_start:Ptr, multiboot_end: Ptr, b : !bootptr) : void *) *)
diff --git a/kernel/prelude/DATS/print.dats b/kernel/prelude/DATS/print.dats
index b183da5..ac864ad 100644
--- a/kernel/prelude/DATS/print.dats
+++ b/kernel/prelude/DATS/print.dats
@@ -7,34 +7,34 @@ staload "lib/DATS/itoa.dats"
staload UN = "prelude/SATS/unsafe.sats"
-extern fun print_newline() : void
+extern fun print_newline() :<!wrt> void
implement print_newline() = put_string("\n")
-extern fun assert_errmsg(b: bool, msg: string) : void
+extern fun assert_errmsg(b: bool, msg: string) :<!wrt> void
implement assert_errmsg(b,msg) = if (~b) then put_string(msg)
-extern fun print_int (n : int) : void
+extern fun print_int (n : int) :<!wrt> void
implement print_int(n) = put_string(itoa(n,10))
-extern fun print_uint32 (n : uint32) : void
+extern fun print_uint32 (n : uint32) :<!wrt> void
implement print_uint32 (n) = put_string(itoa($UN.cast{int}(n),10))
-extern fun print_uint16 (n : uint16) : void
+extern fun print_uint16 (n : uint16) :<!wrt> void
implement print_uint16 (n) = put_string(itoa($UN.cast{int}(n),10))
-extern fun print_uint8 (n : uint8) : void
+extern fun print_uint8 (n : uint8) :<!wrt> void
implement print_uint8 (n) = put_string(itoa($UN.cast{int}(n),10))
-extern fun print_uint64 (n : uint64) : void
+extern fun print_uint64 (n : uint64) :<!wrt> void
implement print_uint64 (n) = put_string(itoa($UN.cast{int}(n),10))
-extern fun print_size_t (n : size_t) : void
+extern fun print_size_t (n : size_t) :<!wrt> void
implement print_size_t (n) = put_string(itoa($UN.cast{int}(n),10))
-extern fun print_uint (n : uint) : void
+extern fun print_uint (n : uint) :<!wrt> void
implement print_uint (n) = put_string(itoa($UN.cast{int}(n),10))
-extern fun print_addr (n : Ptr) : void
+extern fun print_addr (n : Ptr) :<!wrt> void
implement print_addr (n) = put_string(itoa($UN.cast{int}(n),10))
overload print with put_string of 1
@@ -47,10 +47,10 @@ overload print with print_size_t of 1
overload print with print_uint of 1
overload print with print_addr of 1
-extern fun {a : t@ype} println_base {n:nat | n > 1 && n < 33} (n :a, base : int n) : void
+extern fun {a : t@ype} println_base {n:nat | n > 1 && n < 33} (n :a, base : int n) :<!wrt> void
implement{a} println_base(n,base) = println!(itoa($UN.cast{int}(n), base))
-extern fun {a : t@ype} print_base {n:nat | n > 1 && n < 33} (n :a, base : int n) : void
+extern fun {a : t@ype} print_base {n:nat | n > 1 && n < 33} (n :a, base : int n) :<!wrt> void
implement{a} print_base(n,base) = put_string(itoa($UN.cast{int}(n), base))
macdef println_hex(s) = (put_string "0x"; println_base(,(s), 16))