#include "uart.h" #include "io.h" #include "demo_functionality.h" #include "paging.h" #include "atags.h" // for POWER_OF_2() macro... perhaps the macro should be moved #include "memory.h" #include "armclock.h" #include "scheduler.h" void setup(uint32_t r0, uint32_t machine_type, struct atag_header *atags) { uart_init(); // When we attach screen session after loading kernel with socat // we miss kernel's greeting... So we'll make the kernel wait for // one char we're going to send from within screen getchar(); puts("Hello, kernel World!"); prints("ARM machine type: 0x"); printhext(machine_type); puts(""); uint32_t memory_size = 0; // value 3 introduced by stage1 code means no atags was found if (r0 == 3) puts("No ATAGS was found!"); else { prints("ATAGS copied to 0x"); printhex((uint32_t) atags); puts(""); puts("__ ATAGS contents __"); print_atags(atags); puts("__ end of ATAGS contents __"); memory_size = find_memory_size(atags); } if (memory_size) { char *unit; uint32_t size_in_unit; if (memory_size % POWER_OF_2(10)) { unit = "B"; size_in_unit = memory_size; } else if (memory_size % POWER_OF_2(20)) { unit = "KB"; size_in_unit = memory_size / POWER_OF_2(10); } else if (memory_size % POWER_OF_2(30)) { unit = "MB"; size_in_unit = memory_size / POWER_OF_2(20); } else { unit = "GB"; size_in_unit = memory_size / POWER_OF_2(30); } prints("memory available: "); printdect(size_in_unit); puts(unit); } else { // Most Pis have more, but qemu might give us little puts("Couldn't determine available memory - assuming 192MB"); memory_size = 192 * POWER_OF_2(20); } // assume we need at least one section for PL0 if (memory_size < PRIVILEGED_MEMORY_END + SECTION_SIZE) { puts("Not enough memory to continue"); while (1); } // prints some info demo_paging_support(); // prints some info demo_current_mode(); setup_pager_structures(memory_size); // prints some info and sets upp translation table, turns on MMU setup_flat_map(); puts("Initializing clock"); // sets some general settings for arm timer armclk_init(); puts("Setting up scheduler's internal structures"); setup_scheduler_structures(); puts("Switching uart to use irqs"); // note, that kernel's puts() is still going to use blocking io uart_irq_enable(); // prints some info and sets up a section for PL0 code, loads a blob // there, then runs scheduler... never, ever, ever returns demo_setup_PL0(); }