diff --git a/Kernel/CMakeLists.txt b/Kernel/CMakeLists.txt index d2225b0..507246e 100644 --- a/Kernel/CMakeLists.txt +++ b/Kernel/CMakeLists.txt @@ -1,5 +1,6 @@ cmake_minimum_required(VERSION 3.10) project(ksOSKernel LANGUAGES ASM C) +set(KERNEL_MODULE_NAME "Kernel") # --- Locate Swift toolchain with Embedded Swift stdlib --- # Priority: cmake var > env var > auto-detect @@ -62,7 +63,11 @@ add_link_options( -Wl,-T,${LINKER_SCRIPT} ) -set(SWIFT_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/Source/kernel.swift) +set(SWIFT_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/Source/kernel.swift + ${CMAKE_CURRENT_SOURCE_DIR}/Source/Arch/dtb.swift + ${CMAKE_CURRENT_SOURCE_DIR}/Source/IO/uart.swift +) set(SWIFT_OBJ ${CMAKE_CURRENT_BINARY_DIR}/kernel_swift.o) add_custom_command( @@ -75,7 +80,7 @@ add_custom_command( -O -Xcc -fno-stack-protector -Xcc -I${CMAKE_CURRENT_SOURCE_DIR}/../Common - -import-bridging-header ${CMAKE_CURRENT_SOURCE_DIR}/Source/BridgingHeader.h + -import-bridging-header ${CMAKE_CURRENT_SOURCE_DIR}/Source/Support/BridgingHeader.h -resource-dir ${SWIFT_RESOURCE_DIR} -c ${SWIFT_SOURCES} -o ${SWIFT_OBJ} @@ -89,17 +94,47 @@ set_source_files_properties(${SWIFT_OBJ} PROPERTIES GENERATED TRUE ) -add_executable(kernel.elf Source/entry.S Source/stubs.c ${SWIFT_OBJ}) +add_executable(kernel.elf Source/Arch/entry.S Source/Support/stubs.c ${SWIFT_OBJ}) add_custom_command(TARGET kernel.elf POST_BUILD COMMAND ${LLVM_OBJCOPY} -O binary kernel.elf kernel.bin - COMMENT "kernel.elf -> kernel.bin" ) -# --- SourceKit-LSP: generate compile_commands.json for Swift --- -set(_COMMON_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../Common") -set(_BRIDGING_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/Source/BridgingHeader.h") +# --- SourceKit-LSP: generate compile_commands.json for Swift (Dynamic) --- +set(_BRIDGING_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/Source/Support/BridgingHeader.h") + +set(SWIFT_ARGS + "\"${SWIFTC}\"" + "\"-target\"" "\"aarch64-none-none-elf\"" + "\"-enable-experimental-feature\"" "\"Embedded\"" + "\"-module-name\"" "\"${KERNEL_MODULE_NAME}\"" + "\"-parse-as-library\"" + "\"-import-bridging-header\"" "\"${_BRIDGING_HEADER}\"" +) +foreach(_src IN LISTS SWIFT_SOURCES) + list(APPEND SWIFT_ARGS "\"${_src}\"") +endforeach() + +string(JOIN ", " SWIFT_ARGS_JSON ${SWIFT_ARGS}) + +set(COMPDB_ENTRIES "") +list(LENGTH SWIFT_SOURCES _src_count) +math(EXPR _last_idx "${_src_count} - 1") +set(_idx 0) + +foreach(_src IN LISTS SWIFT_SOURCES) + set(_entry " {\n \"file\": \"${_src}\",\n \"directory\": \"${CMAKE_CURRENT_BINARY_DIR}\",\n \"arguments\": [${SWIFT_ARGS_JSON}]\n }") + + if(_idx LESS _last_idx) + string(APPEND _entry ",\n") + else() + string(APPEND _entry "\n") + endif() + + string(APPEND COMPDB_ENTRIES "${_entry}") + math(EXPR _idx "${_idx} + 1") +endforeach() file(GENERATE OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/compile_commands.json" - CONTENT "[\n {\n \"file\": \"${SWIFT_SOURCES}\",\n \"directory\": \"${CMAKE_CURRENT_BINARY_DIR}\",\n \"arguments\": [\n \"${SWIFTC}\",\n \"-target\", \"aarch64-none-none-elf\",\n \"-enable-experimental-feature\", \"Embedded\",\n \"-parse-as-library\",\n \"-wmo\",\n \"-O\",\n \"-Xcc\", \"-fno-stack-protector\",\n \"-Xcc\", \"-I${_COMMON_DIR}\",\n \"-import-bridging-header\", \"${_BRIDGING_HEADER}\",\n \"-resource-dir\", \"${SWIFT_RESOURCE_DIR}\",\n \"${SWIFT_SOURCES}\"\n ]\n }\n]\n" -) + CONTENT "[\n${COMPDB_ENTRIES}]\n" +) \ No newline at end of file diff --git a/Kernel/Source/Arch/dtb.swift b/Kernel/Source/Arch/dtb.swift new file mode 100644 index 0000000..04f8b8b --- /dev/null +++ b/Kernel/Source/Arch/dtb.swift @@ -0,0 +1,81 @@ +struct FDTHeader { + let magic: UInt32 // 0xd00dfeed + let totalsize: UInt32 + let off_dt_struct: UInt32 + let off_dt_strings: UInt32 + let off_mem_rsvmap: UInt32 + let version: UInt32 + let last_comp_version: UInt32 + let boot_cpuid_phys: UInt32 + let size_dt_strings: UInt32 + let size_dt_struct: UInt32 +} + +struct FDTProperty { + let len: UInt32 + let nameoff: UInt32 +} + +enum FDTToken: UInt32 { + case beginNode = 0x1 + case endNode = 0x2 + case prop = 0x3 + case nop = 0x4 + case end = 0x9 +} + +extension UInt32 { + var fromBe: UInt32 { + return self.byteSwapped + } +} + +func alignUp(_ value: Int, to: Int) -> Int { + return (value + to - 1) & ~(to - 1) +} + +let kFDTHeaderMagic = 0xd00dfeed + +func parseDTB(at pointer: UnsafeRawPointer) { + let header = pointer.bindMemory(to: FDTHeader.self, capacity: 1).pointee + guard header.magic.byteSwapped == kFDTHeaderMagic else { + return + } + + let structOffset = Int(header.off_dt_struct.byteSwapped) + let stringOffset = Int(header.off_dt_strings.byteSwapped) + + var structBase = pointer.advanced(by: structOffset) + let stringsBase = pointer.advanced(by: stringOffset) + + var finished = false + while !finished { + let rawToken = structBase.load(as: UInt32.self).byteSwapped + structBase = structBase.advanced(by: 4) + + if let token = FDTToken(rawValue: rawToken) { + switch token { + case .beginNode: + let namePointer = structBase.assumingMemoryBound(to: UInt8.self) + let name = String(cString: namePointer) + let nameLength = name.utf8.count + 1 + structBase = structBase.advanced(by: alignUp(nameLength, to: 4)) + case .prop: + let propertyHeader = structBase.load(as: FDTProperty.self) + let dataLength = Int(propertyHeader.len.byteSwapped) + let nameOffset = Int(propertyHeader.nameoff.byteSwapped) + + let namePointer = stringsBase.advanced(by: nameOffset).assumingMemoryBound(to: UInt8.self) + + structBase = structBase.advanced(by: 8) // skip header + structBase = structBase.advanced(by: alignUp(dataLength, to: 4)) // skip data for now + case .endNode: + continue + case .nop: + continue + case .end: + finished = true + } + } + } +} \ No newline at end of file diff --git a/Kernel/Source/entry.S b/Kernel/Source/Arch/entry.S similarity index 100% rename from Kernel/Source/entry.S rename to Kernel/Source/Arch/entry.S diff --git a/Kernel/Source/BridgingHeader.h b/Kernel/Source/BridgingHeader.h deleted file mode 100644 index 49e7ea7..0000000 --- a/Kernel/Source/BridgingHeader.h +++ /dev/null @@ -1 +0,0 @@ -#include "bootinfo.h" diff --git a/Kernel/Source/IO/uart.swift b/Kernel/Source/IO/uart.swift new file mode 100644 index 0000000..3d9107f --- /dev/null +++ b/Kernel/Source/IO/uart.swift @@ -0,0 +1,20 @@ +let kUARTBaseAddress: UInt = 0x09000000 // TODO: Make it dynamic by parsion DTB + +@_cdecl("putchar") +@discardableResult +public func _serialPutchar(_ char: Int32) -> Int32 { + let uartFR: UInt = kUARTBaseAddress + 0x18// TXFF -- TRansmit FIFO Full for PL011 is 5 bit of FR reg (0x18) + + while (mmio_read32(uartFR) & (1 << 5)) != 0 { + // i love pizza btw + } + + mmio_write32(UInt(kUARTBaseAddress), UInt32(char)) + return char +} + +public func kprint(_ message: StaticString) { + for i in 0.. + +static inline void mmio_write32(uintptr_t addr, uint32_t val) { + *(volatile uint32_t *)addr = val; +} + +static inline uint32_t mmio_read32(uintptr_t addr) { + return *(volatile uint32_t *)addr; +} \ No newline at end of file diff --git a/Kernel/Source/stubs.c b/Kernel/Source/Support/stubs.c similarity index 79% rename from Kernel/Source/stubs.c rename to Kernel/Source/Support/stubs.c index 57dad40..ca96b13 100644 --- a/Kernel/Source/stubs.c +++ b/Kernel/Source/Support/stubs.c @@ -1,4 +1,5 @@ #include +#include void* memmove(void* dest, const void* src, unsigned long n) { unsigned char* d = (unsigned char*)dest; @@ -26,9 +27,6 @@ void* memset(void* dest, int c, unsigned long n) { long __stack_chk_guard = (long)0xDEADBEEFCAFEBABEULL; void __stack_chk_fail(void) { while (1); } -// Swift embedded uses putchar for print(); stub so it links but does nothing -int putchar(int c) { return c; } - // Swift runtime allocator stubs — should never be called in embedded mode int posix_memalign(void** ptr, unsigned long align, unsigned long size) { (void)ptr; (void)align; (void)size; @@ -36,3 +34,9 @@ int posix_memalign(void** ptr, unsigned long align, unsigned long size) { } void free(void* ptr) { (void)ptr; } + +// Swift stdlib uses arc4random_buf for Hasher seed — stub with zeroes in bare-metal +void arc4random_buf(void* buf, unsigned long nbytes) { + unsigned char* b = (unsigned char*)buf; + while (nbytes--) *b++ = 0; +} diff --git a/Kernel/Source/kernel.swift b/Kernel/Source/kernel.swift index 4dee551..0ed9ce8 100644 --- a/Kernel/Source/kernel.swift +++ b/Kernel/Source/kernel.swift @@ -1,7 +1,9 @@ @_cdecl("kmain") public func kernelMain(_ bootInfo: UnsafeMutablePointer) { let fb = bootInfo.pointee.framebuffer + let pixels = fb.base! + let width = Int(fb.width) let height = Int(fb.height) let total = width * height @@ -17,4 +19,5 @@ public func kernelMain(_ bootInfo: UnsafeMutablePointer) { pixels[i] = color i &+= 1 } + kprint("Meow prrr meow nyaaa\n") }