From 98a96fba867ee1fbf4341f53ae3743b6a536cab1 Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Sat, 5 Jul 2025 00:42:04 +0200 Subject: [PATCH] Print the device tree node names --- common.s | 11 ++- kernel.ld | 5 + kernel.s | 18 +++- source.elna | 256 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 280 insertions(+), 10 deletions(-) diff --git a/common.s b/common.s index f20e0f8..b1a05a7 100644 --- a/common.s +++ b/common.s @@ -178,8 +178,8 @@ _is_alnum: # Prints a string. # # Parameters: -# a0 - Length of the string. -# a1 - String pointer. +# a0 - String pointer. +# a1 - Length of the string. .type write_s, @function write_s: # Prologue. @@ -191,8 +191,8 @@ write_s: sw s1, 20(sp) sw s2, 16(sp) - mv s1, a0 - mv s2, a1 + mv s1, a1 + mv s2, a0 .Lwrite_s_if: beqz s1, .Lwrite_s_end @@ -334,7 +334,8 @@ write_i: addi a1, sp, 0 call _print_i - addi a1, sp, 0 + mv a1, a0 + addi a0, sp, 0 call write_s lw ra, 28(sp) diff --git a/kernel.ld b/kernel.ld index 4c5d027..ed1aa24 100644 --- a/kernel.ld +++ b/kernel.ld @@ -27,4 +27,9 @@ SECTIONS { . = ALIGN(4); . += 128 * 1024; /* 128KB */ __stack_top = .; + + . = ALIGN(4096); + __free_ram = .; + . += 64 * 1024 * 1024; /* 64MB */ + __free_ram_end = .; } diff --git a/kernel.s b/kernel.s index 9ff500b..65ca3c2 100644 --- a/kernel.s +++ b/kernel.s @@ -30,7 +30,10 @@ kernel_main: la t0, kernel_entry csrw stvec, t0 - unimp + # unimp + + mv a0, a1 + call device_tree .Lkernel_main: j .Lkernel_main @@ -130,8 +133,8 @@ handle_trap: csrr t1, stval csrr t2, sepc - li a0, PANIC_MESSAGE_SIZE - la a1, panic_message + li a1, PANIC_MESSAGE_SIZE + la a0, panic_message call write_s li a0, ' ' @@ -181,7 +184,12 @@ panic: .section .text.boot boot: - la a0, __stack_top - mv sp, a0 # Set the stack pointer + la t0, __stack_top + mv sp, t0 # Set the stack pointer + + lw t0, (__free_ram) + la t1, next_paddr + sw t0, (t1) + call bzero j kernel_main diff --git a/source.elna b/source.elna index 55052a4..967d093 100644 --- a/source.elna +++ b/source.elna @@ -1,7 +1,263 @@ module; +const + PAGE_SIZE := 4096u; + FDT_BEGIN_NODE := 1u; + FDT_PROP := 3u; + +type + fdt_header = record + magic: Word; + totalsize: Word; + off_dt_struct: Word; + off_dt_strings: Word; + off_mem_rsvmap: Word; + version: Word; + last_comp_version: Word; + boot_cpuid_phys: Word; + size_dt_strings: Word; + size_dt_struct: Word + end; + fdt_property_header = record + len: Word; + nameoff: Word + end; + +var + next_paddr*: Pointer; + +proc write_i(value: Int); extern; +proc write_c(value: Char); extern; +proc write_s(value: String); extern; + proc separator*() -> Char; return ',' end; +proc alloc_pages(n: Word) -> Pointer; +var + paddr: Pointer; +begin + next_paddr := next_paddr + n * PAGE_SIZE; + + return paddr +end; + +(* + Prints a number in the hexadecimal format writing the digits into the sink + procedure. If the value is shorter than the padding, pads the output with + zeroes. +*) +proc print_x(value: Word, padding: Word, sink: proc(Char)) -> Word; +var + current: Word; + buffer: [8]Char; + length: Word; + written: Word; +begin + length := 0u; + written := 0u; + + while value <> 0u do + current := value & 15u; + + if current < 10u then + buffer[length] := cast(current + cast('0': Word): Char) + else + buffer[length] := cast(current - 10u + cast('a': Word): Char) + end; + length := length + 1u; + value := value >> 4u + end; + while padding > length do + padding := padding - 1u; + sink('0'); + written := written + 1u + end; + while length <> 0u do + length := length - 1u; + sink(buffer[length]); + written := written + 1u + end; + return written +end; + +proc write_x(value: Word, padding: Word) -> Word; + return print_x(value, padding, write_c) +end; + +(* + Converts 4 bytes of the input in network byte order into an unsigned integer. +*) +proc network_order(input: ^Char) -> Word; +var + result: Word; + i: Word; +begin + i := 0u; + + while i < 4u do + result := result << 8u; + result := result + cast(input^: Word); + input := input + 1u; + i := i + 1u + end; + + return result +end; + +proc print_header(header: ^fdt_header); +begin + write_s("Magic number: 0x"); + write_x(header^.magic, 8u); + write_c('\n'); + + write_s("Total size: "); + write_i(cast(header^.totalsize: Int)); + write_c('\n'); + + write_s("Struct offset: 0x"); + write_x(header^.off_dt_struct, 8u); + write_c('\n'); + + write_s("Strings offset: 0x"); + write_x(header^.off_dt_strings, 8u); + write_c('\n'); + + write_s("Memory reservation block offset: 0x"); + write_x(header^.off_mem_rsvmap, 8u); + write_c('\n'); + + write_s("Version: "); + write_i(cast(header^.version: Int)); + write_c('\n'); + + write_s("Last compatible version: "); + write_i(cast(header^.last_comp_version: Int)); + write_c('\n'); + + write_s("CPU id: "); + write_i(cast(header^.boot_cpuid_phys: Int)); + write_c('\n'); + + write_s("Strings length: "); + write_i(cast(header^.size_dt_strings: Int)); + write_c('\n'); + + write_s("Struct length: "); + write_i(cast(header^.size_dt_struct: Int)); + write_c('\n') +end; + +proc skip_node(stream: ^Char) -> ^Char; +var + token: Word; + property: fdt_property_header; +begin + (* The first token should be FDT_BEGIN_NODE. *) + token := network_order(stream); + stream := stream + 4; + + (* Read the token name. *) + while cast(stream^: Word) <> 0u do + write_c(stream^); + stream := stream + 1 + end; + stream := stream + 1; (* Skip the trailing \0 encounted in the previous step. *) + write_c('\n'); + + while cast(stream: Word) % 4u <> 0u do + stream := stream + 1 + end; + + (* Property token. *) + token := network_order(stream); + + while token = FDT_PROP do + stream := stream + 4; + + property.len := network_order(stream); + stream := stream + 4; + + property.nameoff := network_order(stream); + stream := stream + 4; + + stream := stream + property.len; + while cast(stream: Word) % 4u <> 0u do + stream := stream + 1 + end; + + token := network_order(stream) + end; + while token = FDT_BEGIN_NODE do + stream := skip_node(stream); + token := network_order(stream) + end; + (* Skip FDT_END_NODE. *) + stream := stream + 4; + + return stream +end; + +proc find_memory(stream: ^Char, header: ^fdt_header); +begin + stream := stream + header^.off_dt_struct; + + skip_node(stream); + + (* write_i(cast(stream^: Int)); + write_i(cast(token: Int)); *) + + write_c('\n') +end; + +proc parse_header(stream: ^Char, header: ^fdt_header) -> ^Char; +begin + header^.magic := network_order(stream); + stream := stream + 4; + + header^.totalsize := network_order(stream); + stream := stream + 4; + + header^.off_dt_struct := network_order(stream); + stream := stream + 4; + + header^.off_dt_strings := network_order(stream); + stream := stream + 4; + + header^.off_mem_rsvmap := network_order(stream); + stream := stream + 4; + + header^.version := network_order(stream); + stream := stream + 4; + + header^.last_comp_version := network_order(stream); + stream := stream + 4; + + header^.boot_cpuid_phys := network_order(stream); + stream := stream + 4; + + header^.size_dt_strings := network_order(stream); + stream := stream + 4; + + header^.size_dt_struct := network_order(stream); + stream := stream + 4; + + return stream +end; + +proc device_tree*(raw: Pointer); +var + raw_as_char: ^Char; + header: fdt_header; +begin + raw_as_char := cast(raw: ^Char); + + parse_header(raw_as_char, @header); + print_header(@header); + + write_c('\n'); + find_memory(raw_as_char, @header) +end; + end.