Merge pull request #4 from 0xKSor/feat/uart
feat: added UART support with a basic kprint in kernel
This commit is contained in:
+43
-8
@@ -1,5 +1,6 @@
|
|||||||
cmake_minimum_required(VERSION 3.10)
|
cmake_minimum_required(VERSION 3.10)
|
||||||
project(ksOSKernel LANGUAGES ASM C)
|
project(ksOSKernel LANGUAGES ASM C)
|
||||||
|
set(KERNEL_MODULE_NAME "Kernel")
|
||||||
|
|
||||||
# --- Locate Swift toolchain with Embedded Swift stdlib ---
|
# --- Locate Swift toolchain with Embedded Swift stdlib ---
|
||||||
# Priority: cmake var > env var > auto-detect
|
# Priority: cmake var > env var > auto-detect
|
||||||
@@ -62,7 +63,11 @@ add_link_options(
|
|||||||
-Wl,-T,${LINKER_SCRIPT}
|
-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)
|
set(SWIFT_OBJ ${CMAKE_CURRENT_BINARY_DIR}/kernel_swift.o)
|
||||||
|
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
@@ -75,7 +80,7 @@ add_custom_command(
|
|||||||
-O
|
-O
|
||||||
-Xcc -fno-stack-protector
|
-Xcc -fno-stack-protector
|
||||||
-Xcc -I${CMAKE_CURRENT_SOURCE_DIR}/../Common
|
-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}
|
-resource-dir ${SWIFT_RESOURCE_DIR}
|
||||||
-c ${SWIFT_SOURCES}
|
-c ${SWIFT_SOURCES}
|
||||||
-o ${SWIFT_OBJ}
|
-o ${SWIFT_OBJ}
|
||||||
@@ -89,17 +94,47 @@ set_source_files_properties(${SWIFT_OBJ} PROPERTIES
|
|||||||
GENERATED TRUE
|
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
|
add_custom_command(TARGET kernel.elf POST_BUILD
|
||||||
COMMAND ${LLVM_OBJCOPY} -O binary kernel.elf kernel.bin
|
COMMAND ${LLVM_OBJCOPY} -O binary kernel.elf kernel.bin
|
||||||
COMMENT "kernel.elf -> kernel.bin"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# --- SourceKit-LSP: generate compile_commands.json for Swift ---
|
# --- SourceKit-LSP: generate compile_commands.json for Swift (Dynamic) ---
|
||||||
set(_COMMON_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../Common")
|
set(_BRIDGING_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/Source/Support/BridgingHeader.h")
|
||||||
set(_BRIDGING_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/Source/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"
|
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"
|
||||||
)
|
)
|
||||||
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1 +0,0 @@
|
|||||||
#include "bootinfo.h"
|
|
||||||
@@ -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..<message.utf8CodeUnitCount {
|
||||||
|
_serialPutchar(Int32(message.utf8Start[i]))
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
#include "bootinfo.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
void* memmove(void* dest, const void* src, unsigned long n) {
|
void* memmove(void* dest, const void* src, unsigned long n) {
|
||||||
unsigned char* d = (unsigned char*)dest;
|
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;
|
long __stack_chk_guard = (long)0xDEADBEEFCAFEBABEULL;
|
||||||
void __stack_chk_fail(void) { while (1); }
|
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
|
// Swift runtime allocator stubs — should never be called in embedded mode
|
||||||
int posix_memalign(void** ptr, unsigned long align, unsigned long size) {
|
int posix_memalign(void** ptr, unsigned long align, unsigned long size) {
|
||||||
(void)ptr; (void)align; (void)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; }
|
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;
|
||||||
|
}
|
||||||
@@ -1,7 +1,9 @@
|
|||||||
@_cdecl("kmain")
|
@_cdecl("kmain")
|
||||||
public func kernelMain(_ bootInfo: UnsafeMutablePointer<Bootinfo>) {
|
public func kernelMain(_ bootInfo: UnsafeMutablePointer<Bootinfo>) {
|
||||||
let fb = bootInfo.pointee.framebuffer
|
let fb = bootInfo.pointee.framebuffer
|
||||||
|
|
||||||
let pixels = fb.base!
|
let pixels = fb.base!
|
||||||
|
|
||||||
let width = Int(fb.width)
|
let width = Int(fb.width)
|
||||||
let height = Int(fb.height)
|
let height = Int(fb.height)
|
||||||
let total = width * height
|
let total = width * height
|
||||||
@@ -17,4 +19,5 @@ public func kernelMain(_ bootInfo: UnsafeMutablePointer<Bootinfo>) {
|
|||||||
pixels[i] = color
|
pixels[i] = color
|
||||||
i &+= 1
|
i &+= 1
|
||||||
}
|
}
|
||||||
|
kprint("Meow prrr meow nyaaa\n")
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user