Compare commits

...

7 Commits

26 changed files with 394 additions and 1469 deletions

View File

@@ -1,12 +1,18 @@
cmake_minimum_required(VERSION 3.13)
project(magenta C ASM)
project(mango C ASM)
if (NOT BUILD_TOOLS_DIR)
message(FATAL_ERROR "No build tools directory specified. Please run build.sh")
endif ()
set(CMAKE_C_STANDARD 17)
set(kernel_name "Magenta")
set(kernel_exe_name "magenta_kernel")
set(kernel_arch x86_64)
set(generic_src_dirs ds init kernel libc obj sched util vm)
set(kernel_name "Mango")
set(kernel_exe_name "mango_kernel")
set(generic_src_dirs ds init kernel libc sched util vm)
set(kernel_sources "")
set(kernel_headers "")
@@ -19,7 +25,6 @@ foreach (dir ${generic_src_dirs})
set(kernel_headers ${kernel_headers} ${dir_headers})
endforeach (dir)
set(kernel_arch x86_64)
file(GLOB_RECURSE arch_sources_c arch/${kernel_arch}/*.c)
file(GLOB_RECURSE arch_sources_asm arch/${kernel_arch}/*.S)
file(GLOB_RECURSE arch_headers arch/${kernel_arch}/*.h)
@@ -40,7 +45,14 @@ target_include_directories(${kernel_exe_name} PRIVATE
target_compile_options(${kernel_exe_name} PRIVATE
-nostdlib -ffreestanding
-Wall -Werror -pedantic -Wno-language-extension-token -Wno-unused-function -Wno-gnu-statement-expression
-O2 -g -fPIC -Iinclude -Iarch/${kernel_arch}/include -Ilibc/include)
-g -fPIC -Iinclude -Iarch/${kernel_arch}/include -Ilibc/include)
add_custom_command(
TARGET ${kernel_exe_name}
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:${kernel_exe_name}> $<TARGET_FILE:${kernel_exe_name}>.debug
COMMAND ${CMAKE_STRIP} -g $<TARGET_FILE:${kernel_exe_name}>)
target_link_libraries(${kernel_exe_name} -nostdlib -ffreestanding -lgcc)
target_compile_definitions(${kernel_exe_name} PRIVATE BUILD_ID="0")

View File

@@ -3,3 +3,8 @@ target_compile_options(${kernel_exe_name} PRIVATE
-mno-sse -mno-sse2 -D_64BIT -DBYTE_ORDER=1234)
target_link_libraries(${kernel_exe_name} "-z max-page-size=0x1000" "-T ${CMAKE_CURRENT_SOURCE_DIR}/arch/x86_64/layout.ld")
add_custom_command(TARGET ${kernel_exe_name} POST_BUILD
COMMAND ${BUILD_TOOLS_DIR}/e64patch $<TARGET_FILE:${kernel_exe_name}>
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMENT "Patching kernel elf64 image"
)

View File

@@ -1,7 +1,7 @@
#include "arch/serial.h"
#include <arch/e820.h>
#include <arch/pit.h>
#include <arch/serial.h>
#include <arch/vgacon.h>
#include <mango/arg.h>
#include <mango/clock.h>
#include <mango/console.h>
@@ -52,11 +52,12 @@ void early_console_init(void)
{
const char *dest = arg_value("kernel.early-console");
if (!dest) {
dest = "ttyS0";
dest = "tty0";
}
if (!strcmp(dest, "tty0")) {
/* show log messages on VGA */
vgacon_init();
} else if (!strcmp(dest, "ttyS0")) {
/* write log messages to serial port */
early_serialcon_init(115200);

View File

@@ -1,10 +1,10 @@
#include <mango/types.h>
#include <mango/compiler.h>
#include <mango/memblock.h>
#include <mango/vm.h>
#include <mango/pmap.h>
#include <mango/printk.h>
#include <mango/status.h>
#include <mango/compiler.h>
#include <mango/pmap.h>
#include <mango/types.h>
#include <mango/vm.h>
/* some helpful datasize constants */
#define C_1GiB 0x40000000ULL
@@ -33,7 +33,7 @@ static size_t ps_size(enum page_size ps)
}
}
static pmap_t alloc_pmap()
static pmap_t alloc_pmap(void)
{
struct pml4t *p = kzalloc(sizeof *p, 0);
return vm_virt_to_phys(p);
@@ -45,12 +45,14 @@ static pte_t make_pte(pfn_t pfn, enum vm_prot prot, enum page_size size)
switch (size) {
case PS_1G:
/* pfn_t is in terms of 4KiB pages, convert to 1GiB page frame number */
/* pfn_t is in terms of 4KiB pages, convert to 1GiB page frame
* number */
pfn >>= 18;
v = (pfn & 0x3FFFFF) << 30;
break;
case PS_2M:
/* pfn_t is in terms of 4KiB pages, convert to 2MiB page frame number */
/* pfn_t is in terms of 4KiB pages, convert to 2MiB page frame
* number */
pfn >>= 9;
v = (pfn & 0x7FFFFFFF) << 21;
break;
@@ -129,14 +131,16 @@ static void delete_pdir(phys_addr_t pd)
kfree(pdir);
}
static kern_status_t do_pmap_add(pmap_t pmap, void *p, pfn_t pfn, enum vm_prot prot, enum page_size size)
static kern_status_t do_pmap_add(
pmap_t pmap,
void *p,
pfn_t pfn,
enum vm_prot prot,
enum page_size size)
{
uintptr_t pv = (uintptr_t)p;
unsigned int
pml4t_index = BAD_INDEX,
pdpt_index = BAD_INDEX,
pd_index = BAD_INDEX,
pt_index = BAD_INDEX;
unsigned int pml4t_index = BAD_INDEX, pdpt_index = BAD_INDEX,
pd_index = BAD_INDEX, pt_index = BAD_INDEX;
switch (size) {
case PS_4K:
@@ -171,16 +175,19 @@ static kern_status_t do_pmap_add(pmap_t pmap, void *p, pfn_t pfn, enum vm_prot p
struct pdpt *pdpt = NULL;
if (!pml4t->p_entries[pml4t_index]) {
pdpt = kzalloc(sizeof *pdpt, 0);
pml4t->p_entries[pml4t_index] = PTR_TO_ENTRY(vm_virt_to_phys(pdpt));
pml4t->p_entries[pml4t_index]
= PTR_TO_ENTRY(vm_virt_to_phys(pdpt));
} else {
pdpt = vm_phys_to_virt(ENTRY_TO_PTR(pml4t->p_entries[pml4t_index]));
pdpt = vm_phys_to_virt(
ENTRY_TO_PTR(pml4t->p_entries[pml4t_index]));
}
/* if we're mapping a 1GiB page, we stop here */
if (size == PS_1G) {
if (pdpt->p_entries[pdpt_index] != 0) {
/* this slot points to a pdir, delete it.
if this slot points to a hugepage, this does nothing */
if this slot points to a hugepage, this does nothing
*/
delete_pdir(pdpt->p_entries[pdpt_index]);
}
@@ -189,22 +196,25 @@ static kern_status_t do_pmap_add(pmap_t pmap, void *p, pfn_t pfn, enum vm_prot p
return KERN_OK;
}
/* 3. traverse PDPT, get PDIR (optional, 4K and 2M only) */
struct pdir *pdir = NULL;
if (!pdpt->p_entries[pdpt_index] || pdpt->p_pages[pdpt_index] & PTE_PAGESIZE) {
if (!pdpt->p_entries[pdpt_index]
|| pdpt->p_pages[pdpt_index] & PTE_PAGESIZE) {
/* entry is null, or points to a hugepage */
pdir = kzalloc(sizeof *pdir, 0);
pdpt->p_entries[pdpt_index] = PTR_TO_ENTRY(vm_virt_to_phys(pdir));
pdpt->p_entries[pdpt_index]
= PTR_TO_ENTRY(vm_virt_to_phys(pdir));
} else {
pdir = vm_phys_to_virt(ENTRY_TO_PTR(pdpt->p_entries[pdpt_index]));
pdir = vm_phys_to_virt(
ENTRY_TO_PTR(pdpt->p_entries[pdpt_index]));
}
/* if we're mapping a 2MiB page, we stop here */
if (size == PS_2M) {
if (pdir->p_entries[pd_index] != 0) {
/* this slot points to a ptab, delete it.
if this slot points to a hugepage, this does nothing */
if this slot points to a hugepage, this does nothing
*/
delete_ptab(pdir->p_entries[pd_index]);
}
@@ -214,7 +224,8 @@ static kern_status_t do_pmap_add(pmap_t pmap, void *p, pfn_t pfn, enum vm_prot p
/* 4. traverse PDIR, get PTAB (optional, 4K only) */
struct ptab *ptab = NULL;
if (!pdir->p_entries[pd_index] || pdir->p_pages[pd_index] & PTE_PAGESIZE) {
if (!pdir->p_entries[pd_index]
|| pdir->p_pages[pd_index] & PTE_PAGESIZE) {
/* entry is null, or points to a hugepage */
ptab = kzalloc(sizeof *ptab, 0);
pdir->p_entries[pd_index] = PTR_TO_ENTRY(vm_virt_to_phys(ptab));
@@ -234,7 +245,8 @@ pmap_t get_kernel_pmap(void)
void pmap_bootstrap(void)
{
can_use_gbpages = gigabyte_pages();
printk("pmap: gigabyte pages %sabled", can_use_gbpages == 1 ? "en" : "dis");
printk("pmap: gigabyte pages %sabled",
can_use_gbpages == 1 ? "en" : "dis");
enable_nx();
printk("pmap: NX protection enabled");
@@ -251,16 +263,19 @@ void pmap_bootstrap(void)
the kernel and memblock-allocated data. */
uintptr_t vbase = VM_KERNEL_VOFFSET;
for (size_t i = 0; i < C_2GiB; i += hugepage_sz) {
do_pmap_add(kernel_pmap,
do_pmap_add(
kernel_pmap,
(void *)(vbase + i),
PFN(i),
VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXEC | VM_PROT_SVR,
VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXEC
| VM_PROT_SVR,
hugepage);
}
phys_addr_t pmem_limit = 0x0;
struct memblock_iter it;
for_each_mem_range(&it, 0x00, UINTPTR_MAX) {
for_each_mem_range(&it, 0x00, UINTPTR_MAX)
{
if (it.it_limit > pmem_limit) {
pmem_limit = it.it_limit;
}
@@ -268,10 +283,13 @@ void pmap_bootstrap(void)
vbase = VM_PAGEMAP_BASE;
for (size_t i = 0; i < pmem_limit; i += hugepage_sz) {
do_pmap_add(kernel_pmap,
do_pmap_add(
kernel_pmap,
(void *)(vbase + i),
PFN(i),
VM_PROT_READ | VM_PROT_WRITE | VM_PROT_SVR | VM_PROT_NOCACHE, hugepage);
VM_PROT_READ | VM_PROT_WRITE | VM_PROT_SVR
| VM_PROT_NOCACHE,
hugepage);
}
pmap_switch(kernel_pmap);
@@ -284,10 +302,14 @@ pmap_t pmap_create(void)
void pmap_destroy(pmap_t pmap)
{
}
kern_status_t pmap_add(pmap_t pmap, void *p, pfn_t pfn, enum vm_prot prot, enum pmap_flags flags)
kern_status_t pmap_add(
pmap_t pmap,
void *p,
pfn_t pfn,
enum vm_prot prot,
enum pmap_flags flags)
{
enum page_size ps = PS_4K;
if (flags & PMAP_HUGEPAGE) {
@@ -297,7 +319,13 @@ kern_status_t pmap_add(pmap_t pmap, void *p, pfn_t pfn, enum vm_prot prot, enum
return do_pmap_add(pmap, p, pfn, prot, ps);
}
kern_status_t pmap_add_block(pmap_t pmap, void *p, pfn_t pfn, size_t len, enum vm_prot prot, enum pmap_flags flags)
kern_status_t pmap_add_block(
pmap_t pmap,
void *p,
pfn_t pfn,
size_t len,
enum vm_prot prot,
enum pmap_flags flags)
{
return KERN_OK;
}

View File

@@ -1,39 +1,50 @@
#include <stdint.h>
uint8_t inportb(uint16_t port) {
uint8_t inportb(uint16_t port)
{
uint8_t data;
__asm__ __volatile__("inb %1, %0" : "=a"(data) : "dN"(port));
return data;
}
void outportb(uint16_t port, uint8_t data) {
void outportb(uint16_t port, uint8_t data)
{
__asm__ __volatile__("outb %1, %0" : : "dN"(port), "a"(data));
}
uint16_t inportw(uint16_t port) {
uint16_t inportw(uint16_t port)
{
uint16_t data;
__asm__ __volatile__("inw %1, %0" : "=a"(data) : "dN"(port));
return data;
}
void outportw(uint16_t port, uint16_t data) {
void outportw(uint16_t port, uint16_t data)
{
__asm__ __volatile__("outw %1, %0" : : "dN"(port), "a"(data));
}
uint32_t inportl(uint16_t port) {
uint32_t inportl(uint16_t port)
{
uint32_t data;
__asm__ __volatile__("inl %%dx, %%eax" : "=a"(data) : "dN"(port));
return data;
}
void outportl(uint16_t port, uint32_t data) {
void outportl(uint16_t port, uint32_t data)
{
__asm__ __volatile__("outl %%eax, %%dx" : : "dN"(port), "a"(data));
}
void outportsw(uint16_t port, void *data, uint32_t size) {
void outportsw(uint16_t port, void *data, uint32_t size)
{
__asm__ __volatile__("rep outsw" : "+S"(data), "+c"(size) : "d"(port));
}
void inportsw(uint16_t port, unsigned char *data, unsigned long size) {
__asm__ __volatile__("rep insw" : "+D"(data), "+c"(size) : "d"(port) : "memory");
void inportsw(uint16_t port, unsigned char *data, unsigned long size)
{
__asm__ __volatile__("rep insw"
: "+D"(data), "+c"(size)
: "d"(port)
: "memory");
}

View File

@@ -1,11 +1,8 @@
#include <arch/irq.h>
#include <arch/ports.h>
#include <arch/serial.h>
#include <mango/device.h>
#include <mango/kext.h>
#include <mango/libc/stdio.h>
#include <mango/printk.h>
#include <mango/tty.h>
#define COM1 0x3F8
#define COM2 0x2F8

View File

@@ -1,7 +1,21 @@
find_program(QEMU qemu-system-x86_64)
set(DEBUG_SESSION ${CMAKE_SOURCE_DIR}/tools/kernel-debug/debug_session.sh)
set(DEBUG_CFG_GDB ${CMAKE_SOURCE_DIR}/tools/kernel-debug/gdb_session_init)
set(DEBUG_CFG_LLDB ${CMAKE_SOURCE_DIR}/tools/kernel-debug/lldb_session_init)
add_custom_target(run
USES_TERMINAL
COMMAND ${QEMU}
-kernel $<TARGET_FILE:${kernel_exe_name}>
-serial stdio)
# LLDB DEPENDS ON AN ELF64 EXECUTABLE.
# .DBG FILE MUST NOT BE PATCHED WITH E64PATCH!
add_custom_target(debug
USES_TERMINAL
COMMAND ${DEBUG_SESSION}
${DEBUG_CFG_GDB}
${DEBUG_CFG_LLDB}
${QEMU} -kernel $<TARGET_FILE:${kernel_exe_name}>
-S -s
-monitor stdio)

View File

@@ -1,11 +1,13 @@
# the name of the target operating system
set(CMAKE_SYSTEM_NAME Magenta)
set(CMAKE_SYSTEM_NAME Mango)
# which compilers to use for C and C++
set(CMAKE_C_COMPILER x86_64-elf-gcc)
set(CMAKE_ASM_COMPILER x86_64-elf-gcc)
set(CMAKE_CXX_COMPILER x86_64-elf-g++)
set(CMAKE_STRIP x86_64-elf-strip)
set(CMAKE_C_COMPILER_WORKS TRUE)
set(CMAKE_CXX_COMPILER_WORKS TRUE)

126
arch/x86_64/vga.c Normal file
View File

@@ -0,0 +1,126 @@
#include <arch/irq.h>
#include <arch/ports.h>
#include <arch/serial.h>
#include <mango/libc/stdio.h>
#include <mango/machine/vm.h>
#include <mango/printk.h>
struct vga_console {
uint16_t *vga_framebuffer;
unsigned int vga_cursor_x, vga_cursor_y;
unsigned int vga_screen_width, vga_screen_height;
uint8_t vga_attrib;
};
static struct vga_console vga_con = {
.vga_attrib = 0x0F,
.vga_screen_width = 80,
.vga_screen_height = 25,
.vga_framebuffer = (uint16_t *)0xffffffff800b8000,
};
static void vga_console_clear(struct vga_console *con)
{
size_t len = con->vga_screen_width * con->vga_screen_height;
for (size_t i = 0; i < len; i++) {
con->vga_framebuffer[i] = (uint16_t)con->vga_attrib << 8;
}
con->vga_cursor_x = 0;
con->vga_cursor_y = 0;
}
static void vga_console_show_cursor(struct vga_console *con)
{
size_t start = 0, end = 15;
outportb(0x3D4, 0x0A);
outportb(0x3D5, (inportb(0x3D5) & 0xC0) | start);
outportb(0x3D4, 0x0B);
outportb(0x3D5, (inportb(0x3D5) & 0xE0) | end);
}
static void vga_console_update_cursor(struct vga_console *con)
{
uint16_t pos
= con->vga_cursor_y * con->vga_screen_width + con->vga_cursor_x;
outportb(0x3D4, 0x0F);
outportb(0x3D5, (uint8_t)(pos & 0xFF));
outportb(0x3D4, 0x0E);
outportb(0x3D5, (uint8_t)((pos >> 8) & 0xFF));
}
static void vga_console_scroll(struct vga_console *con)
{
uint16_t *src = &con->vga_framebuffer[con->vga_screen_width];
uint16_t *dest = &con->vga_framebuffer[0];
size_t len = (con->vga_screen_height - 1) * con->vga_screen_width
* sizeof *con->vga_framebuffer;
memcpy(dest, src, len);
dest = &con->vga_framebuffer
[(con->vga_screen_height - 1) * con->vga_screen_width];
len = con->vga_screen_width;
for (size_t i = 0; i < len; i++) {
dest[i] = (uint16_t)con->vga_attrib << 8;
}
con->vga_cursor_x = 0;
con->vga_cursor_y = con->vga_screen_height - 1;
}
static void vga_console_putc(struct vga_console *con, char c)
{
switch (c) {
case '\n':
con->vga_cursor_x = 0;
con->vga_cursor_y++;
break;
case '\r':
con->vga_cursor_x = 0;
break;
default:
con->vga_framebuffer
[con->vga_cursor_y * con->vga_screen_width
+ con->vga_cursor_x]
= ((uint16_t)con->vga_attrib << 8) | c;
con->vga_cursor_x++;
break;
}
if (con->vga_cursor_x >= con->vga_screen_width) {
con->vga_cursor_x = 0;
con->vga_cursor_y++;
}
if (con->vga_cursor_y >= con->vga_screen_height) {
vga_console_scroll(con);
}
}
static void vgacon_write(struct console *con, const char *s, unsigned int len)
{
for (unsigned int i = 0; i < len; i++) {
vga_console_putc(&vga_con, s[i]);
}
vga_console_update_cursor(&vga_con);
}
static struct console vgacon = {
.c_name = "vgacon",
.c_flags = CON_BOOT,
.c_write = vgacon_write,
.c_lock = SPIN_LOCK_INIT,
};
void vgacon_init(void)
{
vga_console_clear(&vga_con);
vga_console_show_cursor(&vga_con);
console_register(&vgacon);
}

39
build.sh Executable file
View File

@@ -0,0 +1,39 @@
#!/bin/bash
arch=$1
tools_src_dir="$(pwd)/tools"
kernel_src_dir="$(pwd)"
tools_build_dir="$(pwd)/build/tools"
kernel_build_dir="$(pwd)/build"
bin_dir="$kernel_build_dir/bin"
lib_dir="$kernel_build_dir/lib"
if [[ -z "$arch" ]]; then
echo "No architecture specified."
exit -1
fi
rm -rf $kernel_build_dir
mkdir -p $tools_build_dir
mkdir -p $kernel_build_dir
pushd $tools_build_dir
cmake \
-DCMAKE_RUNTIME_OUTPUT_DIRECTORY="$bin_dir" \
-DCMAKE_LIBRARY_OUTPUT_DIRECTORY="$lib_dir" \
-DCMAKE_ARCHIVE_OUTPUT_DIRECTORY="$lib_dir" \
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
$tools_src_dir
ninja
popd
pushd $kernel_build_dir
cmake \
-DBUILD_TOOLS_DIR="$bin_dir" \
-DCMAKE_TOOLCHAIN_FILE="$kernel_src_dir/arch/$arch/toolchain.cmake" \
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
$kernel_src_dir
ninja
popd

59
doc/kernel-interface.txt Executable file
View File

@@ -0,0 +1,59 @@
=== KERNEL TYPES ====
kern_handle_t
kern_status_t
kern_txnid_t
kern_clock_t
kern_msg_t
=== KERNEL ENUMS ====
kern_status_t:
KERN_SUCCESS
KERN_BAD_HANDLE
clockid_t:
CLOCK_REALTIME
CLOCK_MONOTONIC
=== KERNEL STRUCTS ====
kern_msg_t {
void *buf;
size_t len;
kern_handle_t *handles;
size_t nhandles
}
=== KERNEL OBJECTS ====
port
timer
address_space
page_buf
task
thread
event
=== KERNEL SYSTEM CALLS ====
handle_close
port_create
port_publish
port_connect
msg_send
msg_recv
msg_read
msg_write
timer_create
timer_arm
clock_gettime
task_get
task_move_handle

View File

@@ -1,36 +0,0 @@
#ifndef MANGO_BLOCK_H_
#define MANGO_BLOCK_H_
#include <mango/types.h>
#include <mango/btree.h>
#include <mango/locks.h>
#include <mango/status.h>
#include <stdbool.h>
enum block_device_flags {
BLOCK_DEVICE_NO_BCACHE = 0x01u,
};
struct bcache {
unsigned int b_sector_size;
unsigned int b_sectors_per_page;
struct btree b_pagetree;
};
struct bcache_sector {
struct vm_page *sect_page;
unsigned int sect_index;
void *sect_buf;
bool sect_present;
};
extern struct bcache *bcache_create(unsigned int block_size);
extern void bcache_destroy(struct bcache *cache);
extern kern_status_t bcache_init(struct bcache *cache, unsigned int block_size);
extern void bcache_deinit(struct bcache *cache);
extern kern_status_t bcache_get(struct bcache *cache, sectors_t at, bool create, struct bcache_sector *out);
extern void bcache_mark_present(struct bcache_sector *sect);
#endif

View File

@@ -1,336 +0,0 @@
#ifndef MANGO_DEVICE_H_
#define MANGO_DEVICE_H_
#include <mango/queue.h>
#include <mango/btree.h>
#include <mango/status.h>
#include <mango/bitmap.h>
#include <mango/object.h>
#include <mango/block.h>
#include <mango/fb.h>
#include <mango/ringbuffer.h>
struct device;
struct input_event;
struct input_event_hook;
struct tty_device;
#define DEV_NAME_MAX OBJECT_NAME_MAX
#define DEV_MODEL_NAME_MAX 64
#define DEV_MAJOR_MAX 1024
#define DEV_MINOR_MAX 1024
#define DEV_MAJOR_INVALID ((unsigned int)0)
#define DEV_MINOR_INVALID ((unsigned int)0)
#define INPUT_DEVICE_EVENT_QUEUE_SIZE 128
#define INPUT_DEVICE_MAX 4096
#define BLOCK_DEVICE_MAX 4096
#define FRAMEBUFFER_DEVICE_MAX 4096
#define BLOCK_DEVICE(dev) ((dev)->dev_type == DEV_TYPE_BLOCK ? &(dev)->blk : NULL)
#define CHAR_DEVICE(dev) ((dev)->dev_type == DEV_TYPE_CHAR ? &(dev)->chr : NULL)
#define NET_DEVICE(dev) ((dev)->dev_type == DEV_TYPE_NET ? &(dev)->net : NULL)
#define INPUT_DEVICE(dev) ((dev)->dev_type == DEV_TYPE_INPUT ? &(dev)->input : NULL)
#define BUS_DEVICE(dev) ((dev)->dev_type == DEV_TYPE_BUS ? &(dev)->bus : NULL)
#define FRAMEBUFFER_DEVICE(dev) ((dev)->dev_type == DEV_TYPE_FRAMEBUFFER ? &(dev)->fb : NULL)
enum device_type {
DEV_TYPE_UNKNOWN = 0,
DEV_TYPE_BLOCK,
DEV_TYPE_CHAR,
DEV_TYPE_NET,
DEV_TYPE_INPUT,
DEV_TYPE_BUS,
DEV_TYPE_FRAMEBUFFER,
};
struct iovec {
void *io_buf;
size_t io_len;
};
struct device_type_ops {
kern_status_t(*read)(struct device *, void *, size_t, size_t, size_t *, mango_flags_t);
kern_status_t(*write)(struct device *, const void *, size_t, size_t, size_t *, mango_flags_t);
kern_status_t(*register_device)(struct device *);
};
struct block_device_ops {
kern_status_t(*read_blocks)(struct device *, sectors_t, size_t *, struct iovec *, size_t, mango_flags_t);
kern_status_t(*write_blocks)(struct device *, sectors_t, size_t *, struct iovec *, size_t, mango_flags_t);
kern_status_t(*ioctl)(struct device *, unsigned int, void *);
};
struct net_device_ops {
kern_status_t(*online)(struct device *);
kern_status_t(*offline)(struct device *);
kern_status_t(*transmit)(struct device *, const void *, size_t);
kern_status_t(*ioctl)(struct device *, unsigned int, void *);
};
struct char_device_ops {
kern_status_t(*read)(struct device *, void *, size_t, size_t, size_t *, mango_flags_t);
kern_status_t(*write)(struct device *, const void *, size_t, size_t, size_t *, mango_flags_t);
};
struct input_device_ops {
kern_status_t(*ioctl)(struct device *, unsigned int, void *);
};
struct bus_device_ops {
kern_status_t(*scan)(struct device *);
};
struct framebuffer_device_ops {
kern_status_t(*set_varinfo)(struct device *, const struct framebuffer_varinfo *);
};
struct block_device {
struct block_device_ops *b_ops;
struct bcache b_cache;
enum block_device_flags b_flags;
unsigned int b_id;
unsigned int b_sector_size;
sectors_t b_capacity;
};
struct char_device {
struct char_device_ops *c_ops;
/* only valid for TTY devices */
struct tty_device *c_tty;
};
struct net_device {
struct net_device_ops *n_ops;
};
struct input_device {
struct input_device_ops *i_ops;
unsigned int i_id;
struct ringbuffer i_events;
struct queue i_hooks;
};
struct bus_device {
struct queue_entry b_buslist;
struct bus_device_ops *b_ops;
};
struct framebuffer_device {
unsigned int fb_id;
struct framebuffer_device_ops *fb_ops;
struct framebuffer_varinfo fb_varinfo;
struct framebuffer_fixedinfo fb_fixedinfo;
};
struct device {
struct object dev_base;
unsigned int dev_minor;
enum device_type dev_type;
struct device *dev_parent;
struct driver *dev_owner;
struct queue dev_children;
struct queue_entry dev_childent;
struct btree_node dev_driverent;
char dev_name[DEV_NAME_MAX];
char dev_model_name[DEV_MODEL_NAME_MAX];
void *dev_bus_priv;
void *dev_priv;
union {
struct block_device blk;
struct char_device chr;
struct net_device net;
struct input_device input;
struct bus_device bus;
struct framebuffer_device fb;
};
};
struct driver;
struct driver_ops {
/* called when a bus driver finds a device for this driver to manage. */
kern_status_t(*bind)(struct driver *, struct device *, struct device *);
/* called when driver is registered. */
kern_status_t(*install)(struct driver *);
/* called when driver is unregistered. */
kern_status_t(*uninstall)(struct driver *);
};
struct driver {
struct kext *drv_owner;
unsigned int drv_major;
DECLARE_BITMAP(drv_minors, DEV_MINOR_MAX);
char drv_name[DEV_NAME_MAX];
struct btree drv_children;
struct btree_node drv_ent;
spin_lock_t drv_lock;
void *drv_priv;
struct driver_ops *drv_ops;
};
extern kern_status_t device_init(void);
extern struct device *root_device(void);
extern struct device *misc_device(void);
extern struct device *device_alloc(void);
static inline void device_lock(struct device *dev)
{
object_lock(&dev->dev_base);
}
static inline void device_unlock(struct device *dev)
{
object_unlock(&dev->dev_base);
}
static inline void device_lock_irqsave(struct device *dev, unsigned long *flags)
{
object_lock_irqsave(&dev->dev_base, flags);
}
static inline void device_unlock_irqrestore(struct device *dev, unsigned long flags)
{
object_unlock_irqrestore(&dev->dev_base, flags);
}
extern kern_status_t device_read(struct device *dev, void *buf, size_t offset, size_t size, size_t *bytes_read, mango_flags_t flags);
extern kern_status_t device_write(struct device *dev, const void *buf, size_t offset, size_t size, size_t *bytes_written, mango_flags_t flags);
extern struct device *cast_to_device(struct object *obj);
extern struct device *generic_device_create(void);
extern struct char_device *char_device_create(void);
extern struct block_device *block_device_create(void);
extern struct net_device *net_device_create(void);
extern struct input_device *input_device_create(void);
extern struct bus_device *bus_device_create(void);
extern struct framebuffer_device *framebuffer_device_create(void);
extern struct char_device *char_device_from_generic(struct device *dev);
extern struct block_device *block_device_from_generic(struct device *dev);
extern struct net_device *net_device_from_generic(struct device *dev);
extern struct input_device *input_device_from_generic(struct device *dev);
extern struct bus_device *bus_device_from_generic(struct device *dev);
extern struct framebuffer_device *framebuffer_device_from_generic(struct device *dev);
static inline struct device *char_device_base(struct char_device *dev)
{
return (struct device *)((char *)dev - offsetof(struct device, chr));
}
static inline struct device *block_device_base(struct block_device *dev)
{
return (struct device *)((char *)dev - offsetof(struct device, blk));
}
static inline struct device *net_device_base(struct net_device *dev)
{
return (struct device *)((char *)dev - offsetof(struct device, net));
}
static inline struct device *input_device_base(struct input_device *dev)
{
return (struct device *)((char *)dev - offsetof(struct device, input));
}
static inline struct device *bus_device_base(struct bus_device *dev)
{
return (struct device *)((char *)dev - offsetof(struct device, bus));
}
static inline struct device *framebuffer_device_base(struct framebuffer_device *dev)
{
return (struct device *)((char *)dev - offsetof(struct device, fb));
}
static inline struct object *char_device_object(struct char_device *dev)
{
return &char_device_base(dev)->dev_base;
}
static inline struct object *block_device_object(struct block_device *dev)
{
return &block_device_base(dev)->dev_base;
}
static inline struct object *net_device_object(struct net_device *dev)
{
return &net_device_base(dev)->dev_base;
}
static inline struct object *input_device_object(struct input_device *dev)
{
return &input_device_base(dev)->dev_base;
}
static inline struct object *bus_device_object(struct bus_device *dev)
{
return &bus_device_base(dev)->dev_base;
}
static inline struct object *framebuffer_device_object(struct framebuffer_device *dev)
{
return &framebuffer_device_base(dev)->dev_base;
}
extern kern_status_t device_register(struct device *dev, struct driver *owner, struct device *parent);
static inline struct device *device_ref(struct device *dev)
{
return cast_to_device(object_ref(&dev->dev_base));
}
static inline void device_deref(struct device *dev)
{
object_deref(&dev->dev_base);
}
extern kern_status_t input_device_report_event(struct input_device *dev, const struct input_event *ev, bool noblock);
extern kern_status_t input_device_read(struct device *dev, void *buf, size_t offset,
size_t size, size_t *bytes_read, mango_flags_t flags);
extern kern_status_t input_device_add_hook(struct device *dev, struct input_event_hook *hook);
extern kern_status_t input_device_remove_hook(struct device *dev, struct input_event_hook *hook);
extern struct driver *driver_create(struct kext *self, const char *name);
extern kern_status_t driver_destroy(struct driver *driver);
extern kern_status_t driver_init(struct driver *driver, struct kext *self, const char *name);
extern kern_status_t driver_deinit(struct driver *driver);
extern kern_status_t driver_register(struct driver *driver);
extern kern_status_t driver_unregister(struct driver *driver);
extern unsigned int driver_alloc_minor(struct driver *driver);
extern void driver_free_minor(struct driver *driver, unsigned int minor);
extern struct device *driver_get_device(struct driver *driver, unsigned int minor);
extern kern_status_t driver_add_device(struct driver *driver, struct device *dev);
extern kern_status_t driver_remove_device(struct driver *driver, struct device *dev);
extern struct driver *system_driver(void);
extern kern_status_t framebuffer_get_fixedinfo(struct device *dev, struct framebuffer_fixedinfo *out);
extern kern_status_t framebuffer_get_varinfo(struct device *dev, struct framebuffer_varinfo *out);
extern kern_status_t framebuffer_set_varinfo(struct device *dev, const struct framebuffer_varinfo *varinfo);
static inline void driver_lock(struct driver *driver)
{
spin_lock(&driver->drv_lock);
}
static inline void driver_unlock(struct driver *driver)
{
spin_unlock(&driver->drv_lock);
}
static inline void driver_lock_irqsave(struct driver *driver, unsigned long *flags)
{
spin_lock_irqsave(&driver->drv_lock, flags);
}
static inline void driver_unlock_irqrestore(struct driver *driver, unsigned long flags)
{
spin_unlock_irqrestore(&driver->drv_lock, flags);
}
extern kern_status_t scan_all_buses(void);
#endif

View File

@@ -1,99 +0,0 @@
#ifndef MANGO_KEXT_H_
#define MANGO_KEXT_H_
#include <mango/status.h>
#include <mango/object.h>
#include <mango/compiler.h>
#include <mango/btree.h>
#define KERNEL_KEXT_ID "net.doorstuck.mango-kernel"
#define KEXT_IDENT_MAX 80
#define KEXT_NO_DEPENDENCIES NULL
#define __KEXT_INFO_VARNAME_2(a, b) a ## b
#define __KEXT_INFO_VARNAME_1(a, b) __KEXT_INFO_VARNAME_2(a, b)
#ifdef MANGO_INTERNAL
#define __KEXT_INFO_LINKAGE static
#define __KEXT_INFO_VARNAME() __KEXT_INFO_VARNAME_1(__kext_info, __LINE__)
#define __KEXT_INFO_DEPNAME() __KEXT_INFO_VARNAME_1(__kext_deps, __LINE__)
#define __KEXT_INFO_FLAGS KEXT_INTERNAL
#define __KEXT_INFO_ALIGNMENT 0x80
#else
#define __KEXT_INFO_LINKAGE
#define __KEXT_INFO_VARNAME() __kext_info
#define __KEXT_INFO_DEPNAME() __kext_deps
#define __KEXT_INFO_FLAGS KEXT_NONE
#define __KEXT_INFO_ALIGNMENT 0x80
#endif
#ifdef __cplusplus
#define DEFINE_KEXT(ident, online, offline, ...) \
static const char *__KEXT_INFO_DEPNAME()[] = { \
__VA_ARGS__, NULL \
}; \
static struct kext_info __section(".kextinfo") __aligned(__KEXT_INFO_ALIGNMENT) __used __KEXT_INFO_VARNAME() = { \
__KEXT_INFO_FLAGS, \
ident, \
online, \
offline, \
__KEXT_INFO_DEPNAME(), \
}
#else
#define DEFINE_KEXT(ident, online, offline, ...) \
static const char *__KEXT_INFO_DEPNAME()[] = { \
__VA_ARGS__, NULL \
}; \
static struct kext_info __section(".kextinfo") __aligned(__KEXT_INFO_ALIGNMENT) __used __KEXT_INFO_VARNAME() = { \
.k_flags = __KEXT_INFO_FLAGS, \
.k_ident = ident, \
.k_online = online, \
.k_offline = offline, \
.k_dependencies = __KEXT_INFO_DEPNAME(), \
}
#endif
struct kext;
enum kext_flags {
KEXT_NONE = 0x00u,
KEXT_INTERNAL = 0x01u,
KEXT_ONLINE = 0x02u,
};
struct kext_info {
enum kext_flags k_flags;
char k_ident[KEXT_IDENT_MAX];
kern_status_t(*k_online)(struct kext *);
kern_status_t(*k_offline)(struct kext *);
const char **k_dependencies;
};
struct kext {
struct object k_base;
enum kext_flags k_flags;
char k_ident[KEXT_IDENT_MAX];
uint64_t k_ident_hash;
struct btree_node k_node;
kern_status_t(*k_online)(struct kext *);
kern_status_t(*k_offline)(struct kext *);
unsigned int k_nr_dependencies;
struct kext **k_dependencies;
};
extern kern_status_t scan_internal_kexts(void);
extern kern_status_t bring_internal_kexts_online(void);
extern kern_status_t init_kernel_kext(void);
extern struct kext *kernel_kext(void);
extern kern_status_t kext_cache_init(void);
extern struct kext *kext_alloc(void);
extern void kext_release(struct kext *kext);
extern kern_status_t kext_register(struct kext *kext);
extern struct kext *kext_get_by_id(const char *ident);
extern kern_status_t kext_bring_online(struct kext *kext);
#endif

View File

@@ -1,9 +1,9 @@
#ifndef MANGO_OBJECT_H_
#define MANGO_OBJECT_H_
#include <mango/flags.h>
#include <mango/locks.h>
#include <mango/status.h>
#include <mango/flags.h>
#include <mango/vm.h>
#include <stddef.h>
@@ -18,9 +18,9 @@ extern "C" {
#define OBJECT_CAST(to_type, to_type_member, p) \
((to_type *)((uintptr_t)p) - offsetof(to_type, to_type_member))
#define OBJECT_C_CAST(c_type, c_type_member, obj_type, objp) \
OBJECT_IS_TYPE(objp, obj_type) ? OBJECT_CAST(c_type, c_type_member, (objp)) : NULL
#define OBJECT_IS_TYPE(obj, type_ptr) \
((obj)->ob_type == (type_ptr))
OBJECT_IS_TYPE(objp, obj_type) \
? OBJECT_CAST(c_type, c_type_member, (objp)) : NULL
#define OBJECT_IS_TYPE(obj, type_ptr) ((obj)->ob_type == (type_ptr))
struct object;
struct object_attrib;
@@ -30,22 +30,7 @@ enum object_type_flags {
};
struct object_ops {
kern_status_t(*open)(struct object *obj);
kern_status_t(*close)(struct object *obj);
kern_status_t(*read)(struct object *obj, void *p, size_t off, size_t *r, mango_flags_t flags);
kern_status_t(*write)(struct object *obj, const void *p, size_t off, size_t *w, mango_flags_t flags);
kern_status_t(*destroy)(struct object *obj);
kern_status_t(*query_name)(struct object *obj, char out[OBJECT_NAME_MAX]);
kern_status_t(*parse)(struct object *obj, const char *path, struct object **out);
kern_status_t(*get_named)(struct object *obj, const char *name, struct object **out);
kern_status_t(*get_at)(struct object *obj, size_t at, struct object **out);
kern_status_t(*read_attrib)(struct object *obj, struct object_attrib *attrib, char *out, size_t max, size_t *r);
kern_status_t(*write_attrib)(struct object *obj, struct object_attrib *attrib, const char *s, size_t len, size_t *r);
};
struct object_attrib {
char *a_name;
struct queue_entry a_list;
kern_status_t (*destroy)(struct object *obj);
};
struct object_type {
@@ -55,7 +40,6 @@ struct object_type {
unsigned int ob_header_offset;
struct vm_cache ob_cache;
struct queue_entry ob_list;
struct queue ob_attrib;
struct object_ops ob_ops;
};
@@ -65,7 +49,6 @@ struct object {
spin_lock_t ob_lock;
unsigned int ob_refcount;
unsigned int ob_handles;
struct queue ob_attrib;
struct queue_entry ob_list;
} __aligned(sizeof(long));
@@ -73,14 +56,6 @@ extern kern_status_t object_bootstrap(void);
extern kern_status_t object_type_register(struct object_type *p);
extern kern_status_t object_type_unregister(struct object_type *p);
extern struct object_namespace *global_namespace(void);
extern struct object_namespace *object_namespace_create(void);
extern struct object *ns_header(struct object_namespace *ns);
extern kern_status_t object_namespace_get_object(struct object_namespace *ns, const char *path, struct object **out);
extern kern_status_t object_namespace_create_link(struct object_namespace *ns, const char *linkpath, struct object *dest);
extern kern_status_t object_publish(struct object_namespace *ns, const char *path, struct object *obj);
extern kern_status_t object_unpublish(struct object_namespace *ns, struct object *obj);
extern struct object *object_create(struct object_type *type);
extern struct object *object_ref(struct object *obj);
extern void object_deref(struct object *obj);
@@ -88,28 +63,6 @@ extern void object_lock(struct object *obj);
extern void object_unlock(struct object *obj);
extern void object_lock_irqsave(struct object *obj, unsigned long *flags);
extern void object_unlock_irqrestore(struct object *obj, unsigned long flags);
static inline kern_status_t object_get(const char *path, struct object **out)
{
return object_namespace_get_object(global_namespace(), path, out);
}
extern kern_status_t object_read(struct object *obj, void *p, size_t offset, size_t max, size_t *nr_read, mango_flags_t flags);
extern kern_status_t object_write(struct object *obj, const void *p, size_t offset, size_t max, size_t *nr_written, mango_flags_t flags);
extern kern_status_t object_get_child_named(struct object *obj, const char *name, struct object **out);
extern kern_status_t object_get_child_at(struct object *obj, size_t at, struct object **out);
extern kern_status_t object_query_name(struct object *obj, char name[OBJECT_NAME_MAX]);
extern struct object *set_create(const char *name);
extern kern_status_t set_add_object(struct object *set, struct object *obj);
extern kern_status_t set_remove_object(struct object *set, struct object *obj);
extern bool object_is_set(struct object *obj);
extern struct object *link_create(const char *name, struct object *dest);
extern struct object *link_read_ptr(struct object *link);
extern bool object_is_link(struct object *obj);
extern void init_set_objects(void);
extern void init_link_objects(void);
extern void init_global_namespace(void);
#ifdef __cplusplus
}

View File

@@ -1,113 +0,0 @@
#ifndef MANGO_TERMIOS_H_
#define MANGO_TERMIOS_H_
#include <stdint.h>
#define NCCS 32
#define BRKINT 00000001
#define ICRNL 00000002
#define IGNBRK 00000004
#define IGNCR 00000010
#define IGNPAR 00000020
#define INLCR 00000040
#define INPCK 00000100
#define ISTRIP 00000200
#define IUCLC 00000400
#define IXANY 00001000
#define IXOFF 00002000
#define IXON 00004000
#define PARMRK 00010000
#define OPOST 00000001
#define OLCUC 00000002
#define ONLCR 00000004
#define OCRNL 00000010
#define ONOCR 00000020
#define ONLRET 00000040
#define NLDLY 00000100
#define NL0 00000000
#define NL1 00000100
#define OFILL 00000200
#define CRDLY 00003400
#define CR0 00000000
#define CR1 00000400
#define CR2 00001000
#define CR3 00002000
#define TABDLY 00034000
#define TAB0 00000000
#define TAB1 00004000
#define TAB2 00010000
#define TAB3 00020000
#define BSDLY 00040000
#define BS0 00000000
#define BS1 00040000
#define VTDLY 00100000
#define VT0 00000000
#define VT1 00100000
#define FFDLY 00200000
#define FF0 00000000
#define FF1 00200000
#define B0 0
#define B50 50
#define B75 75
#define B110 110
#define B134 134
#define B150 150
#define B200 200
#define B300 300
#define B600 600
#define B1200 1200
#define B1800 1800
#define B2400 2400
#define B4800 4800
#define B9600 9600
#define B19200 19200
#define B38400 38400
#define CSIZE 00000007
#define CS5 00000000
#define CS6 00000001
#define CS7 00000002
#define CS8 00000004
#define CSTOPB 00000010
#define CREAD 00000020
#define PARENB 00000040
#define PARODD 00000100
#define HUPCL 00000200
#define CLOCAL 00000400
#define ECHO 00000001
#define ECHOE 00000002
#define ECHOK 00000004
#define ECHONL 00000010
#define ICANON 00000020
#define IEXTEN 00000040
#define ISIG 00000100
#define NOFLSH 00000200
#define TOSTOP 00000400
#define XCASE 00001000
#define TCSANOW 1
#define TCSADRAIN 2
#define TCSAFLUSH 3
#define TCIFLUSH 1
#define TCOFLUSH 2
#define TCIOFLUSH (TCIFLUSH | TCOFLUSH)
typedef unsigned int speed_t;
typedef unsigned int tcflag_t;
typedef unsigned char cc_t;
struct termios {
tcflag_t c_iflag;
tcflag_t c_oflag;
tcflag_t c_cflag;
tcflag_t c_lflag;
cc_t c_line;
cc_t c_cc[NCCS];
};
#endif

View File

@@ -1,145 +0,0 @@
#ifndef MANGO_TTY_H_
#define MANGO_TTY_H_
#include <mango/status.h>
#include <mango/device.h>
#include <mango/queue.h>
#include <mango/object.h>
#include <mango/termios.h>
#include <stdint.h>
#define TTY_DEVICE(dev) ((dev)->dev_type == DEV_TYPE_CHAR ? (dev)->chr.c_tty : NULL)
#define TTY_DRIVER(drv) ((struct tty_driver *)((char *)drv - offsetof(struct tty_driver, tty_base)))
#define TTY_INPUT_QUEUE_SIZE 256
#define TTY_LINE_MAX 4096
struct kext;
/* The TTY system.
TTYs are an enhanced version of the console object. Rather than a simple output
device for log messages, TTYs are intended to support fully-featured interactive
user sessions, including advanced display manipulation (if applicable) and
buffered user input.
A TTY object is split into 2 parts:
- struct tty: This represents the terminal session, and tracks things like the cursor
position, input buffer, flags, etc.
- struct tty_driver: This is a set of function callbacks that the TTY can use to
manipulate the output device. This could represent a char-based framebuffer
device, a serial port, etc.
*/
#ifdef __cplusplus
extern "C" {
#endif
enum tty_driver_type {
/* For TTYs operating on simple IO devices like serial ports.
Allows writing characters, receiving characters, and not much else. */
TTY_DRIVER_SIMPLE,
/* For TTYs operating on more capable display interfaces.
Allows putting characters at arbitrary locations, scrolling, etc */
TTY_DRIVER_FULL,
};
/* TTY cursor status. The extra cursor styles are just for completeness,
the important one to support (if possible), is TTY_CURSOR_NONE.
The others can be interpreted as "just turn on a cursor of any style". */
enum tty_cursor {
TTY_CURSOR_ULINE,
TTY_CURSOR_BLOCK,
TTY_CURSOR_NONE,
};
/* direction to use for scrolling. The important one to support is
TTY_SCROLL_DOWN for when output overflows the display */
enum tty_scroll_dir {
TTY_SCROLL_DOWN,
TTY_SCROLL_UP,
};
enum tty_modifier_key {
TTY_KEY_OTHER = 0x00u,
TTY_KEY_CTRL = 0x01u,
TTY_KEY_ALT = 0x02u,
TTY_KEY_SHIFT = 0x04u,
};
/* character attribute. this could be as simple as VGA's 16-colour palette
plus an extra bit for bright, or a full 24-bit RGB value with bold and underline
support, depending on what the driver supports. */
typedef uint64_t tty_attrib_t;
struct tty_driver_ops {
void (*tty_init)(struct device *dev);
void (*tty_deinit)(struct device *dev);
void (*tty_clear)(struct device *dev, int x, int y, int width, int height);
void (*tty_putc)(struct device *dev, int c, int xpos, int ypos, tty_attrib_t attrib);
void (*tty_set_cursor)(struct device *dev, enum tty_cursor cur);
void (*tty_move_cursor)(struct device *dev, int x, int y);
void (*tty_scroll)(struct device *dev, enum tty_scroll_dir dir, int lines);
};
struct tty_driver {
struct driver tty_base;
char tty_name[16];
enum tty_driver_type tty_type;
struct queue_entry tty_head;
struct tty_driver_ops *tty_ops;
};
struct tty_ldisc {
char name[OBJECT_NAME_MAX];
kern_status_t(*read)(struct device *, void *, size_t, size_t *, mango_flags_t);
void(*write)(struct device *, const struct input_event *);
};
struct tty_device {
unsigned int tty_xcells, tty_ycells;
unsigned int tty_xcur, tty_ycur;
struct termios tty_config;
tty_attrib_t tty_curattrib;
enum tty_modifier_key tty_modstate;
struct tty_ldisc *tty_ldisc;
/* input characters processed from tty_events, returned by tty_read() */
struct ringbuffer tty_input;
char *tty_linebuf;
};
extern void register_tty_console(void);
extern void redirect_printk_to_tty(struct device *dest);
extern kern_status_t tty_bootstrap(void);
extern struct tty_ldisc *tty_default_line_discipline(void);
extern struct device *tty_device_create(void);
extern kern_status_t tty_device_register(struct device *dev, struct tty_driver *owner, struct device *parent);
extern void tty_set_foreground(struct device *tty);
extern kern_status_t tty_connect_foreground_input_device(struct device *input);
extern struct tty_driver *tty_driver_create(struct kext *self, const char *name);
extern kern_status_t tty_driver_destroy(struct tty_driver *drv);
extern kern_status_t tty_driver_register(struct tty_driver *drv);
extern kern_status_t tty_driver_unregister(struct tty_driver *drv);
static inline struct driver *tty_driver_base(struct tty_driver *drv)
{
return &drv->tty_base;
}
extern kern_status_t tty_read(struct device *tty, void *buf, size_t offset, size_t max, size_t *nr_read, mango_flags_t flags);
extern kern_status_t tty_write(struct device *tty, const void *buf, size_t offset, size_t len, size_t *nr_written, mango_flags_t flags);
extern kern_status_t tty_report_event(struct device *tty, const struct input_event *ev);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,10 +1,8 @@
#include <mango/arg.h>
#include <mango/clock.h>
#include <mango/cpu.h>
#include <mango/device.h>
#include <mango/init.h>
#include <mango/input.h>
#include <mango/kext.h>
#include <mango/libc/stdio.h>
#include <mango/machine/init.h>
#include <mango/object.h>
@@ -12,7 +10,6 @@
#include <mango/printk.h>
#include <mango/sched.h>
#include <mango/test.h>
#include <mango/tty.h>
#include <stdint.h>
extern unsigned long get_rflags(void);

View File

@@ -1,6 +1,6 @@
#include <mango/locks.h>
#include <mango/object.h>
#include <mango/queue.h>
#include <mango/locks.h>
#define HAS_OP(obj, opname) ((obj)->ob_type->ob_ops.opname)
@@ -9,9 +9,6 @@ static spin_lock_t object_types_lock = SPIN_LOCK_INIT;
kern_status_t object_bootstrap(void)
{
init_set_objects();
init_link_objects();
init_global_namespace();
return KERN_OK;
}
@@ -56,7 +53,8 @@ struct object *object_create(struct object_type *type)
memset(obj_buf, 0x00, type->ob_size);
struct object *obj = (struct object *)((unsigned char *)obj_buf + type->ob_header_offset);
struct object *obj = (struct object *)((unsigned char *)obj_buf
+ type->ob_header_offset);
obj->ob_type = type;
obj->ob_lock = SPIN_LOCK_INIT;
@@ -131,64 +129,3 @@ struct object *object_header(void *p)
return obj;
}
kern_status_t object_read(struct object *obj, void *p, size_t offset,
size_t max, size_t *nr_read, mango_flags_t flags)
{
kern_status_t status = KERN_UNSUPPORTED;
if (obj->ob_type->ob_ops.read) {
status = obj->ob_type->ob_ops.read(obj, p, offset, &max, flags);
} else {
max = 0;
}
if (nr_read) {
*nr_read = max;
}
return status;
}
kern_status_t object_write(struct object *obj, const void *p, size_t offset,
size_t max, size_t *nr_written, mango_flags_t flags)
{
kern_status_t status = KERN_UNSUPPORTED;
if (obj->ob_type->ob_ops.write) {
status = obj->ob_type->ob_ops.write(obj, p, offset, &max, flags);
}
return status;
}
kern_status_t object_get_child_named(struct object *obj, const char *name, struct object **out)
{
kern_status_t status = KERN_UNSUPPORTED;
if (HAS_OP(obj, get_named)) {
status = obj->ob_type->ob_ops.get_named(obj, name, out);
}
return status;
}
kern_status_t object_get_child_at(struct object *obj, size_t at, struct object **out)
{
kern_status_t status = KERN_UNSUPPORTED;
if (HAS_OP(obj, get_at)) {
status = obj->ob_type->ob_ops.get_at(obj, at, out);
}
return status;
}
kern_status_t object_query_name(struct object *obj, char name[OBJECT_NAME_MAX])
{
if (HAS_OP(obj, query_name)) {
return obj->ob_type->ob_ops.query_name(obj, name);
}
return KERN_UNSUPPORTED;
}

View File

@@ -1,62 +0,0 @@
#include <mango/object.h>
#define LINK_CAST(p) OBJECT_C_CAST(struct link, l_base, &link_type, p)
struct link {
struct object l_base;
char l_name[OBJECT_NAME_MAX];
struct object *l_dest;
};
static struct object_type link_type;
static kern_status_t link_query_name(struct object *obj, char out[OBJECT_NAME_MAX])
{
struct link *link = LINK_CAST(obj);
strncpy(out, link->l_name, OBJECT_NAME_MAX - 1);
out[OBJECT_NAME_MAX - 1] = 0;
return KERN_OK;
}
static struct object_type link_type = {
.ob_name = "link",
.ob_size = sizeof(struct link),
.ob_header_offset = offsetof(struct link, l_base),
.ob_ops = {
.query_name = link_query_name,
},
};
void init_link_objects(void)
{
object_type_register(&link_type);
}
struct object *link_create(const char *name, struct object *dest)
{
struct object *link_obj = object_create(&link_type);
if (!link_obj) {
return NULL;
}
struct link *link = LINK_CAST(link_obj);
strncpy(link->l_name, name, sizeof link->l_name - 1);
link->l_name[sizeof link->l_name - 1] = 0;
link->l_dest = object_ref(dest);
return link_obj;
}
struct object *link_read_ptr(struct object *link_obj)
{
struct link *link = LINK_CAST(link_obj);
return link->l_dest;
}
bool object_is_link(struct object *obj)
{
return obj->ob_type == &link_type;
}

View File

@@ -1,334 +0,0 @@
#include <mango/object.h>
#define NAMESPACE_CAST(p) OBJECT_C_CAST(struct object_namespace, ns_base, &ns_type, p)
static struct object_type ns_type;
static struct object_namespace *global_ns;
struct object_namespace {
/* root directory set object */
struct object ns_base;
struct object *ns_root;
};
static kern_status_t ns_query_name(struct object *obj, char out[OBJECT_NAME_MAX])
{
out[0] = '/';
out[1] = 0;
return KERN_OK;
}
static kern_status_t ns_get_child_at(struct object *obj, size_t at, struct object **out)
{
struct object_namespace *ns = NAMESPACE_CAST(obj);
return object_get_child_at(ns->ns_root, at, out);
}
static kern_status_t ns_get_child_named(struct object *obj, const char *name, struct object **out)
{
struct object_namespace *ns = NAMESPACE_CAST(obj);
return object_get_child_named(ns->ns_root, name, out);
}
static struct object_type ns_type = {
.ob_name = "namespace",
.ob_size = sizeof(struct object_namespace),
.ob_header_offset = offsetof(struct object_namespace, ns_base),
.ob_ops = {
.query_name = ns_query_name,
.get_named = ns_get_child_named,
.get_at = ns_get_child_at,
},
};
void init_global_namespace(void)
{
object_type_register(&ns_type);
global_ns = object_namespace_create();
}
struct object_namespace *global_namespace(void)
{
return global_ns;
}
struct object_namespace *object_namespace_create(void)
{
struct object *ns_object = object_create(&ns_type);
struct object_namespace *ns = NAMESPACE_CAST(ns_object);
ns->ns_root = set_create("/");
return ns;
}
static void cleanup_object_path(char *path, size_t len, size_t *parts)
{
while (path[len - 1] == '/') {
path[--len] = 0;
}
size_t final_len = len;
*parts = 0;
int slashes = 0;
for (int i = 0; path[i]; i++) {
if (path[i] == '/') {
slashes++;
continue;
}
if (slashes < 1) {
continue;
}
char *from = path + i;
char *to = path + i - slashes + 1;
int count = len - i;
memmove(to, from, count);
final_len -= (slashes - 1);
slashes = 0;
(*parts)++;
}
path[final_len] = 0;
}
struct object *ns_header(struct object_namespace *ns)
{
return &ns->ns_base;
}
kern_status_t object_namespace_get_object(struct object_namespace *ns, const char *path, struct object **out)
{
if (*path != '/') {
return KERN_INVALID_ARGUMENT;
}
while (*path == '/') {
path++;
}
size_t path_len = strlen(path);
if (path_len == 0) {
*out = object_ref(ns->ns_root);
return KERN_OK;
}
size_t parts = 0;
char *rpath = kmalloc(path_len + 1, 0);
if (!rpath) {
return KERN_NO_MEMORY;
}
memcpy(rpath, path, path_len);
rpath[path_len] = 0;
cleanup_object_path(rpath, path_len, &parts);
char *sp;
char *tok = strtok_r(rpath, "/", &sp);
struct object *cur = ns->ns_root;
unsigned long flags;
while (tok) {
object_lock_irqsave(cur, &flags);
struct object *next;
kern_status_t status = object_get_child_named(cur, tok, &next);
if (status != KERN_OK) {
object_unlock_irqrestore(cur, flags);
kfree(rpath);
return status;
}
object_unlock_irqrestore(cur, flags);
cur = next;
tok = strtok_r(NULL, "/", &sp);
object_lock_irqsave(cur, &flags);
if (!object_is_link(cur)) {
object_unlock_irqrestore(cur, flags);
continue;
}
struct object *dest_obj;
dest_obj = link_read_ptr(cur);
object_unlock_irqrestore(cur, flags);
if (!dest_obj) {
kfree(rpath);
/* TODO better error code for broken links */
return KERN_INVALID_ARGUMENT;
}
object_deref(cur);
cur = dest_obj;
}
kfree(rpath);
if (object_is_link(cur)) {
struct object *link_dest = link_read_ptr(cur);
object_deref(cur);
cur = object_ref(link_dest);
}
*out = cur;
return KERN_OK;
}
kern_status_t object_namespace_create_link(struct object_namespace *ns, const char *linkpath, struct object *dest)
{
if (*linkpath != '/') {
return KERN_INVALID_ARGUMENT;
}
while (*linkpath == '/') {
linkpath++;
}
size_t path_len = strlen(linkpath);
if (path_len == 0) {
return KERN_INVALID_ARGUMENT;
}
size_t parts = 0;
char *rpath = kmalloc(path_len + 1, 0);
if (!rpath) {
return KERN_NO_MEMORY;
}
memcpy(rpath, linkpath, path_len);
rpath[path_len] = 0;
cleanup_object_path(rpath, path_len, &parts);
char *p = rpath + strlen(rpath) - 1;
while (*p != '/' && p >= rpath) {
p--;
}
if (p == rpath) {
kfree(rpath);
return KERN_INVALID_ARGUMENT;
}
*p = '\0';
const char *linkname = p + 1;
char *sp;
char *tok = strtok_r(rpath, "/", &sp);
struct object *cur = object_ref(ns->ns_root);
unsigned long flags;
while (tok) {
object_lock_irqsave(cur, &flags);
struct object *next;
kern_status_t status = object_get_child_named(cur, tok, &next);
if (status == KERN_NO_ENTRY) {
next = set_create(tok);
if (!next) {
object_unlock_irqrestore(cur, flags);
object_deref(cur);
kfree(rpath);
return KERN_NO_MEMORY;
}
status = set_add_object(cur, next);
object_unlock_irqrestore(cur, flags);
object_deref(cur);
} else {
object_unlock_irqrestore(cur, flags);
}
if (status != KERN_OK) {
kfree(rpath);
return status;
}
cur = next;
tok = strtok_r(NULL, "/", &sp);
}
struct object *link = link_create(linkname, dest);
kfree(rpath);
if (!link) {
object_deref(cur);
return KERN_NO_MEMORY;
}
object_lock_irqsave(cur, &flags);
kern_status_t status = set_add_object(cur, link);
object_unlock_irqrestore(cur, flags);
object_deref(cur);
object_deref(link);
return status;
}
kern_status_t object_publish(struct object_namespace *ns, const char *path, struct object *obj)
{
if (*path != '/') {
return KERN_INVALID_ARGUMENT;
}
while (*path == '/') {
path++;
}
size_t path_len = strlen(path);
if (path_len == 0) {
return set_add_object(ns->ns_root, obj);
}
size_t parts = 0;
char *rpath = kmalloc(path_len, 0);
if (!rpath) {
return KERN_NO_MEMORY;
}
memcpy(rpath, path, path_len);
cleanup_object_path(rpath, path_len, &parts);
char *sp;
char *tok = strtok_r(rpath, "/", &sp);
struct object *cur = ns->ns_root;
unsigned long flags;
while (tok) {
object_lock_irqsave(cur, &flags);
struct object *next;
kern_status_t status = object_get_child_named(cur, tok, &next);
if (status == KERN_NO_ENTRY) {
next = set_create(tok);
if (!next) {
object_unlock_irqrestore(cur, flags);
kfree(rpath);
return KERN_NO_MEMORY;
}
status = set_add_object(cur, next);
}
if (status != KERN_OK) {
object_unlock_irqrestore(cur, flags);
kfree(rpath);
return status;
}
object_unlock_irqrestore(cur, flags);
cur = next;
tok = strtok_r(NULL, "/", &sp);
}
kfree(rpath);
return set_add_object(cur, obj);
}
kern_status_t object_unpublish(struct object_namespace *ns, struct object *obj)
{
return KERN_OK;
}

134
obj/set.c
View File

@@ -1,134 +0,0 @@
#include <mango/object.h>
#define SET_CAST(p) OBJECT_C_CAST(struct set, s_base, &set_type, p)
struct set {
struct object s_base;
struct queue s_list;
char s_name[OBJECT_NAME_MAX];
};
static struct object_type set_type;
static kern_status_t set_query_name(struct object *obj, char out[OBJECT_NAME_MAX])
{
struct set *set = SET_CAST(obj);
strncpy(out, set->s_name, OBJECT_NAME_MAX - 1);
out[OBJECT_NAME_MAX - 1] = 0;
return KERN_OK;
}
static kern_status_t set_get_child_at(struct object *obj, size_t at, struct object **out)
{
struct set *set = SET_CAST(obj);
size_t i = 0;
queue_foreach(struct object, child, &set->s_list, ob_list) {
if (i == at) {
*out = object_ref(child);
return KERN_OK;
}
i++;
}
return KERN_NO_ENTRY;
}
static kern_status_t set_get_child_named(struct object *obj, const char *name, struct object **out)
{
struct set *set = SET_CAST(obj);
char child_name[OBJECT_NAME_MAX];
queue_foreach(struct object, child, &set->s_list, ob_list) {
kern_status_t status = object_query_name(child, child_name);
if (status != KERN_OK) {
continue;
}
if (!strcmp(child_name, name)) {
*out = object_ref(child);
return KERN_OK;
}
}
return KERN_NO_ENTRY;
}
static struct object_type set_type = {
.ob_name = "set",
.ob_size = sizeof(struct set),
.ob_header_offset = offsetof(struct set, s_base),
.ob_ops = {
.query_name = set_query_name,
.get_named = set_get_child_named,
.get_at = set_get_child_at,
},
};
void init_set_objects(void)
{
object_type_register(&set_type);
}
struct object *set_create(const char *name)
{
struct object *set_obj = object_create(&set_type);
if (!set_obj) {
return NULL;
}
struct set *set = SET_CAST(set_obj);
set->s_list = QUEUE_INIT;
strncpy(set->s_name, name, sizeof set->s_name - 1);
set->s_name[sizeof set->s_name - 1] = 0;
return set_obj;
}
kern_status_t set_add_object(struct object *set_obj, struct object *obj)
{
if (!object_is_set(set_obj)) {
return KERN_INVALID_ARGUMENT;
}
struct set *set = SET_CAST(set_obj);
char child_name[OBJECT_NAME_MAX];
char obj_name[OBJECT_NAME_MAX];
kern_status_t status = object_query_name(obj, obj_name);
if (status != KERN_OK) {
return status;
}
queue_foreach (struct object, child, &set->s_list, ob_list) {
object_query_name(child, child_name);
if (!strcmp(child_name, obj_name)) {
return KERN_NAME_EXISTS;
}
}
object_ref(obj);
queue_push_back(&set->s_list, &obj->ob_list);
return KERN_OK;
}
kern_status_t set_remove_object(struct object *set_obj, struct object *obj)
{
if (!object_is_set(set_obj)) {
return KERN_INVALID_ARGUMENT;
}
struct set *set = SET_CAST(set_obj);
queue_delete(&set->s_list, &obj->ob_list);
object_deref(obj);
return KERN_OK;
}
bool object_is_set(struct object *obj)
{
return obj->ob_type == &set_type;
}

View File

@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.13)
project(magenta-tools C)
project(mango-tools C)
set(tool_dirs e64patch)

View File

@@ -7,24 +7,27 @@ shift 2
if command -v gdb &> /dev/null; then
printf " \033[93;1mGDB\033[0m boot/mango_kernel\n"
tmux \
new-session -d -s hz-debug "sleep 0.3; gdb -tui -x $gdb_cfg" \; \
new-session -d -s mango-debug "sleep 0.3; gdb -tui -x $gdb_cfg" \; \
split-window -h -l 80 \; \
split-window -v -l 25 "$@"\; \
select-pane -t 1 \; \
resize-pane -R 20
resize-pane -R 20 \; \
select-pane -t 0
elif command -v lldb &> /dev/null; then
printf " \033[93;1mLLDB\033[0m boot/mango_kernel\n"
tmux \
new-session -d -s hz-debug "sleep 0.1; lldb --source $lldb_cfg" \; \
new-session -d -s mango-debug "sleep 0.1; lldb --source $lldb_cfg" \; \
split-window -h -l 160 \; \
split-window -v -l 25 "$@"\; \
select-pane -t 1 \; \
resize-pane -R 50
resize-pane -R 50 \; \
select-pane -t 0
else
printf " \033[91;1mERR\033[0m No debugger available\n"
exit -1
fi
tmux a -t hz-debug
tmux kill-session -t hz-debug
tmux a -t mango-debug
tmux kill-session -t mango-debug

View File

@@ -1,4 +1,4 @@
set confirm off
symbol-file build/mango_kernel.dbg
symbol-file mango_kernel.debug
target remote localhost:1234
set confirm on

View File

@@ -1,2 +1,2 @@
file build/mango_kernel.dbg
file mango_kernel.debug
gdb-remote localhost:1234