#set page(paper: "a3", margin: 2cm)

#let karlos-color = rgb("#009c72")
#show: it => block(
  width: 100%,
  height: 100%,
  stroke: black,
  radius: (
    top-left: 64pt,
    bottom-right: 64pt,
  ),
  inset: 32pt,
  it
)

#let logo-image = image(width: 64pt, "karlos-logo.svg")
#let logo = stack(
  dir: ltr,
  logo-image,
  h(10pt),
  [
    #text(font: "fira sans", size: 64pt, weight: "black")[KarlOS] \
    #text(font: "fira sans", size: 16pt, weight: "bold")[Karlsruhe Operating System]
  ]
)

#set text(font: "fira sans", size: 16pt)
#set list(marker: [•])

#let text-block(it) = block(
  fill: rgb("#009c72").transparentize(70%),
  radius: (
    top-left: 8pt,
    bottom-right: 8pt,
  ),
  inset: 8pt,
  it
)

#let text-block2(head, it) = stack(
  dir: ttb,
  block(
    width: 100%,
    fill: karlos-color.transparentize(50%),
    radius: (
      top-left: 8pt,
    ),
    inset: 8pt,
    heading(level: 2, head)
  ),
  block(
    width: 100%,
    fill: karlos-color.transparentize(70%),
    radius: (
      bottom-right: 8pt,
    ),
    inset: 8pt,
    it
  )
)

#grid(columns: (1fr, 1fr), gutter: 16pt,
[
#logo

#text-block2("Who are we?", [
Hobbyist OS-enthusiast students at KIT
])

#text-block2("Our OS", [
- Architecture: x86
- Language: modern C
- Organization
  - Monolithic kernel
  - Multicore
  - Non-POSIX, not Unix-like
#place(horizon + right, block(inset: 16pt, image("c-logo.svg", width: 20%)))
])

#text-block2("Goals", [
- Platform for experimentation
- Non-standard task/process model
- Tagged file system
])
], [
#show raw: set text(font: "fira mono", weight: "bold", size: 4.6pt)
  ```c
void
ram_init(void)
{
    ASSERT(!ram_initialized);

    // collect memory regions and remove initrd range, as well as page frame 0
    populate_ranges(&bootboot_free_cover);
    // TODO removing this is not really necessary anymore, at least in my qemu case.
    // We still keep it in because in the worst case it does nothing.
    cover_remove(&bootboot_free_cover, (struct mem_range) {
        .start = pa_from_value(bootboot.initrd_ptr),
        .size = bootboot.initrd_size
    });
    cover_remove(&bootboot_free_cover, (struct mem_range) {
        .start = pa_from_value(0),
        .size = PG_SIZE
    });

    // Calculate how many levels we need
    uint64_t addrLimit = pa_to_value(cover_end(&bootboot_free_cover));
    addrLimit = next_pow2(addrLimit);
    if (addrLimit == 0) {
        PANIC("Zero physical frames available.");
    }
    ram_num_levels = __builtin_ffsl(addrLimit); // log2(addrLimit) + 1
    ram_num_levels -= PG_SHIFT;
    DEBUG_PRINTF("addrLimit = %lu\n", addrLimit);
    DEBUG_PRINTF("ram_num_levels = %u\n", ram_num_levels);

    // Allocate bitmaps for all levels; Initialize all memory as allocated
    for (unsigned level = 0; level < ram_num_levels; level++) {
        ram_layers[level].first_free = pa_from_value(INVALID_FRAME_ADDR);

        size_t bitmapSize = BITMAP_SIZE(1ul << (ram_num_levels - level - 1));

        ASSERT(cover_steal(&bootboot_free_cover, bitmapSize, &ram_layers[level].avail_bitmap));
        memset(pa_to_pointer(ram_layers[level].avail_bitmap), 0x00, bitmapSize);

        ASSERT(cover_steal(&bootboot_free_cover, bitmapSize, &ram_layers[level].coherent_bitmap));
        memset(pa_to_pointer(ram_layers[level].coherent_bitmap), 0x00, bitmapSize);
    }

    // align all segments to page size
    cover_align(&bootboot_free_cover, PG_SHIFT);

    // Mark free frames as available
    for (unsigned int i = 0; i < bootboot_free_cover.num_ranges; i++) {
        uint64_t start  = pa_to_value(bootboot_free_cover.ranges[i].start);
        uint64_t length = bootboot_free_cover.ranges[i].size;

        uint64_t addr = start;
        while (length >= PG_SIZE) {
            unsigned level = 0;
            for (;;) {
                unsigned next_level_bytes = NUM_BYTES_COVERED_IN_LEVEL(level + 1);
                // size and alignment need to fit
                if (length < next_level_bytes || (addr & (next_level_bytes - 1)) != 0) {
                    break;
                }
                level++;
            }

            DEBUG_PRINTF("freeing %lx at level %u\n", addr, level);
            free_block(pa_from_value(addr), level);

            addr += NUM_BYTES_COVERED_IN_LEVEL(level);
            length -= NUM_BYTES_COVERED_IN_LEVEL(level);
        }
    }

    ram_initialized = true;
}
  ```
]
)

#image(width: 100%, "kernel-diagram.svg")

#let qr = block(
  stroke: 3pt + black, 
  inset: 8pt,
  radius: 16pt,
  image("qr-karlsruhe-os-de.svg")
)
#place(bottom, grid(
  columns: (2fr, 1fr),
  gutter: 16pt,
  align(bottom, text-block2("Join us if you...", [
    - are interested in systems programming
    - want to see what goes into developing an OS
    - have (or want to gain) experience in C programming
  ])),
  qr,
  [],
  align(center, text(weight: "bold")[karlsruhe-os.de])
))
