diff options
-rw-r--r-- | Makefile | 14 | ||||
-rw-r--r-- | PL0_test.c | 18 | ||||
-rw-r--r-- | PL0_test.ld | 44 | ||||
-rw-r--r-- | kernel.c | 57 |
4 files changed, 131 insertions, 2 deletions
@@ -7,13 +7,25 @@ all : kernel7.img kernel.o : kernel.c arm-none-eabi-gcc $(CFLAGS) -c $^ -o $@ +PL0_test.o : PL0_test.c + arm-none-eabi-gcc $(CFLAGS) -c $^ -o $@ + +PL_0_test.elf : PL0_test.o uart.o + arm-none-eabi-gcc -T PL0_test.ld -o $@ $(ELFFLAGS) $^ + +PL_0_test.img : PL_0_test.elf + arm-none-eabi-objcopy $^ -O binary $@ + +PL_0_test_embeddable.o : PL_0_test.img + arm-none-eabi-objcopy -I binary -O elf32-littlearm -B arm --rename-section .data=.rodata $^ $@ + uart.o : uart.c arm-none-eabi-gcc $(CFLAGS) -c $^ -o $@ boot.o : boot.S arm-none-eabi-as -mcpu=cortex-a7 $^ -o $@ -kernel.elf : boot.o kernel.o uart.o +kernel.elf : boot.o kernel.o uart.o PL0_test.o PL_0_test_embeddable.o arm-none-eabi-gcc -T linker.ld -o $@ $(ELFFLAGS) $^ kernel7.img : kernel.elf diff --git a/PL0_test.c b/PL0_test.c new file mode 100644 index 0000000..1a3d49d --- /dev/null +++ b/PL0_test.c @@ -0,0 +1,18 @@ +#include "uart.h" + +void PL0_main(void) +{ + uart_puts("hello PL0!\n\r"); + + while (1) + { + char c; + switch(c = uart_getc()) + { + case '\r': + uart_putc('\n'); + default: + uart_putc(c); + } + } +} diff --git a/PL0_test.ld b/PL0_test.ld new file mode 100644 index 0000000..430e098 --- /dev/null +++ b/PL0_test.ld @@ -0,0 +1,44 @@ +ENTRY(_start) + +SECTIONS +{ + /* 0b10101010101000000000000000000000 */ + . = 0xaaa00000; + __start = .; + __text_start = .; + .text : + { + /* have entry point at the beginning */ + KEEP(*(.text.PL0main)) + *(.text) + } + . = ALIGN(4096); /* align to page size */ + __text_end = .; + + __rodata_start = .; + .rodata : + { + *(.rodata) + } + . = ALIGN(4096); /* align to page size */ + __rodata_end = .; + + __data_start = .; + .data : + { + *(.data) + } + . = ALIGN(4096); /* align to page size */ + __data_end = .; + + __bss_start = .; + .bss : + { + bss = .; + *(.bss) + } + . = ALIGN(4096); /* align to page size */ + __bss_end = .; + __bss_size = __bss_end - __bss_start; + __end = .; +} @@ -6,6 +6,11 @@ extern char __end; +extern char + _binary_PL_0_test_img_start, + _binary_PL_0_test_img_end, + _binary_PL_0_test_img_size; + void enabling_code_from_the_net(void); void kernel_main(uint32_t r0, uint32_t r1, uint32_t atags) @@ -85,7 +90,7 @@ void kernel_main(uint32_t r0, uint32_t r1, uint32_t atags) // flat map all memory uart_puts("preparing translation table\n\r"); - short_descriptor_lvl1_t *translation_table = + short_descriptor_lvl1_t volatile *translation_table = (short_descriptor_lvl1_t*) translation_table_base; for (uint32_t i = 0; i < 4096; i++) @@ -178,6 +183,56 @@ void kernel_main(uint32_t r0, uint32_t r1, uint32_t atags) asm("mcr p15, 0, %0, c1, c0, 0\n\r" "isb" :: "r" (SCTLR.raw) : "memory"); + volatile short_section_descriptor_t *PL0_code_section = + &translation_table[0b101010101010].section_fields; + volatile short_section_descriptor_t *UART_memory_section = + &translation_table[((uint32_t) GPIO_BASE) >> 20].section_fields; + + // map code section to the memory right after out kernel + uint32_t kernel_memory_end = (uint32_t) (translation_table + 4096); + uint32_t unprivileged_memory_start = + (((kernel_memory_end - 1) >> 20) + 1) << 20; + + PL0_code_section->SECTION_BASE_ADDRESS_31_20 = + unprivileged_memory_start >> 20; + + // make the selected section and uart section available for PL0 + PL0_code_section->ACCESS_PERMISSIONS_2 = + AP_2_0_MODEL_RW_ALL >> 2; + PL0_code_section->ACCESS_PERMISSIONS_1_0 = + AP_2_0_MODEL_RW_ALL & 0b011; + + UART_memory_section->ACCESS_PERMISSIONS_2 = + AP_2_0_MODEL_RW_ALL >> 2; + UART_memory_section->ACCESS_PERMISSIONS_1_0 = + AP_2_0_MODEL_RW_ALL & 0b011; + + + // invalidate main Translation Lookup Buffer (just in case) + asm("mcr p15, 0, %0, c8, c7, 0\n\r" + "isb" :: "r" (0) : "memory"); + + // check that translation works... by copying a string using one + // mapping and reading it using other :D + char message[] = "mapped sections for PL0 code\n\r"; + + unsigned int i; + for (i = 0; i < sizeof(message); i++) + ((volatile char*) unprivileged_memory_start)[i] = message[i]; + + uart_puts((char*) (((uint32_t) 0b101010101010) << 20)); + + // now paste a userspace program to that section, jump to it and + // switch to PL0 + for (size_t i = 0; i < (size_t) &_binary_PL_0_test_img_size; i++) + ((char*) (((uint32_t) 0b101010101010) << 20))[i] = + (&_binary_PL_0_test_img_start)[i]; + + // jump to that copied code (no switch to PL0 yet, just testing) + ((void(*)(void)) (((uint32_t) 0b101010101010) << 20))(); + + while(1); + while (1) { char c; |