├── .gitignore ├── Makefile ├── README.md ├── arch ├── aarch64 │ ├── devices │ │ ├── gic.c │ │ ├── psci.c │ │ ├── serial.c │ │ ├── timer.c │ │ └── uart.c │ ├── include.mk │ ├── include │ │ ├── arch-hvc.h │ │ ├── arch-interrupt.h │ │ ├── arch-mmu.h │ │ ├── arch-processor.h │ │ ├── arch-psci.h │ │ ├── arch-thread.h │ │ ├── arch-timer.h │ │ ├── mmu-bits.h │ │ └── registers.h │ ├── kernel │ │ ├── calls.S │ │ ├── crti.c │ │ ├── crtn.c │ │ ├── exception.S │ │ ├── init.c │ │ ├── interrupt.c │ │ ├── mmu.c │ │ ├── processor.c │ │ ├── start.S │ │ ├── switch.S │ │ ├── thread.c │ │ └── unwind.c │ └── link.ldi └── x86_64 │ ├── devices │ ├── apic.c │ ├── hpet.c │ └── madt.c │ ├── include.mk │ ├── include │ ├── arch-interrupt.h │ ├── arch-mmu.h │ ├── arch-processor.h │ ├── arch-thread.h │ ├── arch-timer.h │ ├── x86_64-ioport.h │ ├── x86_64-madt.h │ └── x86_64-msr.h │ ├── kernel │ ├── bootstrap.S │ ├── crti.S │ ├── crtn.S │ ├── gate.S │ ├── gdt.c │ ├── idt.c │ ├── init.c │ ├── interrupt.c │ ├── mmu.c │ ├── processor.c │ ├── start.S │ ├── switch.S │ ├── thread.c │ ├── time.c │ ├── timer.c │ ├── tss.c │ └── unwind.c │ └── link.ldi ├── config.cfg ├── doc ├── TODO ├── arch.txt ├── blockpoint.txt ├── global_defines.txt ├── mapping.txt └── ports.txt ├── drivers ├── ahci │ ├── ahci.c │ ├── ahci.h │ ├── command.c │ ├── include.mk │ └── main.c ├── e1000.c ├── e1000.h ├── ext2 │ ├── ext2.c │ ├── ext2.h │ └── include.mk ├── include.mk ├── lo.c ├── pci.c └── rtl8139.c ├── include ├── _default.h ├── arena.h ├── assert.h ├── block.h ├── blocklist.h ├── charbuffer.h ├── debug.h ├── device.h ├── devices │ └── serial.h ├── drivers │ └── pci.h ├── errno.h ├── fcntl.h ├── file.h ├── frame.h ├── fs │ ├── dirent.h │ ├── filesystem.h │ ├── inode.h │ ├── path.h │ ├── proc.h │ ├── socket.h │ ├── stat.h │ └── sys.h ├── interrupt.h ├── ioctl.h ├── klibc.h ├── ksymbol.h ├── lib │ ├── bitmap.h │ ├── elf.h │ ├── hash.h │ ├── heap.h │ ├── linkedlist.h │ ├── stack.h │ └── ubsan.h ├── map.h ├── mmu.h ├── mutex.h ├── net │ ├── ipv6.h │ ├── network.h │ ├── nic.h │ └── packet.h ├── obj │ ├── object.h │ └── process.h ├── panic.h ├── printk.h ├── priqueue.h ├── process.h ├── processor.h ├── random.h ├── refcount.h ├── signal.h ├── slab.h ├── spinlock.h ├── string.h ├── sys.h ├── syscall.h ├── system.h ├── termios.h ├── thread-bits.h ├── thread.h ├── timer.h ├── trace.h ├── worker.h └── workqueue.h ├── kernel ├── block.c ├── blocklist.c ├── charbuffer.c ├── com.c ├── debug │ ├── include.mk │ ├── perf.c │ ├── trace.c │ ├── ubsan.c │ └── unwind.c ├── device.c ├── elf.c ├── frame.c ├── fs │ ├── char.c │ ├── dirent.c │ ├── file.c │ ├── filesystem.c │ ├── include.mk │ ├── inode.c │ ├── inoderw.c │ ├── link.c │ ├── path.c │ ├── pipe.c │ ├── proc.c │ ├── ramfs.c │ └── socket.c ├── include.mk ├── interrupt.c ├── kobj_lru.c ├── ksymbol.c ├── ksymbol_weak.c ├── main.c ├── mapping.c ├── mmu.c ├── mutex.c ├── net │ ├── ethernet.c │ ├── icmp6.c │ ├── include.mk │ ├── ipv6.c │ ├── ipv6rawsock.c │ ├── network.c │ ├── nic.c │ ├── packet.c │ ├── tcp.c │ ├── udp.c │ └── unix.c ├── panic.c ├── pm_buddy.c ├── printk.c ├── process.c ├── processor.c ├── pty.c ├── queue.c ├── random.c ├── schedule.c ├── signal.c ├── slab.c ├── spinlock.c ├── syms.c.begin ├── syms.c.end ├── synchro.c ├── sys │ ├── ctl.c │ ├── execve.c │ ├── fork.c │ ├── futex.c │ ├── include.mk │ ├── info.c │ ├── map.c │ ├── open.c │ ├── path.c │ ├── poll.c │ ├── proc.c │ ├── process.c │ ├── select.c │ ├── sync.c │ ├── thread.c │ └── time.c ├── syscall.c ├── test.c ├── thread.c ├── time.c ├── timer.c ├── wait.c ├── worker.c └── workqueue.c ├── lib ├── ds │ ├── hash.c │ ├── heap.c │ ├── include.mk │ ├── linkedlist.c │ ├── qsort.c │ └── stack.c ├── fdt │ ├── LICENSE │ ├── Makefile.libfdt │ ├── TODO │ ├── fdt.c │ ├── fdt_addresses.c │ ├── fdt_empty_tree.c │ ├── fdt_ro.c │ ├── fdt_rw.c │ ├── fdt_strerror.c │ ├── fdt_sw.c │ ├── fdt_wip.c │ ├── include.mk │ ├── include │ │ ├── fdt.h │ │ ├── libfdt.h │ │ └── libfdt_env.h │ ├── libfdt_internal.h │ └── version.lds └── string │ ├── include.mk │ └── mem.c ├── machine ├── pc │ ├── devices │ │ ├── acpi.c │ │ ├── ioapic.c │ │ ├── keyboard.c │ │ ├── serial.c │ │ ├── uart.c │ │ └── vga.c │ ├── include.mk │ ├── include │ │ ├── machine │ │ │ ├── acpi.h │ │ │ ├── machine.h │ │ │ └── memmap.h │ │ └── multiboot.h │ └── machine.c └── virt │ ├── include.mk │ ├── include │ └── machine │ │ ├── gic.h │ │ ├── machine.h │ │ └── memmap.h │ └── kernel │ └── init.c ├── ports ├── build.sh ├── clean.sh ├── get.sh ├── p.sh ├── package.sh └── ports │ ├── autoconf │ ├── autoconf-2.69-seaos.patch │ └── build.sh │ ├── automake │ └── build.sh │ ├── bash │ ├── bash-4.3-seaos.patch │ └── build.sh │ ├── binutils │ └── build.sh │ ├── bison │ └── build.sh │ ├── coreutils │ ├── build.sh │ └── coreutils-8.25-seaos.patch │ ├── curl │ └── build.sh │ ├── diffutils │ └── build.sh │ ├── dropbear │ ├── build.sh │ └── dropbear-2016.74-seaos-all.patch │ ├── findutils │ └── build.sh │ ├── flex │ ├── build.sh │ └── flex-2.6.0-seaos.patch │ ├── gawk │ └── build.sh │ ├── gcc │ ├── build.sh │ └── gcc-5.3.0-seaos.patch │ ├── gdbm │ └── build.sh │ ├── git │ └── build.sh │ ├── gmp │ └── build.sh │ ├── grep │ └── build.sh │ ├── groff │ ├── build.sh │ └── groff-1.22.3-seaos.patch │ ├── gzip │ └── build.sh │ ├── less │ └── build.sh │ ├── libpipeline │ └── build.sh │ ├── libz │ └── build.sh │ ├── lynx │ └── build.sh │ ├── m4 │ └── build.sh │ ├── make │ └── build.sh │ ├── man-db │ └── build.sh │ ├── mpc │ └── build.sh │ ├── mpfr │ └── build.sh │ ├── ncurses │ ├── build.sh │ └── ncurses-6.0-seaos.patch │ ├── openssl │ └── build.sh │ ├── readline │ └── build.sh │ ├── rsync │ └── build.sh │ ├── seaosbase │ └── build.sh │ ├── sed │ ├── build.sh │ └── sed-4.2.2-seaos.patch │ ├── shadow │ ├── build.sh │ └── shadow-4.2-seaos-all.patch │ ├── tar │ └── build.sh │ └── vim │ └── build.sh ├── prepare.sh ├── sysroot └── usr │ └── src │ ├── cond │ ├── cond.c │ ├── cond.h │ ├── include.mk │ ├── keyboard.c │ └── output.c │ ├── include.mk │ ├── init.c │ ├── lookup.c │ ├── netcat.c │ ├── ping.c │ ├── ps.c │ ├── pswitch.c │ ├── sctl.c │ ├── syslogd.c │ ├── thr.c │ └── udps.c ├── tests └── build-opts-test.sh ├── toolchain.sh └── tools ├── gcc-5.3.0-seaos.patch ├── qemu-ifup.sh └── strip-all.sh /.gitignore: -------------------------------------------------------------------------------- 1 | toolchain 2 | toolchain-4.9 3 | build 4 | initrd 5 | sysroot-install 6 | sysroot 7 | !sysroot/usr/src/* 8 | !sysroot/usr/etc/* 9 | ports/build 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Build Instructions 2 | ------------------ 3 | 4 | Good luck. You'll need a cross compiler. 5 | There's a script in this repo called 'toolchain.sh' which will do it for you. I've tested it only 6 | on the vegas nodes, so it'll probably work. Probably. 7 | 8 | Once you have the cross compiler set up and installed, and in your PATH, you can edit config.cfg to set 9 | options for the build. 10 | 11 | To build, run 'make'. To test, run 'make test'. If you're using the x86 version, you may want to run 'QEMU_FLAGS="-enable-kvm" make test' 12 | to make it run faster. 13 | -------------------------------------------------------------------------------- /arch/aarch64/devices/gic.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define GICC_WRITE(reg, value) \ 6 | *(uint32_t *)(GIC_CPU_BASE + reg) = value 7 | 8 | #define GICD_WRITE(reg, value) \ 9 | *(uint32_t *)(GIC_DIST_BASE + reg) = value 10 | 11 | #define GICC_READ(reg) \ 12 | *(uint32_t *)(GIC_CPU_BASE + reg) 13 | 14 | #define GICD_READ(reg) \ 15 | *(uint32_t *)(GIC_DIST_BASE + reg) 16 | 17 | #define GICC_CTLR 0 18 | #define GICC_PMR 0x4 19 | #define GICC_IAR 0xc 20 | #define GICC_EOIR 0x10 21 | 22 | 23 | #define GICD_CTLR (0x000) 24 | #define GICD_TYPER (0x004) 25 | #define GICD_IIDR (0x008) 26 | #define GICD_IGROUPR(n) (0x080 + (n) * 4) 27 | #define GICD_ISENABLER(n) (0x100 + (n) * 4) 28 | #define GICD_ICENABLER(n) (0x180 + (n) * 4) 29 | #define GICD_ISPENDR(n) (0x200 + (n) * 4) 30 | #define GICD_ICPENDR(n) (0x280 + (n) * 4) 31 | #define GICD_ISACTIVER(n) (0x300 + (n) * 4) 32 | #define GICD_ICACTIVER(n) (0x380 + (n) * 4) 33 | #define GICD_IPRIORITYR(n) (0x400 + (n) * 4) 34 | #define GICD_ITARGETSR(n) (0x800 + (n) * 4) 35 | #define GICD_ICFGR(n) (0xc00 + (n) * 4) 36 | #define GICD_NSACR(n) (0xe00 + (n) * 4) 37 | #define GICD_SGIR (0xf00) 38 | #define GICD_CPENDSGIR(n) (0xf10 + (n) * 4) 39 | #define GICD_SPENDSGIR(n) (0xf20 + (n) * 4) 40 | 41 | void gic_enable_vector(int vector) 42 | { 43 | int r = vector / 32; 44 | uint32_t mask = 1ULL << (vector % 32); 45 | GICD_WRITE(GICD_ISENABLER(r), mask); 46 | } 47 | 48 | void gic_disable_vector(int vector) 49 | { 50 | int r = vector / 32; 51 | uint32_t mask = 1ULL << (vector % 32); 52 | GICD_WRITE(GICD_ICENABLER(r), mask); 53 | } 54 | 55 | void arch_interrupt_mask(int vector) 56 | { 57 | gic_disable_vector(vector); 58 | } 59 | 60 | void arch_interrupt_unmask(int vector) 61 | { 62 | gic_enable_vector(vector); 63 | } 64 | 65 | uint32_t gic_read_interrupt_number(void) 66 | { 67 | uint32_t v = GICC_READ(GICC_IAR); 68 | return v; 69 | } 70 | 71 | void gic_signal_eoi(uint32_t vector) 72 | { 73 | GICC_WRITE(GICC_EOIR, vector); 74 | } 75 | 76 | void gic_init(void) 77 | { 78 | /* disable all interrupts, and clear their pending 79 | * status */ 80 | for(int i=0;i 2 | 3 | unsigned long psci_hvc_cmd2(unsigned long func, unsigned long arg1, unsigned long arg2) 4 | { 5 | return aarch64_hvc2(func, arg1, arg2); 6 | } 7 | 8 | unsigned long psci_hvc_cmd3(unsigned long func, unsigned long arg1, unsigned long arg2, unsigned long arg3) 9 | { 10 | return aarch64_hvc3(func, arg1, arg2, arg3); 11 | } 12 | 13 | -------------------------------------------------------------------------------- /arch/aarch64/devices/serial.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define SERIAL_BASE (UART(UART_SERIAL) + PHYS_MAP_START) 4 | #define SERIAL_FLAG_REGISTER 0x18 5 | #define SERIAL_BUFFER_FULL (1 << 5) 6 | 7 | extern void uart_putc(char); 8 | extern unsigned char uart_getc(void); 9 | static void serial_putc (char c) 10 | { 11 | uart_putc(c); 12 | if (c == '\n') 13 | { 14 | serial_putc('\r'); 15 | } 16 | } 17 | 18 | void serial_puts(const char * str) 19 | { 20 | while (*str) serial_putc (*str++); 21 | } 22 | 23 | unsigned char serial_getc(void) 24 | { 25 | return uart_getc(); 26 | } 27 | 28 | -------------------------------------------------------------------------------- /arch/aarch64/devices/timer.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | int arch_timer_init(void) 4 | { 5 | asm volatile ("mov x0, #0; msr cntp_tval_el0, x0" ::: "x0"); 6 | asm volatile ("mov x0, #1; msr cntp_ctl_el0, x0" ::: "x0"); 7 | return TIMER_INTERRUPT; 8 | } 9 | 10 | void arch_timer_tick(void) 11 | { 12 | asm volatile ("mov x0, #0; msr cntp_ctl_el0, x0" ::: "x0"); 13 | asm volatile ("mov x0, %0; msr cntp_tval_el0, x0" ::"r"(100ul): "x0"); 14 | asm volatile ("mov x0, #1; msr cntp_ctl_el0, x0" ::: "x0"); 15 | } 16 | 17 | -------------------------------------------------------------------------------- /arch/aarch64/include.mk: -------------------------------------------------------------------------------- 1 | TOOLCHAIN_PREFIX=aarch64-elf 2 | 3 | CFLAGS+=-mcpu=cortex-a57 -mlittle-endian -mgeneral-regs-only 4 | ASFLAGS+=-mcpu=cortex-a57 -mlittle-endian 5 | 6 | ARCH_SUPPORTED=FEATURE_SUPPORTED_UNWIND FEATURE_SUPPORTED_CYCLE_COUNT 7 | 8 | QEMU_FLAGS+=-cpu cortex-a57 9 | 10 | ASM_SOURCES+= \ 11 | $(ARCHDIR)/kernel/start.S \ 12 | $(ARCHDIR)/kernel/exception.S \ 13 | $(ARCHDIR)/kernel/switch.S \ 14 | $(ARCHDIR)/kernel/calls.S 15 | C_SOURCES+= \ 16 | $(ARCHDIR)/kernel/interrupt.c \ 17 | $(ARCHDIR)/kernel/init.c \ 18 | $(ARCHDIR)/kernel/processor.c \ 19 | $(ARCHDIR)/kernel/unwind.c \ 20 | $(ARCHDIR)/kernel/mmu.c \ 21 | $(ARCHDIR)/kernel/crti.c \ 22 | $(ARCHDIR)/kernel/crtn.c \ 23 | $(ARCHDIR)/kernel/thread.c \ 24 | $(ARCHDIR)/devices/gic.c \ 25 | $(ARCHDIR)/devices/serial.c \ 26 | $(ARCHDIR)/devices/timer.c \ 27 | $(ARCHDIR)/devices/psci.c \ 28 | $(ARCHDIR)/devices/uart.c 29 | 30 | 31 | # these are defined by machine's include.mk 32 | CFLAGS+=-DKERNEL_LOAD_OFFSET=$(KERNEL_LOAD_OFFSET) -DKERNEL_PHYS_BASE=$(KERNEL_PHYS_BASE) -DKERNEL_VIRT_BASE=$(KERNEL_VIRT_BASE) $(addprefix -D,$(ARCH_SUPPORTED)) 33 | 34 | $(BUILDDIR)/link.ld: $(ARCHDIR)/link.ldi 35 | @echo -e "[GEN]\t$(BUILDDIR)/link.ld" 36 | @sed "s/%KERNEL_VIRT_BASE%/$(KERNEL_VIRT_BASE)/g" < $(ARCHDIR)/link.ldi | sed "s/%KERNEL_PHYS_BASE%/$(KERNEL_PHYS_BASE)/g" | sed "s/%KERNEL_LOAD_OFFSET%/$(KERNEL_LOAD_OFFSET)/g" > $(BUILDDIR)/link.ld 37 | -------------------------------------------------------------------------------- /arch/aarch64/include/arch-hvc.h: -------------------------------------------------------------------------------- 1 | #ifndef __ARCH_HVC_H 2 | #define __ARCH_HVC_H 3 | 4 | unsigned long aarch64_hvc2(unsigned long, unsigned long, unsigned long); 5 | unsigned long aarch64_hvc3(unsigned long, unsigned long, unsigned long, unsigned long); 6 | 7 | #endif 8 | 9 | -------------------------------------------------------------------------------- /arch/aarch64/include/arch-interrupt.h: -------------------------------------------------------------------------------- 1 | #ifndef __ARCH_INTERRUPT_H 2 | #define __ARCH_INTERRUPT_H 3 | #include 4 | static inline uint32_t arch_interrupt_set(int st) 5 | { 6 | uint64_t oldmask; 7 | asm volatile("mrs %0, DAIF" : "=r"(oldmask)); 8 | asm volatile("msr DAIF, %0" :: "r"(st ? 0ul : 1ul << 6 | 1ul << 7)); 9 | if(oldmask & (1 << 6)) 10 | return 0; 11 | return 1; 12 | } 13 | 14 | struct exception_frame { 15 | uint64_t x0; 16 | uint64_t x1; 17 | uint64_t x2; 18 | uint64_t x3; 19 | uint64_t x4; 20 | uint64_t x5; 21 | uint64_t x6; 22 | uint64_t x7; 23 | uint64_t x8; 24 | uint64_t x9; 25 | uint64_t x10; 26 | uint64_t x11; 27 | uint64_t x12; 28 | uint64_t x13; 29 | uint64_t x14; 30 | uint64_t x15; 31 | uint64_t x16; 32 | uint64_t x17; 33 | uint64_t x18; 34 | uint64_t x19; 35 | uint64_t x20; 36 | uint64_t x21; 37 | uint64_t x22; 38 | uint64_t x23; 39 | uint64_t x24; 40 | uint64_t x25; 41 | uint64_t x26; 42 | uint64_t x27; 43 | uint64_t x28; 44 | uint64_t x29; 45 | uint64_t x30; 46 | uint64_t elr; 47 | uint64_t spsr; 48 | }; 49 | 50 | #define MAX_INTERRUPTS 1024 51 | 52 | #endif 53 | 54 | -------------------------------------------------------------------------------- /arch/aarch64/include/arch-mmu.h: -------------------------------------------------------------------------------- 1 | #ifndef __ARCH_MMU_H 2 | #define __ARCH_MMU_H 3 | #include 4 | #include 5 | #include 6 | 7 | struct arch_vm_context { 8 | uintptr_t kernel_tt, user_tt; 9 | }; 10 | 11 | struct vm_context; 12 | void arch_mm_init(struct vm_context *ctx); 13 | uintptr_t arch_mm_physical_allocate(size_t size, bool clear); 14 | #endif 15 | 16 | -------------------------------------------------------------------------------- /arch/aarch64/include/arch-processor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct arch_processor { 4 | 5 | }; 6 | -------------------------------------------------------------------------------- /arch/aarch64/include/arch-psci.h: -------------------------------------------------------------------------------- 1 | #ifndef __ARCH_PSCI_H 2 | #define __ARCH_PSCI_H 3 | 4 | unsigned long psci_hvc_cmd2(unsigned long func, unsigned long arg1, unsigned long arg2); 5 | unsigned long psci_hvc_cmd3(unsigned long function, unsigned long arg1, unsigned long arg2, unsigned long arg3); 6 | 7 | #endif 8 | 9 | -------------------------------------------------------------------------------- /arch/aarch64/include/arch-thread.h: -------------------------------------------------------------------------------- 1 | #ifndef __THREAD_ARCH_H 2 | #define __THREAD_ARCH_H 3 | 4 | #include 5 | 6 | struct arch_thread { 7 | uint8_t fpu_data[512]; 8 | uint64_t fpcr; 9 | uint64_t fpsr; 10 | }; 11 | 12 | __attribute__((const)) static inline struct thread *arch_thread_get_current(void) 13 | { 14 | uint64_t id; 15 | asm volatile("mrs %0, TPIDR_EL1" : "=r"(id)); 16 | return (struct thread *)id; 17 | } 18 | 19 | #endif 20 | 21 | -------------------------------------------------------------------------------- /arch/aarch64/include/arch-timer.h: -------------------------------------------------------------------------------- 1 | #ifndef __ARCH_TIMER_H 2 | #define __ARCH_TIMER_H 3 | 4 | int arch_timer_init(void); 5 | 6 | #endif 7 | 8 | -------------------------------------------------------------------------------- /arch/aarch64/include/registers.h: -------------------------------------------------------------------------------- 1 | #ifndef __REGISTERS_H 2 | #define __REGISTERS_H 3 | 4 | #define PSR_A_BIT 0x100 5 | #define PSR_D_BIT 0x200 6 | #define PSR_F_BIT 0x40 7 | #define PSR_I_BIT 0x80 8 | #define PSR_MODE_EL1h 0x5 9 | 10 | 11 | 12 | #endif 13 | 14 | -------------------------------------------------------------------------------- /arch/aarch64/kernel/calls.S: -------------------------------------------------------------------------------- 1 | .globl aarch64_hvc2 2 | .globl aarch64_hvc3 3 | aarch64_hvc2: 4 | aarch64_hvc3: 5 | hvc #0 6 | ret 7 | 8 | .globl aarch64_thread_usermode_jump 9 | /* noreturn void aarch64_thread_usermode_jump(uintptr_t entry, uintptr_t stack_base, uintptr_t usertt, void *arg) */ 10 | aarch64_thread_usermode_jump: 11 | mov x8, #0 12 | msr spsr_el1, x8 13 | msr elr_el1, x0 14 | msr sp_el0, x1 15 | msr ttbr0_el1, x2 16 | mov x0, x3 17 | eret 18 | -------------------------------------------------------------------------------- /arch/aarch64/kernel/crti.c: -------------------------------------------------------------------------------- 1 | /* crti.c for ARM - BPABI - use -std=c99 */ 2 | typedef void (*func_ptr)(void); 3 | #include 4 | extern func_ptr _init_array_start, _init_array_end; 5 | void _init(void) 6 | { 7 | /* _init is called by main (which, if you know about how a C program usually 8 | * initializes) is pretty funny. But here, we want to be able to allocate 9 | * memory inside constructor functions, so we need to wait until we have a memory 10 | * manager. 11 | * 12 | * Anyway. This function calls constructor functions. This is handled with a little 13 | * bit of linker magic - we let the linker script tell us where this section is 14 | * so that we can iterate over the array and call the functions. 15 | */ 16 | for ( func_ptr* func = &_init_array_start; func != &_init_array_end; func++ ) { 17 | (*func)(); 18 | } 19 | } 20 | 21 | -------------------------------------------------------------------------------- /arch/aarch64/kernel/crtn.c: -------------------------------------------------------------------------------- 1 | /* crtn.c for ARM - BPABI - use -std=c99 */ 2 | typedef void (*func_ptr)(void); 3 | 4 | 5 | -------------------------------------------------------------------------------- /arch/aarch64/kernel/init.c: -------------------------------------------------------------------------------- 1 | extern void *table0; 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | _Alignas(0x10000) unsigned long long kernel_translation_table[64]; 11 | _Alignas(0x10000) unsigned long long table_l2[8192]; 12 | _Alignas(0x10000) unsigned long long table_l2_dev[8192]; 13 | 14 | 15 | void init_exceptions(void) 16 | { 17 | asm volatile("ldr x0, =table0; msr VBAR_EL1, x0"); 18 | 19 | } 20 | 21 | extern void _start_secondary(void); 22 | void arch_processor_poke_secondary(int id, uintptr_t init_stack) 23 | { 24 | psci_hvc_cmd3(0xC4000003, id, (uintptr_t)(_start_secondary - (KERNEL_VIRT_BASE - KERNEL_PHYS_BASE)), init_stack + KERNEL_STACK_SIZE); 25 | } 26 | 27 | extern void main(void); 28 | extern void uart_init(void); 29 | void aarch64_cpu_primary_entry(void) 30 | { 31 | init_exceptions(); 32 | uart_init(); 33 | gic_init(); 34 | gic_init_percpu(); 35 | main(); 36 | } 37 | 38 | void aarch64_cpu_secondary_entry(unsigned long mpidr) 39 | { 40 | printk("Seconary CPU %lx!\n", mpidr); 41 | init_exceptions(); 42 | gic_init_percpu(); 43 | processor_secondary_main(); 44 | } 45 | 46 | -------------------------------------------------------------------------------- /arch/aarch64/kernel/interrupt.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | void aarch64_mm_pagefault(uintptr_t addr, int re, bool wr, bool ex, bool us); 9 | 10 | static void __fault(unsigned long esr, bool el0, struct exception_frame *frame) 11 | { 12 | int ec = (esr >> 26) & 0x3F; 13 | bool exec = false; 14 | uint64_t addr; 15 | switch(ec) { 16 | case 0x20: case 0x21: 17 | exec = true; 18 | /* fall through */ 19 | case 0x24: case 0x25: 20 | asm volatile("mrs %0, FAR_EL1" : "=r"(addr)); 21 | bool write = !!(esr & (1 << 6)); 22 | int reason = esr & 0x1F; 23 | aarch64_mm_pagefault(addr, reason, write, exec, el0); 24 | break; 25 | case 0x15: 26 | if((esr & 0xFFFF) == SYS_FORK) { 27 | frame->x0 = frame->elr; 28 | frame->x1 = frame->spsr; 29 | } 30 | frame->x0 = syscall_entry(esr & 0xFFFF, frame->x0, frame->x1, frame->x2, frame->x3, frame->x4); 31 | break; 32 | default: 33 | panic(0, "unknown exception"); 34 | } 35 | } 36 | 37 | void arm_entry_l64_sync(unsigned long esr, struct exception_frame *frame) 38 | { 39 | printk("SYNC: %lx\n", esr); 40 | __fault(esr, true, frame); 41 | } 42 | 43 | void arm_entry_l64_serror(unsigned long esr) 44 | { 45 | printk("SERR: %lx\n", esr); 46 | } 47 | 48 | void arm_entry_l64_irq(unsigned long esr) 49 | { 50 | (void)esr; 51 | uint32_t iar = gic_read_interrupt_number(); 52 | int v = iar & 0x3FF; 53 | gic_signal_eoi(iar); 54 | interrupt_entry(v, 0); 55 | } 56 | 57 | void arm_entry_l64_fiq(unsigned long esr) 58 | { 59 | (void)esr; 60 | uint32_t iar = gic_read_interrupt_number(); 61 | int v = iar & 0x3FF; 62 | gic_signal_eoi(iar); 63 | interrupt_entry(v, 0); 64 | } 65 | 66 | void arm_entry_spx_sync(unsigned long esr, struct exception_frame *frame) 67 | { 68 | uint64_t elr; 69 | asm volatile("mrs %0, ELR_EL1" : "=r"(elr)); 70 | printk("S_SYNC: %lx, %lx\n", esr, elr); 71 | __fault(esr, false, frame); 72 | } 73 | 74 | void arm_entry_spx_serror(unsigned long esr) 75 | { 76 | printk("S_SERR: %lx\n", esr); 77 | } 78 | 79 | void arm_entry_spx_irq(unsigned long esr) 80 | { 81 | (void)esr; 82 | uint64_t elr; 83 | asm volatile("mrs %0, ELR_EL1" : "=r"(elr)); 84 | uint32_t iar = gic_read_interrupt_number(); 85 | int v = iar & 0x3FF; 86 | gic_signal_eoi(iar); 87 | interrupt_entry(v, INTERRUPT_INKERNEL); 88 | } 89 | 90 | void arm_entry_spx_fiq(unsigned long esr) 91 | { 92 | (void)esr; 93 | uint32_t iar = gic_read_interrupt_number(); 94 | int v = iar & 0x3FF; 95 | gic_signal_eoi(iar); 96 | interrupt_entry(v, INTERRUPT_INKERNEL); 97 | } 98 | 99 | void arm_entry_unknown(unsigned long esr) 100 | { 101 | printk("UNKNOWN: %lx\n", esr); 102 | } 103 | 104 | 105 | -------------------------------------------------------------------------------- /arch/aarch64/kernel/processor.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | int arch_processor_current_id(void) 5 | { 6 | uint64_t id; 7 | asm volatile("mrs %0, MPIDR_EL1" : "=r"(id)); 8 | return (id & 0xFFFFFF) | (id & 0xFF00000000) >> 8; 9 | } 10 | 11 | __attribute__((no_instrument_function)) 12 | uint64_t arch_processor_get_cycle_count(void) 13 | { 14 | uint64_t c; 15 | asm volatile("mrs %0, PMCCNTR_EL0" : "=r"(c)); 16 | return c; 17 | } 18 | 19 | __initializer static void aarch64_init_cycle_counter(void) 20 | { 21 | long x = 1 << 31; 22 | asm volatile("msr pmcntenset_el0, %0" :: "r"(x)); 23 | x = 1; 24 | asm volatile("msr pmcr_el0, %0" :: "r"(x)); 25 | } 26 | 27 | void arch_processor_reset(void) 28 | { 29 | /* TODO */ 30 | } 31 | 32 | void arch_panic_begin(void) 33 | { 34 | } 35 | 36 | -------------------------------------------------------------------------------- /arch/aarch64/kernel/switch.S: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | .globl aarch64_do_context_switch 4 | /* void aarch64_do_context_switch(void **save_stack_pointer, void *new_stack_pointer) */ 5 | aarch64_do_context_switch: 6 | sub sp, sp, #16*8 7 | stp x16, x17, [sp, #16 * 0] 8 | stp x18, x19, [sp, #16 * 1] 9 | stp x20, x21, [sp, #16 * 2] 10 | stp x22, x23, [sp, #16 * 3] 11 | stp x24, x25, [sp, #16 * 4] 12 | stp x26, x27, [sp, #16 * 5] 13 | stp x28, x29, [sp, #16 * 6] 14 | str x30, [sp, #16 * 7 + 8] 15 | 16 | mov x15, sp 17 | str x15, [x0] 18 | mov sp, x1 19 | 20 | ldp x16, x17, [sp, #16 * 0] 21 | ldp x18, x19, [sp, #16 * 1] 22 | ldp x20, x21, [sp, #16 * 2] 23 | ldp x22, x23, [sp, #16 * 3] 24 | ldp x24, x25, [sp, #16 * 4] 25 | ldp x26, x27, [sp, #16 * 5] 26 | ldp x28, x29, [sp, #16 * 6] 27 | ldr x30, [sp, #16 * 7 + 8] 28 | add sp, sp, #16*8 29 | ret 30 | 31 | aarch64_thread_initial_entry: 32 | ldp x1, x0, [sp, #0] 33 | add sp, sp, #16 34 | mov x2, #0 35 | msr DAIF, x2 36 | br x1 37 | 38 | .globl aarch64_do_thread_create 39 | /* void aarch64_do_thread_create(void *stack, void **stack_pointer, uintptr_t entry, void *arg); */ 40 | aarch64_do_thread_create: 41 | add x0, x0, KERNEL_STACK_SIZE 42 | 43 | sub x0, x0, #16 44 | stp x2, x3, [x0, #0] 45 | 46 | sub x0, x0, #16*8 47 | ldr x4, =aarch64_thread_initial_entry 48 | str x4, [x0, #16*7 + 8] 49 | 50 | str x0, [x1] 51 | 52 | ret 53 | -------------------------------------------------------------------------------- /arch/aarch64/kernel/unwind.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | bool arch_debug_unwind_frame(struct frame *frame) 6 | { 7 | if(frame->fp == 0) 8 | return false; 9 | void *fp = (void *)frame->fp; 10 | frame->fp = *(uintptr_t *)(fp); 11 | frame->pc = *(uintptr_t *)((uintptr_t)fp + 8) - 4; 12 | return true; 13 | } 14 | 15 | -------------------------------------------------------------------------------- /arch/aarch64/link.ldi: -------------------------------------------------------------------------------- 1 | OUTPUT_FORMAT("elf64-littleaarch64", "elf64-bigaarch64", "elf64-littleaarch64") 2 | OUTPUT_ARCH(aarch64) 3 | ENTRY (_start) 4 | 5 | SECTIONS 6 | { 7 | . = %KERNEL_VIRT_BASE% + %KERNEL_LOAD_OFFSET%; 8 | .text : AT(%KERNEL_PHYS_BASE% + %KERNEL_LOAD_OFFSET%) { 9 | kernel_text_start = .; 10 | KEEP(*(.text.boot)) 11 | *(.text*) 12 | kernel_text_end = .; 13 | } 14 | 15 | .init_array : 16 | { 17 | _init_array_start = .; 18 | KEEP(*(.init_array*)) 19 | _init_array_end = .; 20 | } 21 | 22 | .data : ALIGN(0x1000) { 23 | *(.data*) 24 | } 25 | 26 | .bss : ALIGN(0x1000) { 27 | *(COMMON) 28 | *(.bss*) 29 | } 30 | 31 | .rodata : ALIGN(0x1000) { 32 | *(.rodata) 33 | *(.rodata.symbols) 34 | } 35 | 36 | . = ALIGN(8); 37 | kernel_end = .; 38 | 39 | /DISCARD/ : { *(.comment .note) } 40 | } 41 | 42 | -------------------------------------------------------------------------------- /arch/x86_64/devices/hpet.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | struct __attribute__((packed)) hpet_desc { 6 | struct sdt_header header; 7 | uint8_t hw_rev_id; 8 | uint8_t comp_count:5; 9 | uint8_t counter_size:1; 10 | uint8_t _res:1; 11 | uint8_t leg_repl:1; 12 | uint16_t ven_id; 13 | uint32_t pci_addr_data; 14 | uint64_t address; 15 | uint8_t hpet_number; 16 | uint16_t min_tick; 17 | uint8_t page_prot; 18 | }; 19 | 20 | static struct hpet_desc *hpet; 21 | static uint32_t countperiod; 22 | 23 | __attribute__((no_instrument_function)) 24 | static inline uint64_t hpet_read64(int offset) 25 | { 26 | return *(volatile uint64_t *)(hpet->address + PHYS_MAP_START + offset); 27 | } 28 | 29 | __attribute__((no_instrument_function)) 30 | static inline void hpet_write64(int offset, uint64_t data) 31 | { 32 | *(volatile uint64_t *)(hpet->address + PHYS_MAP_START + offset) = data; 33 | } 34 | 35 | __orderedinitializer(__orderedafter(ACPI_INITIALIZER_ORDER)) 36 | static void hpet_init(void) 37 | { 38 | hpet = acpi_find_table("HPET"); 39 | if(!hpet) 40 | panic(0, "HPET not found"); 41 | uint64_t tmp = hpet_read64(0); 42 | countperiod = tmp >> 32; 43 | /* enable */ 44 | tmp = hpet_read64(0x10); 45 | tmp |= 1; 46 | hpet_write64(0x10, tmp); 47 | } 48 | 49 | __attribute__((no_instrument_function)) 50 | uint64_t arch_processor_get_cycle_count(void) 51 | { 52 | if(hpet) { 53 | return (hpet_read64(0xF0) * countperiod) / 1000000; 54 | } else { 55 | panic(0, "HPET not found"); 56 | } 57 | } 58 | 59 | uint64_t arch_processor_get_nanoseconds(void) 60 | { 61 | return arch_processor_get_cycle_count(); 62 | } 63 | 64 | -------------------------------------------------------------------------------- /arch/x86_64/devices/madt.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | struct __attribute__((packed)) madt_desc { 10 | struct sdt_header header; 11 | uint32_t lca; 12 | uint32_t flags; 13 | }; 14 | 15 | #define LAPIC_ENTRY 0 16 | #define IOAPIC_ENTRY 1 17 | 18 | struct __attribute__((packed)) lapic_entry { 19 | struct madt_record rec; 20 | uint8_t acpiprocid; 21 | uint8_t apicid; 22 | uint32_t flags; 23 | }; 24 | 25 | static struct madt_desc *madt; 26 | 27 | __orderedinitializer(MADT_INITIALIZER_ORDER) 28 | static void madt_init(void) 29 | { 30 | madt = acpi_find_table("APIC"); 31 | assert(madt != NULL); 32 | 33 | uintptr_t table = (uintptr_t)(madt + 1); 34 | int entries = madt->header.length - sizeof(*madt); 35 | for(int i=0;ireclen == 0) 38 | break; 39 | switch(rec->type) { 40 | struct lapic_entry *lapic; 41 | case LAPIC_ENTRY: 42 | lapic = (void *)rec; 43 | if(lapic->flags & 1) 44 | processor_create(lapic->acpiprocid, lapic->apicid == 0 ? PROCESSOR_UP : 0); 45 | break; 46 | case IOAPIC_ENTRY: 47 | ioapic_init((struct ioapic_entry *)rec); 48 | break; 49 | default: 50 | break; 51 | } 52 | table += rec->reclen; 53 | } 54 | } 55 | 56 | -------------------------------------------------------------------------------- /arch/x86_64/include.mk: -------------------------------------------------------------------------------- 1 | TOOLCHAIN_PREFIX=x86_64-elf 2 | 3 | CFLAGS+=-mno-red-zone -mno-sse -mcmodel=kernel -mno-avx 4 | LDFLAGS+=-mcmodel=kernel -Wl,-z,max-page-size=4096 5 | # these are defined by machine's include.mk 6 | CFLAGS+=-DKERNEL_LOAD_OFFSET=$(KERNEL_LOAD_OFFSET) -DKERNEL_PHYS_BASE=$(KERNEL_PHYS_BASE) -DKERNEL_VIRT_BASE=$(KERNEL_VIRT_BASE) $(addprefix -D,$(ARCH_SUPPORTED)) 7 | 8 | ARCH_SUPPORTED=FEATURE_SUPPORTED_UNWIND FEATURE_SUPPORTED_CYCLE_COUNT FEATURE_SUPPORTED_GETTIME 9 | 10 | CRTIOBJ=arch/x86_64/kernel/crti.o 11 | CRTNOBJ=arch/x86_64/kernel/crtn.o 12 | 13 | ASM_SOURCES+=arch/x86_64/kernel/start.S \ 14 | arch/x86_64/kernel/gate.S \ 15 | arch/x86_64/kernel/bootstrap.S \ 16 | arch/x86_64/kernel/switch.S 17 | 18 | 19 | C_SOURCES+=arch/x86_64/kernel/init.c \ 20 | arch/x86_64/kernel/mmu.c \ 21 | arch/x86_64/kernel/processor.c \ 22 | arch/x86_64/kernel/timer.c \ 23 | arch/x86_64/kernel/time.c \ 24 | arch/x86_64/kernel/idt.c \ 25 | arch/x86_64/kernel/tss.c \ 26 | arch/x86_64/kernel/gdt.c \ 27 | arch/x86_64/kernel/unwind.c \ 28 | arch/x86_64/devices/apic.c \ 29 | arch/x86_64/devices/madt.c \ 30 | arch/x86_64/devices/hpet.c \ 31 | arch/x86_64/kernel/interrupt.c \ 32 | arch/x86_64/kernel/thread.c 33 | 34 | $(BUILDDIR)/link.ld: $(ARCHDIR)/link.ldi $(MAKEFILES) 35 | @echo -e "[GEN]\t$(BUILDDIR)/link.ld" 36 | @sed "s/%KERNEL_VIRT_BASE%/$(KERNEL_VIRT_BASE)/g" < $(ARCHDIR)/link.ldi | sed "s/%KERNEL_PHYS_BASE%/$(KERNEL_PHYS_BASE)/g" | sed "s/%KERNEL_LOAD_OFFSET%/$(KERNEL_LOAD_OFFSET)/g" > $(BUILDDIR)/link.ld 37 | 38 | -------------------------------------------------------------------------------- /arch/x86_64/include/arch-interrupt.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | struct __attribute__((packed)) arch_exception_frame 5 | { 6 | uint64_t r15, r14, r13, r12, rbp, rbx, r11, r10, r9, r8, rax, rcx, rdx, rsi, rdi; 7 | uint64_t int_no, err_code; 8 | uint64_t rip, cs, rflags, userrsp, ss; 9 | }; 10 | 11 | __attribute__((no_instrument_function)) 12 | static inline uint32_t arch_interrupt_set(int st) 13 | { 14 | long old; 15 | asm ("pushfq; pop %0;" : "=r"(old) :: "memory"); 16 | if(st) 17 | asm ("mfence; sti"); 18 | else 19 | asm ("cli; mfence"); 20 | return old & (1 << 9); 21 | } 22 | 23 | #define MAX_INTERRUPTS 256 24 | -------------------------------------------------------------------------------- /arch/x86_64/include/arch-mmu.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | struct arch_vm_context { 6 | uintptr_t pml4_phys; 7 | }; 8 | 9 | struct vm_context; 10 | void arch_mm_init(struct vm_context *ctx); 11 | uintptr_t arch_mm_physical_allocate(size_t size, bool clear); 12 | 13 | #define MMU_NUM_PAGESIZE_LEVELS 2 14 | 15 | #define MMU_PTE_GLOBAL (1 << 8) 16 | #define MMU_PTE_LARGE (1 << 7) 17 | #define MMU_PTE_DIRTY (1 << 6) 18 | #define MMU_PTE_ACCESSED (1 << 5) 19 | #define MMU_PTE_NOCACHE (1 << 4) 20 | #define MMU_PTE_WRITETHR (1 << 3) 21 | #define MMU_PTE_USER (1 << 2) 22 | #define MMU_PTE_WRITE (1 << 1) 23 | #define MMU_PTE_PRESENT (1 << 0) 24 | #define MMU_PTE_NOEXEC (1ull << 63) 25 | 26 | #define MMU_PTE_PHYS_MASK 0x7FFFFFFFFFFFF000 27 | __attribute__((const,pure)) static inline size_t arch_mm_page_size(int level) 28 | { 29 | if(level == 0) 30 | return 0x1000; //4K 31 | else if(level == 1) 32 | return 2 * 1024 * 1024; //2M 33 | else 34 | return 1024 * 1024 * 1024; //1G 35 | } 36 | 37 | 38 | -------------------------------------------------------------------------------- /arch/x86_64/include/arch-processor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define PROCESSOR_IPI_DEST_OTHERS -1 4 | #define PROCESSOR_IPI_SHOOTDOWN 100 5 | #define PROCESSOR_IPI_HALT 90 6 | struct x86_64_gdt_entry 7 | { 8 | uint16_t limit_low; 9 | uint16_t base_low; 10 | uint8_t base_middle; 11 | uint8_t access; 12 | uint8_t granularity; 13 | uint8_t base_high; 14 | } __attribute__((packed)); 15 | 16 | struct x86_64_tss 17 | { 18 | uint32_t prev_tss; 19 | uint64_t esp0; // The stack pointer to load when we change to kernel mode. 20 | uint32_t ss0; // The stack segment to load when we change to kernel mode. 21 | uint64_t esp1; // Unused... 22 | uint32_t ss1; 23 | uint64_t esp2; 24 | uint32_t ss2; 25 | uint64_t cr3; 26 | uint64_t rip; 27 | uint64_t rflags; 28 | uint64_t rax; 29 | uint64_t rcx; 30 | uint64_t rdx; 31 | uint64_t rbx; 32 | uint64_t rsp; 33 | uint64_t rbp; 34 | uint64_t rsi; 35 | uint64_t rdi; 36 | uint32_t es; // The value to load into ES when we change to kernel mode. 37 | uint32_t cs; // The value to load into CS when we change to kernel mode. 38 | uint32_t ss; // The value to load into SS when we change to kernel mode. 39 | uint32_t ds; // The value to load into DS when we change to kernel mode. 40 | uint32_t fs; // The value to load into FS when we change to kernel mode. 41 | uint32_t gs; // The value to load into GS when we change to kernel mode. 42 | uint32_t ldt; // Unused... 43 | uint16_t trap; 44 | uint16_t iomap_base; 45 | } __attribute__((packed)); 46 | 47 | struct arch_processor { 48 | _Alignas(16) struct x86_64_tss tss; 49 | _Alignas(16) struct x86_64_gdt_entry gdt[8]; 50 | _Alignas(16) struct __attribute__((packed)) { 51 | uint16_t limit; 52 | uint64_t base; 53 | } gdtptr; 54 | }; 55 | 56 | -------------------------------------------------------------------------------- /arch/x86_64/include/arch-thread.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | struct arch_thread { 5 | _Alignas(16) uint8_t fpu_data[512]; 6 | uintptr_t fs; 7 | bool usedfpu; 8 | }; 9 | 10 | __attribute__((const)) static inline struct thread *arch_thread_get_current(void) 11 | { 12 | uint64_t stack; 13 | asm("mov %%rsp, %0" : "=r"(stack)); 14 | return *(struct thread **)(stack & ~(KERNEL_STACK_SIZE - 1)); 15 | } 16 | 17 | -------------------------------------------------------------------------------- /arch/x86_64/include/arch-timer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | int arch_timer_init(void); 3 | -------------------------------------------------------------------------------- /arch/x86_64/include/x86_64-ioport.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | static inline void x86_64_outb(uint16_t port, uint8_t val) 4 | { 5 | asm volatile ("outb %1, %0" : : "dN" (port), "a" ((unsigned char)val)); 6 | } 7 | 8 | static inline uint8_t x86_64_inb(uint16_t port) 9 | { 10 | uint8_t ret; 11 | asm volatile("inb %1, %0" : "=a" (ret) : "dN" (port)); 12 | return ret; 13 | } 14 | 15 | static inline void x86_64_outl(uint16_t port, uint32_t val) 16 | { 17 | asm volatile ("outl %1, %0" : : "dN" (port), "a" (val)); 18 | } 19 | 20 | static inline uint32_t x86_64_inl(uint16_t port) 21 | { 22 | uint32_t ret; 23 | asm volatile("inl %1, %0" : "=a" (ret) : "dN" (port)); 24 | return ret; 25 | } 26 | 27 | 28 | static inline unsigned char x86_64_cmos_read(unsigned char addr) 29 | { 30 | unsigned char ret; 31 | x86_64_outb(0x70,addr); 32 | asm volatile ("jmp 1f; 1: jmp 1f;1:"); 33 | ret = x86_64_inb(0x71); 34 | asm volatile ("jmp 1f; 1: jmp 1f;1:"); 35 | return ret; 36 | } 37 | 38 | static inline void x86_64_cmos_write(unsigned char addr, unsigned int value) 39 | { 40 | x86_64_outb(0x70, addr); 41 | asm volatile ("jmp 1f; 1: jmp 1f;1:"); 42 | x86_64_outb(0x71, value); 43 | asm volatile ("jmp 1f; 1: jmp 1f;1:"); 44 | } 45 | 46 | -------------------------------------------------------------------------------- /arch/x86_64/include/x86_64-madt.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #define MADT_INITIALIZER_ORDER __orderedafter(ACPI_INITIALIZER_ORDER) 7 | 8 | struct __attribute__((packed)) madt_record { 9 | uint8_t type; 10 | uint8_t reclen; 11 | }; 12 | 13 | struct __attribute__((packed)) ioapic_entry { 14 | struct madt_record rec; 15 | uint8_t apicid; 16 | uint8_t __res0; 17 | uint32_t ioapicaddr; 18 | uint32_t gsib; 19 | }; 20 | 21 | void ioapic_init(struct ioapic_entry *entry); 22 | -------------------------------------------------------------------------------- /arch/x86_64/include/x86_64-msr.h: -------------------------------------------------------------------------------- 1 | #define X86_MSR_APIC_BASE 0x1B 2 | #define X86_MSR_APIC_BASE_BSP 0x100 3 | #define X86_MSR_APIC_BASE_X2MODE 0x400 4 | #define X86_MSR_APIC_BASE_ENABLE 0x800 5 | 6 | #define X86_MSR_FS_BASE 0xc0000100 7 | 8 | 9 | static inline void x86_64_rdmsr(uint32_t msr, uint32_t *lo, uint32_t *hi) 10 | { 11 | asm volatile("rdmsr" : "=a"(*lo), "=d"(*hi) : "c"(msr)); 12 | } 13 | 14 | static inline void x86_64_wrmsr(uint32_t msr, uint32_t lo, uint32_t hi) 15 | { 16 | asm volatile("wrmsr" : : "a"(lo), "d"(hi), "c"(msr)); 17 | } 18 | 19 | -------------------------------------------------------------------------------- /arch/x86_64/kernel/crti.S: -------------------------------------------------------------------------------- 1 | /* x86_64 crti.s */ 2 | .section .init 3 | .global _init 4 | .type _init, @function 5 | _init: 6 | push %rbp 7 | movq %rsp, %rbp 8 | /* gcc will nicely put the contents of crtbegin.o's .init section here. */ 9 | 10 | .section .fini 11 | .global _fini 12 | .type _fini, @function 13 | _fini: 14 | push %rbp 15 | movq %rsp, %rbp 16 | /* gcc will nicely put the contents of crtbegin.o's .fini section here. */ 17 | 18 | -------------------------------------------------------------------------------- /arch/x86_64/kernel/crtn.S: -------------------------------------------------------------------------------- 1 | /* x86_64 crtn.s */ 2 | .section .init 3 | /* gcc will nicely put the contents of crtend.o's .init section here. */ 4 | popq %rbp 5 | ret 6 | 7 | .section .fini 8 | /* gcc will nicely put the contents of crtend.o's .fini section here. */ 9 | popq %rbp 10 | ret 11 | -------------------------------------------------------------------------------- /arch/x86_64/kernel/gdt.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | void x86_64_write_gdt_entry(struct x86_64_gdt_entry *entry, uint32_t base, uint32_t limit, 4 | uint8_t access, uint8_t gran) 5 | { 6 | entry->base_low = base & 0xFFFF; 7 | entry->base_middle = (base >> 16) & 0xFF; 8 | entry->base_high = (base >> 24) & 0xFF; 9 | entry->limit_low = limit & 0xFFFF; 10 | entry->granularity = ((limit >> 16) & 0x0F) | ((gran & 0x0F) << 4); 11 | entry->access = access; 12 | } 13 | 14 | void x86_64_gdt_init(struct processor *proc) 15 | { 16 | memset(&proc->arch.gdt, 0, sizeof(proc->arch.gdt)); 17 | x86_64_write_gdt_entry(&proc->arch.gdt[0], 0, 0, 0, 0); 18 | x86_64_write_gdt_entry(&proc->arch.gdt[1], 0, 0xFFFFF, 0x9A, 0xA); 19 | x86_64_write_gdt_entry(&proc->arch.gdt[2], 0, 0xFFFFF, 0x92, 0xA); 20 | x86_64_write_gdt_entry(&proc->arch.gdt[3], 0, 0xFFFFF, 0xFA, 0xA); 21 | x86_64_write_gdt_entry(&proc->arch.gdt[4], 0, 0xFFFFF, 0xF2, 0xA); 22 | proc->arch.gdtptr.limit = sizeof(struct x86_64_gdt_entry) * 8 - 1; 23 | proc->arch.gdtptr.base = (uintptr_t)&proc->arch.gdt; 24 | asm volatile("lgdt (%0)" :: "r"(&proc->arch.gdtptr)); 25 | } 26 | 27 | -------------------------------------------------------------------------------- /arch/x86_64/kernel/init.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | extern void main(void); 7 | extern void uart_init(void); 8 | extern void idt_init(void); 9 | void pc_save_multiboot(void *header); 10 | 11 | static void init_proc(void) 12 | { 13 | uint64_t cr0, cr4; 14 | asm volatile("finit"); 15 | asm volatile("mov %%cr0, %0" : "=r"(cr0)); 16 | cr0 |= (1 << 2); 17 | cr0 |= (1 << 5); 18 | cr0 |= (1 << 1); 19 | cr0 |= (1 << 16); 20 | cr0 &= ~(1 << 30); // make sure caching is on 21 | asm volatile("mov %0, %%cr0" :: "r"(cr0)); 22 | 23 | 24 | asm volatile("mov %%cr4, %0" : "=r"(cr4)); 25 | //cr4 |= (1 << 7); //enable page global 26 | cr4 |= (1 << 10); //enable fast fxsave etc, sse 27 | /* TODO: bit 16 of CR4 enables wrfsbase etc instructions. 28 | * But we need to check CPUID before using them. */ 29 | //cr4 |= (1 << 16); //enable wrfsbase etc 30 | asm volatile("mov %0, %%cr4" :: "r"(cr4)); 31 | } 32 | 33 | void x86_64_cpu_primary_entry(void *mth, uint32_t magic) 34 | { 35 | uart_init(); 36 | init_proc(); 37 | if(magic != 0x2BADB002) { 38 | panic(0, "multiboot magic number not present"); 39 | } 40 | pc_save_multiboot(mth); 41 | idt_init(); 42 | main(); 43 | } 44 | 45 | void x86_64_lapic_init_percpu(void); 46 | void idt_init_secondary(void); 47 | void x86_64_cpu_secondary_entry(uint32_t id) 48 | { 49 | arch_mm_context_switch(&kernel_context); 50 | idt_init_secondary(); 51 | init_proc(); 52 | x86_64_lapic_init_percpu(); 53 | assert((int)id == arch_processor_current_id()); 54 | processor_secondary_main(); 55 | } 56 | 57 | -------------------------------------------------------------------------------- /arch/x86_64/kernel/processor.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | -------------------------------------------------------------------------------- /arch/x86_64/kernel/switch.S: -------------------------------------------------------------------------------- 1 | #include 2 | .code64 3 | .global x86_64_do_context_switch 4 | x86_64_do_context_switch: 5 | pushfq 6 | pushq %rbp 7 | pushq %rbx 8 | pushq %r12 9 | pushq %r13 10 | pushq %r14 11 | pushq %r15 12 | 13 | movq %rsp, (%rdi) 14 | movq (%rsi), %rsp 15 | 16 | popq %r15 17 | popq %r14 18 | popq %r13 19 | popq %r12 20 | popq %rbx 21 | popq %rbp 22 | popfq 23 | ret 24 | 25 | _x86_64_thread_initial_entry: 26 | movq %r15, %rdi 27 | sti 28 | jmp *%r14 29 | 30 | # void x86_64_do_thread_create( 31 | # void *stack_base, RDI 32 | # void **stackpointer, RSI 33 | # struct thread *thread, RDX 34 | # void *fn, RCX 35 | # void *arg) R8 36 | .global x86_64_do_thread_create 37 | x86_64_do_thread_create: 38 | # write the thread pointer into the bottom of the stack 39 | movq %rdx, (%rdi) 40 | 41 | # move to the top of the stack to write the initial frame 42 | addq $KERNEL_STACK_SIZE, %rdi 43 | movq $_x86_64_thread_initial_entry, -0x08(%rdi) # return address 44 | 45 | # initial frame 46 | pushfq 47 | popq %rax 48 | movq %rax, -0x10(%rdi) 49 | 50 | movq $0, -0x18(%rdi) 51 | movq $0, -0x20(%rdi) 52 | movq $0, -0x28(%rdi) 53 | movq $0, -0x30(%rdi) 54 | movq %rcx, -0x38(%rdi) 55 | movq %r8, -0x40(%rdi) 56 | 57 | # write the initial stack pointer 58 | subq $0x40, %rdi 59 | movq %rdi, (%rsi) 60 | 61 | ret 62 | 63 | -------------------------------------------------------------------------------- /arch/x86_64/kernel/timer.c: -------------------------------------------------------------------------------- 1 | #include 2 | int arch_timer_init(void) 3 | { 4 | return 32; 5 | } 6 | 7 | void arch_timer_tick(void) 8 | { 9 | 10 | } 11 | 12 | -------------------------------------------------------------------------------- /arch/x86_64/kernel/tss.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | /* we need a GDT per CPU... :( */ 5 | 6 | void x86_64_write_gdt_entry(struct x86_64_gdt_entry *entry, uint32_t base, uint32_t limit, 7 | uint8_t access, uint8_t gran); 8 | void x86_64_tss_init(struct processor *proc) 9 | { 10 | struct x86_64_tss *tss = &proc->arch.tss; 11 | memset(tss, 0, sizeof(*tss)); 12 | tss->ss0 = 0x10; 13 | tss->esp0 = 0; 14 | tss->cs = 0x0b; 15 | tss->ss = tss->ds = tss->es = 0x13; 16 | x86_64_write_gdt_entry(&proc->arch.gdt[5], (uint32_t)(uintptr_t)tss, sizeof(*tss), 0xE9, 0); 17 | x86_64_write_gdt_entry(&proc->arch.gdt[6], ((uintptr_t)tss >> 48) & 0xFFFF, ((uintptr_t)tss >> 32) & 0xFFFF, 0, 0); 18 | asm volatile("movw $0x2B, %%ax; ltr %%ax" ::: "rax", "memory"); 19 | } 20 | 21 | void x86_64_tss_ctxswitch(struct processor *proc, uintptr_t stacktop) 22 | { 23 | proc->arch.tss.esp0 = stacktop; 24 | } 25 | 26 | -------------------------------------------------------------------------------- /arch/x86_64/kernel/unwind.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #ifdef __clang__ 7 | __attribute__((no_sanitize("alignment"))) 8 | #else 9 | __attribute__((no_sanitize_undefined)) 10 | #endif 11 | bool arch_debug_unwind_frame(struct frame *frame) 12 | { 13 | if(frame->fp == 0 || !(frame->fp >= PHYS_MAP_START)) 14 | return false; 15 | void *fp = (void *)frame->fp; 16 | frame->fp = *(uintptr_t *)(fp); 17 | frame->pc = *(uintptr_t *)((uintptr_t)fp + 8) - 5; 18 | return true; 19 | } 20 | 21 | -------------------------------------------------------------------------------- /arch/x86_64/link.ldi: -------------------------------------------------------------------------------- 1 | OUTPUT_FORMAT("elf64-x86-64") 2 | ENTRY (_start) 3 | 4 | SECTIONS 5 | { 6 | . = %KERNEL_VIRT_BASE% + %KERNEL_LOAD_OFFSET%; 7 | 8 | /* let the alignment of virtual memory match the offset into the file */ 9 | . += SIZEOF_HEADERS; 10 | 11 | /* there is an extra alignment here for the kernel symbols to work. 12 | * we can't have the start of .text change between stage1 and final linkings. */ 13 | .text : AT(%KERNEL_PHYS_BASE% + %KERNEL_LOAD_OFFSET%) ALIGN(0x100) { 14 | kernel_text_start = .; 15 | *(.boot) 16 | *(.text*) 17 | kernel_text_end = .; 18 | } 19 | .ctors : ALIGN(4) { 20 | KEEP (*crtbegin.o(.ctors)) 21 | KEEP (*crtbegin?.o(.ctors)) 22 | /* We don't want to include the .ctor section from 23 | the crtend.o file until after the sorted ctors. 24 | The .ctor section from the crtend file contains the 25 | end of ctors marker and it must be last */ 26 | KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) 27 | KEEP (*(SORT(.ctors.*))) 28 | KEEP (*(.ctors)) 29 | } 30 | .dtors : ALIGN(4) { 31 | KEEP (*crtbegin.o(.dtors)) 32 | KEEP (*crtbegin?.o(.dtors)) 33 | KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) 34 | KEEP (*(SORT(.dtors.*))) 35 | KEEP (*(.dtors)) 36 | } 37 | .data : ALIGN(0x1000) { 38 | kernel_data_start = .; 39 | *(.data*) 40 | } 41 | .rodata : ALIGN(0x1000) { 42 | *(.rodata*) 43 | } 44 | kernel_data_end = .; 45 | .bss : ALIGN(0x1000) { 46 | *(COMMON) 47 | *(.bss*) 48 | } 49 | kernel_bss_end = .; 50 | 51 | .extra : 52 | { 53 | *(.gnu.linkonce.t*) 54 | *(.gnu.linkonce.r*) 55 | . = ALIGN(4096); 56 | } 57 | 58 | . = ALIGN(8); 59 | kernel_end = .; 60 | 61 | /DISCARD/ : { *(.comment .note) } 62 | } 63 | 64 | -------------------------------------------------------------------------------- /config.cfg: -------------------------------------------------------------------------------- 1 | # controls build optimization. Valid values are g, 0, 1, 2, 3, fast. 2 | CONFIG_BUILD_OPTIMIZATION=g 3 | 4 | # enable debugging statements (such as asserts) 5 | CONFIG_DEBUG=y 6 | 7 | # build with -Werror (you probably want this on) 8 | CONFIG_BUILD_WERROR=y 9 | 10 | # target architecture. Valid values are x86_64 and aarch64. 11 | CONFIG_ARCH=x86_64 12 | 13 | # target machine. Valid values depends on CONFIG_ARCH. 14 | # valid value for x86_64 is 'pc'. Valid for aarch64 is 'virt'. 15 | CONFIG_MACHINE=pc 16 | 17 | # Enable link-time optimization (this is not actively supported) 18 | CONFIG_BUILD_LTO=n 19 | 20 | # Enable UBSAN (Undefined Behavior Santitizer). This slows down the 21 | # code, but adds safety checks. 22 | CONFIG_UBSAN=y 23 | 24 | # Enable tracing. Allows use of the trace.h TRACE() infrastructure. 25 | CONFIG_TRACE=y 26 | 27 | # Insert perf instrumentation for functions. This will let the kernel 28 | # keep track of how long any of its functions are taking to run. 29 | CONFIG_PERF_FUNCTIONS=n 30 | 31 | # Use the clang compiler (better warnings). 32 | CONFIG_BUILD_CLANG=n 33 | 34 | # Run the test infrastructure on bootup. 35 | CONFIG_RUN_TESTS=n 36 | 37 | # point this to the sysroot 38 | CONFIG_BUILD_SYSROOT=sysroot 39 | 40 | # DO NOT CHANGE THIS. 41 | CONFIG_BUILD_SYSTEM_COMPILER=n 42 | 43 | -------------------------------------------------------------------------------- /doc/TODO: -------------------------------------------------------------------------------- 1 | aarch64 2 | ------- 3 | * FPU state save/restore 4 | 5 | kernel 6 | ------ 7 | 8 | -------------------------------------------------------------------------------- /doc/global_defines.txt: -------------------------------------------------------------------------------- 1 | Preprocessor defines 2 | -------------------- 3 | KERNEL_VIRT_BASE - Virtual address of kernel base 4 | KERNEL_PHYS_BASE - Physical address of kernel base 5 | KERNEL_LOAD_OFFSET - Offset from kernel base where kernel image is placed 6 | KERNEL_STACK_SIZE - Size of a thread's kernel stack 7 | 8 | Global constant variables 9 | ------------------------- 10 | initial_boot_stack - Stack used during boot of BSP 11 | kernel_context - The struct vm_context used by the kernel (and kernel threads) 12 | kernel_end - End of kernel image (used by MM) 13 | 14 | Global defines, constant per thread 15 | ----------------------------------- 16 | current_thread - The current executing thread, by view of the code. 17 | 18 | Global defines, non-constant per thread in special circumstances 19 | ---------------------------------------------------------------- 20 | current_context - The context for current_thread (just current_thread->ctx) 21 | 22 | -------------------------------------------------------------------------------- /doc/mapping.txt: -------------------------------------------------------------------------------- 1 | The mapping system handles mmap, munmap, mremap, etc. It is designed to be 2 | agnostic about what it is actually mapping, and instead focus on individual 3 | frames of data. 4 | 5 | A frame is a reference counted region of contiguous physical memory. The 6 | mapping system handles frames, and manages them as follows: 7 | 8 | When a region specified by mmap is faulted on, it calls the callback 'map' 9 | for the file associated with the region, passing it information about the 10 | region. This function passes back a physical address to map to. When a map 11 | is copied, the mapping system increments the refcount for any frame that is 12 | actually mapped. Note that any physical address is also a frame. 13 | 14 | When a mapping is destroyed, the mapping system iterates over it and unmaps 15 | all established mappings for that region (established meaning that they were 16 | actually loaded due to a fault or whatnot). For each one it finds, it calls 17 | the unmap function. 18 | 19 | Note that this means that the unmap function can be called more often then 20 | the map function for a given object! The implementations of map and unmap 21 | must track these themselves (likely using the frame's reference count). 22 | 23 | Example (map, unmap) implementation: Zero-file 24 | ---------------------------------------------- 25 | MAP_ANON is an important thing to support, but to reduce complexity, the 26 | mapping system can only deal with things that have an associated file 27 | object. Thus, if some code calls mmap with MAP_ANON, this is transformed 28 | into a call which uses a special zero-file, and the MAP_ANON flag is cleared. 29 | The map function for this simply allocates a frame and returns it, while the 30 | unmap function releases that frame. 31 | 32 | inode-backed map, unmap implementation 33 | -------------------------------------- 34 | The map function here looks for the correct inode page structure and then 35 | returns the associated frame, after incrementing its reference count. The 36 | frames allocated for inodepage structures have a special property where 37 | they are not automatically released when the refs reach zero, and they are 38 | started at a reference count of zero (essentially telling the frame allocation 39 | system that the inodepage code will deal with them). The map function 40 | intentionally keeps a reference to the inodepage structure around, essentially 41 | giving ownership of this reference to the frame that is associated with it. 42 | 43 | The unmap function then decrements the frame count and if it is zero, it 44 | releases the inodepage structure. 45 | -------------------------------------------------------------------------------- /doc/ports.txt: -------------------------------------------------------------------------------- 1 | flex 2 | ---- 3 | * Flex defines a wrapper for malloc, rpl_malloc. This function ensures 4 | that the size is non-zero. However, it is never prototyped, so C 5 | defaults to making it return an int. If malloc returns memory that is 6 | above the 4GB mark, the returned value is simply truncated. 7 | 8 | -------------------------------------------------------------------------------- /drivers/ahci/include.mk: -------------------------------------------------------------------------------- 1 | C_SOURCES+=drivers/ahci/ahci.c drivers/ahci/main.c drivers/ahci/command.c 2 | -------------------------------------------------------------------------------- /drivers/ext2/include.mk: -------------------------------------------------------------------------------- 1 | C_SOURCES+=drivers/ext2/ext2.c 2 | -------------------------------------------------------------------------------- /drivers/include.mk: -------------------------------------------------------------------------------- 1 | C_SOURCES+=drivers/pci.c drivers/e1000.c 2 | 3 | include drivers/ext2/include.mk 4 | include drivers/ahci/include.mk 5 | 6 | -------------------------------------------------------------------------------- /drivers/rtl8139.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | static int _rtl_init_device(struct pci_device *dev) 4 | { 5 | 6 | } 7 | 8 | static struct pci_driver pcidriver = { 9 | .init_device = _rtl_init_device, 10 | .name = "rtl8139", 11 | .num = 1, 12 | 13 | .supported = { 14 | { 0x10ec, 0x8139}, 15 | }, 16 | }; 17 | 18 | 19 | -------------------------------------------------------------------------------- /include/_default.h: -------------------------------------------------------------------------------- 1 | #ifndef __default_universal__ 2 | #define __default_universal__ 3 | 4 | #ifndef __ASSEMBLER__ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | typedef long ssize_t; 12 | typedef uint64_t dev_t; 13 | typedef long sysret_t; 14 | #endif 15 | 16 | #endif 17 | 18 | -------------------------------------------------------------------------------- /include/arena.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | struct arena { 9 | void *start; 10 | struct spinlock lock; 11 | }; 12 | 13 | struct arena_node { 14 | size_t used; 15 | size_t len; 16 | void *next; 17 | }; 18 | 19 | static inline void arena_create(struct arena *arena) 20 | { 21 | spinlock_create(&arena->lock); 22 | arena->start = (void *)mm_virtual_allocate(arch_mm_page_size(0), true); 23 | struct arena_node *node = arena->start; 24 | node->len = arch_mm_page_size(0); 25 | node->used = sizeof(struct arena_node); 26 | } 27 | 28 | static inline void *arena_allocate(struct arena *arena, size_t length) 29 | { 30 | spinlock_acquire(&arena->lock); 31 | 32 | length = (length & ~15) + 16; 33 | 34 | struct arena_node *node = arena->start, *prev = NULL; 35 | while(node && (node->used + length >= node->len)) { 36 | prev = node; 37 | node = node->next; 38 | } 39 | 40 | if(!node) { 41 | assert(prev != NULL); 42 | size_t len = __round_up_pow2(length * 2); 43 | if(len < arch_mm_page_size(0)) 44 | len = arch_mm_page_size(0); 45 | node = prev->next = (void *)mm_virtual_allocate(len, true); 46 | node->len = len; 47 | node->used = sizeof(struct arena_node); 48 | } 49 | 50 | void *ret = (void *)((uintptr_t)node + node->used); 51 | node->used += length; 52 | 53 | spinlock_release(&arena->lock); 54 | return ret; 55 | } 56 | 57 | static inline void arena_destroy(struct arena *arena) 58 | { 59 | struct arena_node *node = arena->start, *next; 60 | while(node) { 61 | next = node->next; 62 | mm_virtual_deallocate((uintptr_t)node); 63 | node = next; 64 | } 65 | } 66 | 67 | -------------------------------------------------------------------------------- /include/assert.h: -------------------------------------------------------------------------------- 1 | #ifndef __ASSERT_H 2 | #define __ASSERT_H 3 | 4 | #include 5 | 6 | #if CONFIG_DEBUG 7 | 8 | #define assert(cond) do { if(!__builtin_expect(cond, 0)) panic(0, "assertion failure (%s:%d) %s", __FILE__, __LINE__, #cond); } while(0) 9 | #define assertmsg(cond, msg, ...) do { if(!__builtin_expect(cond, 0)) panic(0, "assertion failure (%s:%d) %s -- " msg, __FILE__, __LINE__, #cond, ##__VA_ARGS__); } while(0) 10 | 11 | #else 12 | 13 | #define assert(x) 14 | #define assertmsg(...) 15 | 16 | #endif 17 | 18 | #endif 19 | 20 | -------------------------------------------------------------------------------- /include/block.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | struct blockdev { 8 | struct kobj_header _header; 9 | struct blockdriver *drv; 10 | int devid; 11 | void *devdata; 12 | struct workqueue requests; 13 | struct hash cache; 14 | struct spinlock cache_lock; 15 | struct worker kio; 16 | struct attachment attach; 17 | struct blocklist wait; 18 | }; 19 | 20 | struct request { 21 | struct kobj_header _header; 22 | struct blockdev *bd; 23 | struct blocklist wait; 24 | unsigned long start; 25 | uintptr_t phys; 26 | _Atomic int count, ret_count; 27 | bool write; 28 | }; 29 | 30 | struct blockdriver { 31 | const char *name; 32 | int blksz; 33 | int devnr; 34 | _Atomic int _next_id; 35 | int (*read_blocks)(struct blockdev *bd, unsigned long start, int count, uintptr_t phys); 36 | int (*write_blocks)(struct blockdev *bd, unsigned long start, int count, uintptr_t phys); 37 | int (*handle_req)(struct blockdev *bd, struct request *req); 38 | struct device device; 39 | struct kobj kobj_block; 40 | }; 41 | 42 | struct block { 43 | struct kobj_header _header; 44 | unsigned long block; 45 | struct hashelem elem; 46 | bool dirty; 47 | char data[]; 48 | }; 49 | 50 | static inline int blockdev_getid(struct blockdriver *drv) 51 | { 52 | return drv->_next_id++; 53 | } 54 | 55 | extern struct kobj kobj_blockdev; 56 | 57 | void blockdriver_register(struct blockdriver *driver); 58 | void blockdev_register(struct blockdev *bd, struct blockdriver *drv); 59 | struct blockdev *blockdev_get(int major, int minor); 60 | int block_read(struct blockdev *bd, unsigned long start, int count, uintptr_t phys, bool cache); 61 | int block_write(struct blockdev *bd, unsigned long start, int count, uintptr_t phys); 62 | -------------------------------------------------------------------------------- /include/blocklist.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | struct blocklist { 8 | struct linkedlist waitlist; 9 | struct spinlock lock; 10 | }; 11 | 12 | enum block_result { 13 | BLOCK_RESULT_BLOCKED, 14 | BLOCK_RESULT_UNBLOCKED, 15 | BLOCK_RESULT_TIMEOUT, 16 | BLOCK_RESULT_INTERRUPTED, 17 | }; 18 | 19 | #define BLOCK_UNINTERRUPT 1 20 | #define BLOCK_TIMEOUT 2 21 | #define BLOCK_UNBLOCKED 4 22 | struct thread; 23 | struct blockpoint { 24 | struct thread * _Atomic thread; 25 | struct blocklist *bl; 26 | _Atomic int flags; 27 | long timeout; 28 | _Atomic enum block_result result; 29 | struct linkedentry node; 30 | struct timer timer; 31 | }; 32 | 33 | void blocklist_create(struct blocklist *bl); 34 | bool blocklist_unblock_one(struct blocklist *bl); 35 | void blockpoint_startblock(struct blocklist *bl, struct blockpoint *bp); 36 | enum block_result blockpoint_cleanup(struct blockpoint *bp); 37 | void thread_unblock(struct thread *thread); 38 | void blocklist_unblock_all(struct blocklist *bl); 39 | 40 | #include 41 | static inline void blockpoint_create(struct blockpoint *bp, int flags, long timeout) 42 | { 43 | assert(!(flags & BLOCK_UNBLOCKED)); 44 | bp->flags = flags; 45 | bp->timeout = timeout; 46 | bp->result = BLOCK_RESULT_UNBLOCKED; 47 | bp->thread = NULL; 48 | bp->bl = NULL; 49 | } 50 | 51 | struct sleepflag { 52 | _Atomic int flag; 53 | struct blocklist bl; 54 | }; 55 | 56 | void sleepflag_wake(struct sleepflag *s); 57 | void sleepflag_sleep(struct sleepflag *s); 58 | void sleepflag_create(struct sleepflag *s); 59 | 60 | -------------------------------------------------------------------------------- /include/charbuffer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #define CHARBUFFER_DO_ANY 1 7 | #define CHARBUFFER_DO_NONBLOCK 2 8 | 9 | struct charbuffer { 10 | _Atomic char *buffer; 11 | size_t capacity; 12 | _Atomic size_t head, tail, pending; 13 | struct blocklist wait_write, wait_read; 14 | struct spinlock write, read; 15 | _Atomic bool term; 16 | int eof; 17 | }; 18 | 19 | static inline size_t charbuffer_pending(struct charbuffer *cb) { return cb->pending; } 20 | static inline size_t charbuffer_avail(struct charbuffer *cb) 21 | { return cb->capacity - cb->pending; } 22 | 23 | void charbuffer_create(struct charbuffer *cb, size_t cap); 24 | ssize_t charbuffer_write(struct charbuffer *cb, const char *buf, size_t len, int flags); 25 | ssize_t charbuffer_read(struct charbuffer *cb, char *buf, size_t len, int flags); 26 | void charbuffer_terminate(struct charbuffer *cb); 27 | void charbuffer_destroy(struct charbuffer *cb); 28 | void charbuffer_reset(struct charbuffer *cb); 29 | 30 | -------------------------------------------------------------------------------- /include/debug.h: -------------------------------------------------------------------------------- 1 | #ifndef __DEBUG_H 2 | #define __DEBUG_H 3 | 4 | #include 5 | #include 6 | 7 | #if FEATURE_SUPPORTED_UNWIND 8 | struct frame { 9 | uintptr_t pc, fp; 10 | }; 11 | void debug_print_backtrace(void); 12 | bool arch_debug_unwind_frame(struct frame *frame); 13 | #endif 14 | 15 | #endif 16 | 17 | -------------------------------------------------------------------------------- /include/device.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | struct inode; 6 | struct file_calls; 7 | 8 | struct device { 9 | struct hashelem elem; 10 | struct file_calls *calls; 11 | int devnr; 12 | struct hash attached; 13 | }; 14 | 15 | struct attachment { 16 | int id; 17 | void *obj; 18 | struct hashelem elem; 19 | }; 20 | 21 | #define DEVICE_INITIALIZER_ORDER 100 22 | 23 | struct file_calls *dev_get_fops(struct inode *); 24 | int dev_register(struct device *dev, struct file_calls *calls, int type); 25 | struct device *dev_get(int type, int major); 26 | void *dev_get_attached(struct device *dev, int id); 27 | void dev_attach(struct device *dev, struct attachment *at, int id, void *); 28 | 29 | #define major(x) \ 30 | ((unsigned)( (((x)>>31>>1) & 0xfffff000) | (((x)>>8) & 0x00000fff) )) 31 | #define minor(x) \ 32 | ((unsigned)( (((x)>>12) & 0xffffff00) | ((x) & 0x000000ff) )) 33 | 34 | #define makedev(x,y) ( \ 35 | ((((unsigned long)x)&0xfffff000ULL) << 32) | \ 36 | ((((unsigned long)x)&0x00000fffULL) << 8) | \ 37 | (((y)&0xffffff00ULL) << 12) | \ 38 | (((y)&0x000000ffULL)) ) 39 | 40 | -------------------------------------------------------------------------------- /include/devices/serial.h: -------------------------------------------------------------------------------- 1 | #ifndef __DEVICES_SERIAL_H 2 | #define __DEVICES_SERIAL_H 3 | 4 | void serial_puts(const char * str); 5 | 6 | #endif 7 | 8 | -------------------------------------------------------------------------------- /include/drivers/pci.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | struct pci_config_space 7 | { 8 | /* 0x00 */ 9 | uint16_t vendor_id; 10 | uint16_t device_id; 11 | /* 0x04 */ 12 | uint16_t command; 13 | uint16_t status; 14 | /* 0x08 */ 15 | uint16_t revision; 16 | uint8_t subclass; 17 | uint8_t class_code; 18 | /* 0x0C */ 19 | uint8_t cache_line_size; 20 | uint8_t latency_timer; 21 | uint8_t header_type; 22 | uint8_t bist; 23 | /* 0x10 */ 24 | uint32_t bar[6]; 25 | /* 0x28 */ 26 | uint32_t cardbus_cis_pointer; 27 | /* 0x2C */ 28 | uint16_t subsystem_vendor_id; 29 | uint16_t subsystem_id; 30 | /* 0x30 */ 31 | uint32_t expansion_rom_base_address; 32 | /* 0x34 */ 33 | uint32_t reserved0; 34 | /* 0x38 */ 35 | uint32_t reserved1; 36 | /* 0x3C */ 37 | uint8_t interrupt_line; 38 | uint8_t interrupt_pin; 39 | uint8_t min_grant; 40 | uint8_t max_latency; 41 | }__attribute__((packed)); 42 | 43 | struct pci_driver; 44 | struct pci_device { 45 | struct kobj_header _header; 46 | int bus, dev, func; 47 | struct pci_config_space config; 48 | int flags; 49 | 50 | struct pci_driver *driver; 51 | 52 | struct linkedentry entry; 53 | }; 54 | 55 | #define PCI_BAR_IO 1 56 | #define PCI_BAR_MEM 0 57 | 58 | static inline uint32_t pci_get_bar(struct pci_device *dev, uint8_t type) 59 | { 60 | uint32_t bar = 0; 61 | for(int i = 0; i < 6; i++) 62 | { 63 | bar = dev->config.bar[i]; 64 | if((bar & 0x1) == type) { 65 | return type == PCI_BAR_IO ? bar & ~1 : bar & ~3; 66 | } 67 | } 68 | return 0xFFFFFFFF; 69 | } 70 | 71 | struct pci_driver { 72 | int (*init_device)(struct pci_device *); 73 | struct linkedentry entry; 74 | const char *name; 75 | 76 | int num; 77 | struct { 78 | uint16_t vendor; 79 | uint16_t device; 80 | } supported[]; 81 | }; 82 | 83 | void pci_register_driver(struct pci_driver *driver); 84 | void pci_write_dword(const uint16_t bus, const uint16_t dev, const uint16_t func, const uint32_t reg, unsigned data); 85 | #define PCI_INITIALIZER_ORDER 1 86 | -------------------------------------------------------------------------------- /include/fcntl.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define FD_CLOEXEC 1 4 | -------------------------------------------------------------------------------- /include/frame.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #define FRAME_PERSIST 1 5 | #define FRAME_NOCLEAR 2 6 | #define FRAME_ZEROCOUNT 4 7 | #define FRAME_DIRTY 8 8 | struct frame { 9 | _Atomic int flags; 10 | _Atomic long count; 11 | }; 12 | 13 | uintptr_t frame_get_physical(struct frame *); 14 | struct frame *frame_get_from_address(uintptr_t phys); 15 | void frame_acquire(uintptr_t phys); 16 | uintptr_t frame_allocate(int level, int flags); 17 | long frame_release(uintptr_t phys); 18 | 19 | -------------------------------------------------------------------------------- /include/fs/dirent.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #define DIRENT_UNLINK 1 7 | #define DIRENT_UNCACHED 2 8 | 9 | struct dirent { 10 | struct kobj_header _header; 11 | 12 | _Atomic int flags; 13 | struct inode_id ino; 14 | struct inode *pnode; 15 | struct inode_id parent; 16 | size_t namelen; 17 | char name[256]; 18 | }; 19 | 20 | #define DIRENT_ID_LEN (sizeof(char) * 256 + sizeof(size_t) + sizeof(struct inode_id)) 21 | 22 | struct kobj kobj_dirent; 23 | struct inode *dirent_get_inode(struct dirent *); 24 | void dirent_put(struct dirent *dir); 25 | struct dirent *dirent_lookup(struct inode *node, const char *name, size_t namelen); 26 | struct dirent *dirent_lookup_cached(struct inode *node, const char *name, size_t namelen); 27 | 28 | struct gd_dirent { 29 | int64_t d_ino; /* 64-bit inode number */ 30 | int64_t d_off; /* 64-bit offset to next structure */ 31 | unsigned short d_reclen; /* Size of this dirent */ 32 | unsigned char d_type; /* File type */ 33 | char d_name[]; /* Filename (null-terminated) */ 34 | }; 35 | 36 | 37 | -------------------------------------------------------------------------------- /include/fs/filesystem.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | struct inode; 12 | struct dirent; 13 | struct blockdev; 14 | 15 | struct inode_ops { 16 | int (*read_page)(struct inode *, int pagenr, uintptr_t phys); 17 | int (*write_page)(struct inode *, int pagenr, uintptr_t phys); 18 | int (*sync)(struct inode *); 19 | int (*update)(struct inode *); 20 | int (*lookup)(struct inode *, const char *name, size_t namelen, struct dirent *); 21 | int (*link)(struct inode *, const char *name, size_t namelen, struct inode *); 22 | int (*unlink)(struct inode *, const char *name, size_t namelen); 23 | size_t (*getdents)(struct inode *node, _Atomic size_t *, struct gd_dirent *, size_t); 24 | int (*readlink)(struct inode *node, char *path, size_t); 25 | int (*writelink)(struct inode *node, const char *path); 26 | }; 27 | 28 | struct filesystem; 29 | struct fs_ops { 30 | int (*mount)(struct filesystem *fs, struct blockdev *bd, unsigned long flags); 31 | int (*unmount)(struct filesystem *fs); 32 | int (*load_inode)(struct filesystem *fs, uint64_t inoid, struct inode *node); 33 | int (*alloc_inode)(struct filesystem *fs, uint64_t *inoid); 34 | int (*update_inode)(struct filesystem *fs, struct inode *node); 35 | void (*release_inode)(struct filesystem *fs, struct inode *node); 36 | }; 37 | 38 | struct fsdriver { 39 | struct inode_ops *inode_ops; 40 | struct fs_ops *fs_ops; 41 | const char *name; 42 | uint64_t rootid; 43 | struct hashelem elem; 44 | }; 45 | 46 | struct filesystem { 47 | struct kobj_header _header; 48 | uint64_t id; 49 | struct fsdriver *driver; 50 | void *fsdata; 51 | struct mutex lock; 52 | struct inode_id up_mount; 53 | }; 54 | 55 | #define FILESYSTEM_INIT_ORDER 100 56 | 57 | int fs_load_inode(uint64_t fsid, uint64_t inoid, struct inode *node); 58 | void fs_update_inode(struct inode *node); 59 | int filesystem_register(struct fsdriver *driver); 60 | struct filesystem *fs_load_filesystem(struct blockdev *bd, const char *type, unsigned long flags, int *err); 61 | void fs_unload_filesystem(struct filesystem *fs); 62 | void filesystem_deregister(struct fsdriver *driver); 63 | int fs_mount(struct inode *point, struct filesystem *fs); 64 | 65 | extern struct fsdriver ramfs; 66 | 67 | struct kobj kobj_filesystem; 68 | 69 | static inline struct inode *fs_inode_lookup(struct filesystem *fs, uint64_t inoid) 70 | { 71 | struct inode_id id = {.fsid = fs->id, .inoid = inoid }; 72 | return inode_lookup(&id); 73 | } 74 | 75 | #include 76 | static inline int fs_max_page(size_t len) 77 | { 78 | return len > 0 ? (int)((len - 1) / arch_mm_page_size(0)) : -1; 79 | } 80 | 81 | -------------------------------------------------------------------------------- /include/fs/inode.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | struct blockpoint; 7 | struct inode_id { 8 | uint64_t fsid; 9 | uint64_t inoid; 10 | }; 11 | 12 | struct inode; 13 | #define INODEPAGE_DIRTY 1 14 | 15 | struct inodepage_id { 16 | uint64_t fsid; 17 | uint64_t inoid; 18 | uint64_t page; 19 | }; 20 | 21 | struct inodepage { 22 | struct kobj_header _header; 23 | struct inodepage_id id; 24 | uintptr_t frame; 25 | _Atomic int flags; 26 | struct inode *node; 27 | }; 28 | 29 | #define INODE_FLAG_DIRTY 1 30 | #define INODE_FLAG_UNCACHED 2 31 | struct pipe; 32 | struct inode { 33 | struct kobj_header _header; 34 | _Atomic int flags; 35 | struct mutex lock; 36 | 37 | struct inode_id id; 38 | 39 | struct filesystem *fs; 40 | struct filesystem * _Atomic mount; 41 | 42 | _Atomic uint16_t mode; 43 | _Atomic uint16_t links; 44 | _Atomic size_t length; 45 | 46 | _Atomic uint64_t atime, mtime, ctime; 47 | _Atomic int uid, gid; 48 | 49 | int major, minor; 50 | struct pipe *pipe; 51 | struct blocklist readbl; 52 | }; 53 | 54 | extern struct kobj kobj_inode_page; 55 | struct file; 56 | 57 | void inode_put(struct inode *inode); 58 | void inode_release_page(struct inodepage *page); 59 | uintptr_t inode_acquire_page(struct inode *node, int nodepage); 60 | struct inodepage *inode_get_page(struct inode *node, int nodepage); 61 | struct inode *inode_lookup(struct inode_id *id); 62 | ssize_t inode_write_data(struct file *, size_t off, size_t len, const char *buf); 63 | ssize_t inode_read_data(struct file *, size_t off, size_t len, char *buf); 64 | bool inode_check_perm(struct inode *node, int type); 65 | bool inode_check_access(struct inode *node, int type); 66 | ssize_t inode_do_write_data(struct inode *ino, size_t off, size_t len, const char *buf); 67 | ssize_t inode_do_read_data(struct inode *ino, size_t off, size_t len, char *buf); 68 | 69 | static inline void inode_mark_dirty(struct inode *node) 70 | { 71 | node->flags |= INODE_FLAG_DIRTY; 72 | } 73 | 74 | 75 | -------------------------------------------------------------------------------- /include/fs/path.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define PATH_CREATE 1 4 | #define PATH_NOFOLLOW 2 5 | 6 | #define PATH_DID_CREATE 1 7 | 8 | struct dirent; 9 | struct inode; 10 | int fs_path_resolve(const char *path, struct inode *_start, int flags, int mode, struct dirent **dir_out, struct inode **ino_out); 11 | int fs_unlink(struct inode *node, const char *name, size_t namelen); 12 | int fs_link(struct inode *node, const char *name, size_t namelen, struct inode *target); 13 | int fs_rmdir(struct inode *node, const char *name, size_t namelen); 14 | -------------------------------------------------------------------------------- /include/fs/proc.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | void proc_destroy(const char *path); 4 | void proc_create(const char *path, ssize_t (*call)(void *data, int, size_t, size_t, char *), void *data); 5 | ssize_t proc_read_data(uint32_t id, size_t off, size_t len, char *b); 6 | #include 7 | #define PROCFS_PRINTF(offset,length,buf,current,format...) \ 8 | do { \ 9 | char line[1024]; \ 10 | int add = snprintf(line, 1024, format); \ 11 | if(current + add > offset && current < (offset + length)) { \ 12 | size_t linestart = current > offset ? 0 : (offset - current); \ 13 | size_t bufstart = current > offset ? (current - offset) : 0; \ 14 | size_t amount = add - linestart; \ 15 | if(amount > ((offset + length) - current)) \ 16 | amount = (offset + length) - current; \ 17 | memcpy(buf + bufstart, line + linestart, amount); \ 18 | current += amount; \ 19 | } else if(current + add <= offset) { \ 20 | offset -= add; \ 21 | } \ 22 | } while(0); 23 | 24 | 25 | ssize_t _proc_read_int(void *data, int rw, size_t off, size_t len, char *buf); 26 | -------------------------------------------------------------------------------- /include/fs/stat.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | struct stat { 4 | int64_t st_dev; 5 | int64_t st_ino; 6 | unsigned long st_nlink; 7 | 8 | unsigned st_mode; 9 | unsigned st_uid; 10 | unsigned st_gid; 11 | unsigned int __pad0; 12 | int64_t st_rdev; 13 | int64_t st_size; 14 | long st_blksize; 15 | int64_t st_blocks; 16 | 17 | struct timespec st_atim; 18 | struct timespec st_mtim; 19 | struct timespec st_ctim; 20 | long __unused[3]; 21 | }; 22 | 23 | #define S_IFMT 0170000 24 | 25 | #define S_IFDIR 0040000 26 | #define S_IFCHR 0020000 27 | #define S_IFBLK 0060000 28 | #define S_IFREG 0100000 29 | #define S_IFIFO 0010000 30 | #define S_IFLNK 0120000 31 | #define S_IFSOCK 0140000 32 | 33 | #define S_TYPEISMQ(buf) 0 34 | #define S_TYPEISSEM(buf) 0 35 | #define S_TYPEISSHM(buf) 0 36 | #define S_TYPEISTMO(buf) 0 37 | 38 | #define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) 39 | #define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR) 40 | #define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK) 41 | #define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) 42 | #define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO) 43 | #define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK) 44 | #define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK) 45 | 46 | #define PERM_READ 0400 47 | #define PERM_WRITE 0200 48 | #define PERM_EXEC 0100 49 | 50 | #define S_ISUID 04000 51 | #define S_ISGID 02000 52 | #define S_ISVTX 01000 53 | #define S_IRUSR 0400 54 | #define S_IWUSR 0200 55 | #define S_IXUSR 0100 56 | #define S_IRWXU 0700 57 | #define S_IRGRP 0040 58 | #define S_IWGRP 0020 59 | #define S_IXGRP 0010 60 | #define S_IRWXG 0070 61 | #define S_IROTH 0004 62 | #define S_IWOTH 0002 63 | #define S_IXOTH 0001 64 | #define S_IRWXO 0007 65 | 66 | -------------------------------------------------------------------------------- /include/interrupt.h: -------------------------------------------------------------------------------- 1 | #ifndef __INTERRUPT_H 2 | #define __INTERRUPT_H 3 | 4 | #define MAX_HANDLERS 128 5 | 6 | #define INTERRUPT_INKERNEL 1 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | struct exception_frame { 14 | struct kobj_header _header; 15 | struct arch_exception_frame arch; 16 | struct linkedentry node; 17 | sigset_t mask; 18 | }; 19 | 20 | void interrupt_init(void); 21 | void interrupt_entry(int vector, int flags); 22 | int interrupt_register(int vector, void (*f)(int, int flags)); 23 | void arch_interrupt_mask(int vector); 24 | void arch_interrupt_unmask(int vector); 25 | struct exception_frame *interrupt_pop_frame(void); 26 | void interrupt_push_frame(struct arch_exception_frame *af, struct sigaction *action); 27 | #endif 28 | 29 | -------------------------------------------------------------------------------- /include/klibc.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | void qsort (void* base, size_t num, size_t size, int (*compar)(const void*,const void*)); 4 | -------------------------------------------------------------------------------- /include/ksymbol.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | struct ksymbol { 6 | uintptr_t value; 7 | size_t size; 8 | const char *name; 9 | }; 10 | 11 | extern const struct ksymbol kernel_symbol_table[]; 12 | extern size_t kernel_symbol_table_length; 13 | 14 | const struct ksymbol *ksymbol_find_by_value(void *addr, bool range); 15 | const struct ksymbol *ksymbol_find_by_name(const char *name); 16 | 17 | -------------------------------------------------------------------------------- /include/lib/bitmap.h: -------------------------------------------------------------------------------- 1 | #ifndef __LIB_BITMAP_H 2 | #define __LIB_BITMAP_H 3 | 4 | #include 5 | 6 | static inline void bitmap_assign(void *ptr, int bit, int val) 7 | { 8 | int index = bit / 8; 9 | int offset = bit % 8; 10 | uint8_t *tmp = ptr; 11 | if(val) 12 | tmp[index] |= (1 << offset); 13 | else 14 | tmp[index] &= ~(1 << offset); 15 | } 16 | 17 | static inline int bitmap_test(void *ptr, int bit) 18 | { 19 | int index = bit / 8; 20 | int offset = bit % 8; 21 | uint8_t *tmp = ptr; 22 | return (tmp[index] & (1 << offset)); 23 | } 24 | 25 | static inline int bitmap_ffs(void *ptr, int numbits) 26 | { 27 | uint8_t *tmp = ptr; 28 | for(int i=0;i 5 | #include 6 | #include 7 | 8 | #define HASH_LOCKLESS 1 9 | struct hashelem { 10 | void *ptr; 11 | const void *key; 12 | size_t keylen; 13 | struct linkedentry entry; 14 | }; 15 | 16 | struct hash { 17 | struct linkedlist *table; 18 | _Atomic size_t length, count; 19 | int flags; 20 | struct spinlock lock; 21 | }; 22 | 23 | struct hashiter { 24 | struct hash *hash; 25 | unsigned int bucket; 26 | struct linkedentry *entry, *next; 27 | }; 28 | 29 | void __hash_unlock(struct hash *h); 30 | void __hash_lock(struct hash *h); 31 | 32 | static inline void *hash_iter_get(struct hashiter *iter) { return ((struct hashelem *)iter->entry->obj)->ptr; } 33 | static inline bool hash_iter_done(struct hashiter *iter) 34 | { 35 | return iter->bucket >= iter->hash->length; 36 | } 37 | 38 | void hash_iter_init(struct hashiter *iter, struct hash *h); 39 | void hash_iter_next(struct hashiter *iter); 40 | static inline size_t hash_count(struct hash *h) { return h->count; } 41 | static inline size_t hash_length(struct hash *h) { return h->length; } 42 | 43 | void hash_create(struct hash *h, int flags, size_t length); 44 | void hash_destroy(struct hash *h); 45 | int hash_insert(struct hash *h, const void *key, size_t keylen, struct hashelem *elem, void *data); 46 | int hash_delete(struct hash *h, const void *key, size_t keylen); 47 | void *hash_lookup(struct hash *h, const void *key, size_t keylen); 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /include/lib/heap.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | struct heapnode { 7 | struct heapnode *left, *right, *parent; 8 | void *data; 9 | }; 10 | 11 | enum heap_type { 12 | heap_type_max, 13 | heap_type_min, 14 | }; 15 | 16 | struct heap { 17 | struct heapnode *root, *end; 18 | _Atomic size_t count; 19 | struct spinlock lock; 20 | enum heap_type type; 21 | int (*compare)(void *, void *); 22 | }; 23 | 24 | static inline size_t heap_count(struct heap *heap) 25 | { 26 | return heap->count; 27 | } 28 | 29 | void *heap_pop(struct heap *heap); 30 | void heap_insert(struct heap *heap, struct heapnode *node, void *data); 31 | void heap_create(struct heap *heap, int (*comp)(void *, void *), enum heap_type type); 32 | -------------------------------------------------------------------------------- /include/lib/linkedlist.h: -------------------------------------------------------------------------------- 1 | #ifndef __LIB_LINKEDLIST_H 2 | #define __LIB_LINKEDLIST_H 3 | 4 | #define LINKEDLIST_LOCKLESS 1 5 | struct linkedlist; 6 | struct linkedentry { 7 | void *obj; 8 | struct linkedlist *list; 9 | struct linkedentry *next, *prev; 10 | }; 11 | 12 | #define linkedentry_obj(entry) ((entry) ? (entry)->obj : NULL) 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | struct linkedlist { 20 | struct linkedentry * _Atomic head; 21 | struct linkedentry sentry; 22 | struct spinlock lock; 23 | _Atomic ssize_t count; 24 | int flags; 25 | }; 26 | 27 | #define linkedlist_iter_end(list) &(list)->sentry 28 | #define linkedlist_iter_start(list) (list)->head->next 29 | #define linkedlist_iter_next(entry) (entry)->next 30 | 31 | #define linkedlist_back_iter_end(list) &(list)->sentry 32 | #define linkedlist_back_iter_start(list) (list)->head->prev 33 | #define linkedlist_back_iter_next(entry) (entry)->prev 34 | 35 | static inline void __linkedlist_lock(struct linkedlist *list) 36 | { 37 | if(likely(!(list->flags & LINKEDLIST_LOCKLESS))) { 38 | spinlock_acquire(&list->lock); 39 | } 40 | } 41 | 42 | static inline void __linkedlist_unlock(struct linkedlist *list) 43 | { 44 | if(likely(!(list->flags & LINKEDLIST_LOCKLESS))) { 45 | spinlock_release(&list->lock); 46 | } 47 | } 48 | 49 | void *linkedlist_head(struct linkedlist *list); 50 | void *linkedlist_remove_head(struct linkedlist *list); 51 | void *__linkedlist_remove_tail(struct linkedlist *list, bool locked); 52 | #define linkedlist_remove_tail(list) __linkedlist_remove_tail(list, false) 53 | void linkedlist_create(struct linkedlist *list, int flags); 54 | void linkedlist_insert(struct linkedlist *list, struct linkedentry *entry, void *obj); 55 | void linkedlist_remove(struct linkedlist *list, struct linkedentry *entry); 56 | struct linkedentry *linkedlist_find(struct linkedlist *list, bool (*fn)(struct linkedentry *, void *data), void *data); 57 | 58 | #endif 59 | 60 | -------------------------------------------------------------------------------- /include/lib/stack.h: -------------------------------------------------------------------------------- 1 | #ifndef __SEA_LIB_STACK_H 2 | #define __SEA_LIB_STACK_H 3 | 4 | #include 5 | #include 6 | #include 7 | #define STACK_LOCKLESS 1 8 | 9 | struct stack_elem { 10 | void *obj; 11 | struct stack_elem *next, *prev; 12 | }; 13 | 14 | struct stack { 15 | int flags; 16 | _Atomic size_t count; 17 | struct stack_elem *top; 18 | struct spinlock lock; 19 | }; 20 | 21 | static inline bool stack_is_empty(struct stack *stack) 22 | { 23 | return stack->count == 0; 24 | } 25 | 26 | void stack_create(struct stack *stack, int flags); 27 | void stack_push(struct stack *stack, struct stack_elem *elem, void *obj); 28 | void *stack_pop(struct stack *stack); 29 | void stack_delete(struct stack *stack, struct stack_elem *elem); 30 | 31 | #endif 32 | 33 | -------------------------------------------------------------------------------- /include/lib/ubsan.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | enum { 4 | type_kind_int = 0, 5 | type_kind_float = 1, 6 | type_unknown = 0xffff 7 | }; 8 | 9 | struct type_descriptor { 10 | uint16_t type_kind; 11 | uint16_t type_info; 12 | char type_name[1]; 13 | }; 14 | 15 | struct source_location { 16 | const char *file_name; 17 | union { 18 | unsigned long reported; 19 | struct { 20 | uint32_t line; 21 | uint32_t column; 22 | }; 23 | }; 24 | }; 25 | 26 | struct overflow_data { 27 | struct source_location location; 28 | struct type_descriptor *type; 29 | }; 30 | 31 | struct type_mismatch_data { 32 | struct source_location location; 33 | struct type_descriptor *type; 34 | unsigned long alignment; 35 | unsigned char type_check_kind; 36 | }; 37 | 38 | struct nonnull_arg_data { 39 | struct source_location location; 40 | struct source_location attr_location; 41 | int arg_index; 42 | }; 43 | 44 | struct nonnull_return_data { 45 | struct source_location location; 46 | struct source_location attr_location; 47 | }; 48 | 49 | struct vla_bound_data { 50 | struct source_location location; 51 | struct type_descriptor *type; 52 | }; 53 | 54 | struct out_of_bounds_data { 55 | struct source_location location; 56 | struct type_descriptor *array_type; 57 | struct type_descriptor *index_type; 58 | }; 59 | 60 | struct shift_out_of_bounds_data { 61 | struct source_location location; 62 | struct type_descriptor *lhs_type; 63 | struct type_descriptor *rhs_type; 64 | }; 65 | 66 | struct unreachable_data { 67 | struct source_location location; 68 | }; 69 | 70 | struct invalid_value_data { 71 | struct source_location location; 72 | struct type_descriptor *type; 73 | }; 74 | 75 | -------------------------------------------------------------------------------- /include/map.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #define MMAP_MAP_SHARED 0x1 7 | #define MMAP_MAP_PRIVATE 0x2 8 | #define MMAP_MAP_FIXED 0x10 9 | #define MMAP_MAP_ANON 0x20 10 | 11 | #define PROT_READ 1 12 | #define PROT_WRITE 2 13 | #define PROT_EXEC 4 14 | 15 | #define MREMAP_MAYMOVE 1 16 | #define MREMAP_FIXED 2 17 | 18 | struct inode; 19 | struct inodepage; 20 | struct mapping { 21 | struct kobj_header _header; 22 | uintptr_t vpage; 23 | struct file *file; 24 | struct inodepage *page; 25 | int prot, flags, nodepage; 26 | }; 27 | 28 | struct map_region { 29 | struct kobj_header _header; 30 | struct linkedentry entry; 31 | uintptr_t start; 32 | size_t psize; 33 | size_t length; 34 | 35 | struct file *file; 36 | int nodepage; 37 | int prot; 38 | int flags; 39 | }; 40 | 41 | struct process; 42 | 43 | 44 | void map_region_setup(struct process *proc, uintptr_t start, size_t len, int prot, int flags, struct file *file, int nodepage, size_t psize, bool locked); 45 | void map_mmap(struct process *proc, uintptr_t virt, size_t len, int prot, int flags, struct file *file, size_t off); 46 | 47 | int mmu_mappings_handle_fault(struct process *proc, uintptr_t addr, int flags); 48 | int mapping_resize(struct process *proc, uintptr_t virt, size_t oldsz, size_t newsz); 49 | int mapping_move(struct process *proc, uintptr_t virt, size_t oldsz, size_t newsz, uintptr_t new); 50 | int map_change_protect(struct process *proc, uintptr_t virt, size_t len, int prot); 51 | void map_region_remove(struct process *proc, uintptr_t start, size_t len, bool locked); 52 | 53 | -------------------------------------------------------------------------------- /include/mmu.h: -------------------------------------------------------------------------------- 1 | #ifndef __MMU_H 2 | #define __MMU_H 3 | 4 | #define MAP_DEVICE 0x2 /* controls caching, if possible */ 5 | #define MAP_USER 0x4 6 | #define MAP_WRITE 0x8 7 | #define MAP_PRIVATE 0x10 /* is only accessed inside this address-space */ 8 | #define MAP_ACCESSED 0x20 /* has been accessed (if supported, set by processor) */ 9 | #define MAP_EXECUTE 0x40 10 | #define MAP_DIRTY 0x80 11 | 12 | #define FAULT_EXEC 0x1 13 | #define FAULT_WRITE 0x2 14 | #define FAULT_USER 0x4 15 | #define FAULT_ERROR_PERM 0x10 16 | #define FAULT_ERROR_PRES 0x20 17 | 18 | #define MM_BUDDY_MIN_SIZE 0x1000 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | struct vm_context { 26 | struct kobj_header _header; 27 | struct arch_vm_context arch; 28 | }; 29 | 30 | extern struct kobj kobj_vm_context; 31 | 32 | extern struct vm_context kernel_context; 33 | void arch_mm_context_switch(struct vm_context *ctx); 34 | uintptr_t mm_physical_allocate(size_t length, bool clear); 35 | void mm_physical_deallocate(uintptr_t address); 36 | void mm_init(void); 37 | void mm_early_init(void); 38 | 39 | void arch_mm_context_create(struct vm_context *ctx); 40 | void arch_mm_context_init(struct vm_context *ctx); 41 | void arch_mm_context_destroy(struct vm_context *ctx); 42 | 43 | __attribute__((const,pure)) size_t arch_mm_page_size(int level); 44 | bool arch_mm_virtual_map(struct vm_context *ctx, uintptr_t virt, 45 | uintptr_t phys, size_t pagesize, int flags); 46 | uintptr_t arch_mm_virtual_unmap(struct vm_context *, uintptr_t virt); 47 | bool arch_mm_virtual_getmap(struct vm_context *, uintptr_t virt, uintptr_t *phys, int *flags, size_t *); 48 | bool arch_mm_virtual_chattr(struct vm_context *ctx, uintptr_t virt, int flags); 49 | 50 | void pmm_buddy_init(void); 51 | void mm_fault_entry(uintptr_t address, int flags, uintptr_t); 52 | void mm_print_context(struct vm_context *ctx); 53 | 54 | static inline uintptr_t mm_virtual_allocate(size_t length, 55 | bool clear) 56 | { 57 | return mm_physical_allocate(length, clear) + PHYS_MAP_START; 58 | } 59 | 60 | static inline void mm_virtual_deallocate(uintptr_t addr) 61 | { 62 | mm_physical_deallocate(addr - PHYS_MAP_START); 63 | } 64 | 65 | static inline uintptr_t page_mask(int l) 66 | { 67 | return ~(arch_mm_page_size(l) - 1); 68 | } 69 | 70 | static inline int mm_get_pagelevel(size_t len) 71 | { 72 | for(int i=MMU_NUM_PAGESIZE_LEVELS-1;i>=0;i--) { 73 | if(arch_mm_page_size(i) <= len) 74 | return i; 75 | } 76 | return 0; 77 | } 78 | 79 | #endif 80 | 81 | -------------------------------------------------------------------------------- /include/mutex.h: -------------------------------------------------------------------------------- 1 | #ifndef __MUTEX_H 2 | #define __MUTEX_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | struct thread; 9 | struct mutex { 10 | _Atomic int lock; 11 | struct blocklist wait; 12 | #if CONFIG_DEBUG 13 | struct thread * _Atomic owner; 14 | #endif 15 | }; 16 | 17 | void mutex_acquire(struct mutex *); 18 | void mutex_release(struct mutex *); 19 | void mutex_create(struct mutex *); 20 | 21 | #endif 22 | 23 | -------------------------------------------------------------------------------- /include/net/network.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | int net_network_send(struct socket *, const struct sockaddr *dest, const void *trheader, size_t thlen, const void *msg, size_t mlen, int prot, int checksum_offset); 6 | -------------------------------------------------------------------------------- /include/net/nic.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | struct nic; 9 | struct packet; 10 | 11 | enum { 12 | NIC_TYPE_ETHERNET, 13 | }; 14 | 15 | enum network_type { 16 | NETWORK_TYPE_IPV6, 17 | 18 | NETWORK_TYPE_NUM, 19 | }; 20 | 21 | struct nic_driver { 22 | const char *name; 23 | int (*recv)(struct nic *); 24 | void (*send)(struct nic *, struct packet *); 25 | int type; 26 | size_t headlen; 27 | }; 28 | 29 | enum nic_change_event { 30 | NIC_CHANGE_CREATE, 31 | NIC_CHANGE_DELETE, 32 | NIC_CHANGE_UP, 33 | }; 34 | 35 | struct network_protocol { 36 | const char *name; 37 | void (*nic_change)(struct nic *, enum nic_change_event event); 38 | }; 39 | 40 | struct physical_address { 41 | size_t len; 42 | uint8_t octets[6]; 43 | }; 44 | 45 | struct nic { 46 | struct kobj_header _header; 47 | int id; 48 | void *data; 49 | struct worker worker; 50 | struct blocklist bl; 51 | struct spinlock lock; 52 | _Atomic bool rxpending; 53 | const struct nic_driver *driver; 54 | struct physical_address physaddr; 55 | 56 | void *netprotdata[NETWORK_TYPE_NUM]; 57 | char name[16]; 58 | struct hashelem elem; 59 | struct hashelem elemnum; 60 | }; 61 | 62 | struct nic *net_nic_init(void *data, struct nic_driver *, void *, size_t); 63 | void net_nic_receive(struct nic *nic, void *data, size_t length, int flags); 64 | void net_nic_change(struct nic *nic, enum nic_change_event event); 65 | struct nic *net_nic_get_byname(const char *name); 66 | struct nic *net_nic_get_bynum(int num); 67 | 68 | void net_ethernet_receive(struct packet *packet); 69 | void net_ethernet_send(struct packet *packet, int prot, struct physical_address *addr); 70 | 71 | -------------------------------------------------------------------------------- /include/net/packet.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | struct nic; 7 | struct network_address; 8 | struct packet { 9 | struct kobj_header _header; 10 | void *data; 11 | size_t length; 12 | struct nic *origin, *sender; 13 | struct linkedentry queue_entry; 14 | void *transport_header; 15 | void *network_header; 16 | struct sockaddr saddr; 17 | struct sockaddr daddr; 18 | }; 19 | 20 | extern struct kobj kobj_packet; 21 | void *net_packet_buffer_allocate(void); 22 | struct packet *packet_duplicate(const struct packet *src); 23 | 24 | -------------------------------------------------------------------------------- /include/obj/object.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #define FOT_PRESENT 1 5 | 6 | struct fot_entry { 7 | uint64_t guid[2]; 8 | uint64_t res; 9 | uint64_t options; 10 | } __attribute__((packed)); 11 | 12 | struct fot { 13 | uint32_t length; 14 | uint32_t flags; 15 | struct fot_entry entries[]; 16 | } __attribute__((packed)); 17 | 18 | struct object { 19 | struct kobj_header _header; 20 | uint64_t guid[2]; 21 | size_t length; 22 | struct hashelem elem; 23 | 24 | struct hash physicals; 25 | struct fot *fot; 26 | }; 27 | 28 | void frame_release(uintptr_t phys); 29 | uintptr_t frame_allocate(void); 30 | void frame_acquire(uintptr_t phys); 31 | 32 | extern struct kobj kobj_object; 33 | uintptr_t object_allocate_frame(struct object *obj, int pagenr); 34 | void object_assign_guid(struct object *obj, uint64_t *guid); 35 | struct object *object_get_by_guid(uint64_t *guid); 36 | 37 | -------------------------------------------------------------------------------- /include/obj/process.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | struct process { 10 | struct kobj_header _header; 11 | struct vm_context *ctx; 12 | struct linkedlist threads; 13 | struct linkedlist objects; 14 | 15 | struct object *user_context_object; 16 | }; 17 | 18 | extern struct kobj kobj_process; 19 | 20 | void process_attach_thread(struct process *proc, struct thread *thread); 21 | void process_pagefault_handle(uintptr_t addr, int flags); 22 | 23 | -------------------------------------------------------------------------------- /include/panic.h: -------------------------------------------------------------------------------- 1 | #ifndef __PANIC_H 2 | #define __PANIC_H 3 | 4 | #include 5 | 6 | __attribute__((format(printf, 2, 3))) 7 | noreturn void panic(int flags, const char *fmt, ...); 8 | 9 | void arch_panic_begin(void); 10 | #endif 11 | 12 | -------------------------------------------------------------------------------- /include/printk.h: -------------------------------------------------------------------------------- 1 | #ifndef __PRINTK_H 2 | #define __PRINTK_H 3 | #include 4 | #include 5 | 6 | __attribute__ ((format (printf, 1, 2))) void printk(const char *, ...); 7 | int vprintk(const char *fmt, va_list args); 8 | int snprintf(char *buf, size_t len, const char *fmt, ...); 9 | 10 | #endif 11 | 12 | -------------------------------------------------------------------------------- /include/priqueue.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | struct priqueue_node { 6 | struct linkedentry entry; 7 | }; 8 | 9 | #define PRIQUEUE_LEVELS 32 10 | 11 | struct priqueue { 12 | struct spinlock lock; 13 | int levels, curhighest; 14 | struct linkedlist lists[PRIQUEUE_LEVELS]; 15 | }; 16 | 17 | void *priqueue_pop(struct priqueue *pq); 18 | void priqueue_insert(struct priqueue *pq, struct priqueue_node *node, void *data, int pri); 19 | void priqueue_create(struct priqueue *pq, int levels); 20 | 21 | -------------------------------------------------------------------------------- /include/processor.h: -------------------------------------------------------------------------------- 1 | #ifndef __PROCESSOR_H 2 | #define __PROCESSOR_H 3 | 4 | #define MAX_PROCESSORS 64 5 | 6 | #define PROCESSOR_PRESENT 1 7 | #define PROCESSOR_UP 2 8 | 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | struct processor { 18 | struct arch_processor arch; 19 | int id; 20 | int flags; 21 | struct thread idle_thread; 22 | _Atomic long long time; 23 | _Atomic int preempt_disable; 24 | void *idle_stack; 25 | struct workqueue workqueue; 26 | struct priqueue runqueue; 27 | struct thread * _Atomic running; 28 | struct spinlock schedlock; 29 | }; 30 | 31 | void processor_create(int id, int flags); 32 | void arch_processor_poke_secondary(int id, uintptr_t); 33 | void arch_processor_reset(void); 34 | void processor_start_secondaries(void); 35 | void processor_secondary_main(void); 36 | int arch_processor_current_id(void); 37 | void processor_add_thread(struct processor *proc, struct thread *thread); 38 | void processor_remove_thread(struct thread *thread); 39 | 40 | extern struct processor plist[]; 41 | 42 | static inline struct processor *processor_get_id(int id) 43 | { 44 | return &plist[id]; 45 | } 46 | 47 | static inline struct processor *processor_get_current(void) 48 | { 49 | int old = arch_interrupt_set(0); 50 | struct processor *proc = current_thread ? current_thread->processor : processor_get_id(arch_processor_current_id()); 51 | int r = atomic_fetch_add_explicit(&proc->preempt_disable, 1, memory_order_acquire); 52 | assert(r >= 0); 53 | arch_interrupt_set(old); 54 | return proc; 55 | } 56 | 57 | static inline void processor_release(struct processor *proc) 58 | { 59 | int r = atomic_fetch_sub_explicit(&proc->preempt_disable, 1, memory_order_release); 60 | assert(r > 0); 61 | } 62 | 63 | static inline void processor_disable_preempt(void) 64 | { 65 | int old = arch_interrupt_set(0); 66 | struct processor *proc = current_thread ? current_thread->processor : processor_get_id(arch_processor_current_id()); 67 | int r = atomic_fetch_add_explicit(&proc->preempt_disable, 1, memory_order_acquire); 68 | assert(r >= 0); 69 | arch_interrupt_set(old); 70 | } 71 | 72 | static inline void processor_enable_preempt(void) 73 | { 74 | int old = arch_interrupt_set(0); 75 | struct processor *proc = current_thread ? current_thread->processor : processor_get_id(arch_processor_current_id()); 76 | int r = atomic_fetch_sub_explicit(&proc->preempt_disable, 1, memory_order_release); 77 | assert(r > 0); 78 | arch_interrupt_set(old); 79 | } 80 | 81 | #if FEATURE_SUPPORTED_CYCLE_COUNT 82 | uint64_t arch_processor_get_cycle_count(void); 83 | #endif 84 | uint64_t arch_processor_get_nanoseconds(void); 85 | 86 | #endif 87 | 88 | -------------------------------------------------------------------------------- /include/random.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | uint32_t random_u32(void); 4 | 5 | -------------------------------------------------------------------------------- /include/refcount.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | typedef _Atomic unsigned long refcount_t; 5 | 6 | static inline void refcount_get(refcount_t *refs) 7 | { 8 | atomic_fetch_add(refs, 1); 9 | } 10 | 11 | static inline bool refcount_dec(refcount_t *refs, void (*destroy)(void *), void *obj) 12 | { 13 | if(atomic_fetch_sub(refs, 1) == 1) 14 | destroy(obj); 15 | } 16 | 17 | -------------------------------------------------------------------------------- /include/spinlock.h: -------------------------------------------------------------------------------- 1 | #ifndef __SPINLOCK_H 2 | #define __SPINLOCK_H 3 | #include 4 | #include 5 | struct spinlock { 6 | atomic_flag lock; 7 | int interrupt; 8 | }; 9 | 10 | void spinlock_create(struct spinlock *); 11 | void spinlock_acquire(struct spinlock *); 12 | void spinlock_release(struct spinlock *); 13 | 14 | #define SPINLOCK_INIT { {0}, 0 } 15 | 16 | #endif 17 | 18 | -------------------------------------------------------------------------------- /include/string.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | size_t strlen(const char *s); 4 | int memcmp(const void* ptr1, const void* ptr2, size_t num); 5 | void* memchr(const void* ptr, int value, size_t num); 6 | int strcmp(const char* str1, const char* str2); 7 | void *memset(void *s, int c, size_t n); 8 | int strncmp(const char* s1, const char* s2, size_t n); 9 | void* memcpy(void* destination, const void* source, size_t num); 10 | void* memmove(void* destination, const void* source, size_t num); 11 | char *strncpy(char *dest, const char *src, size_t n); 12 | const char *strrchrc(const char *str, char v); 13 | char *strrchrm(char *str, char v); 14 | const char *strchrc(const char *str, char v); 15 | long strtol(char *str, char **end, int base); 16 | char *strcat(char *str, const char *cat); 17 | -------------------------------------------------------------------------------- /include/system.h: -------------------------------------------------------------------------------- 1 | #ifndef __SYSTEM_H 2 | #define __SYSTEM_H 3 | 4 | #define likely(cond) __builtin_expect(cond, 1) 5 | #define unlikely(cond) __builtin_expect(cond, 0) 6 | 7 | #define stringify_define(x) stringify(x) 8 | #define stringify(x) #x 9 | 10 | #define __initializer __attribute__((used,constructor)) 11 | #define __orderedinitializer(x) __attribute__((used,constructor (x + 3000) )) 12 | 13 | #define ORDERED_FIRST 0 14 | #define ORDERED_LAST 3000 15 | 16 | #define __orderedafter(x) (x+1) 17 | #define __orderedbefore(x) (x-1) 18 | 19 | /* credit to Andrew Kwong for this */ 20 | static inline unsigned long long __round_up_pow2(unsigned int a) 21 | { 22 | return 1ull << (sizeof(a) * 8 - __builtin_clz(a)); 23 | } 24 | 25 | void init_register_late_call(void *call, void *data); 26 | 27 | #define LATE_INIT_CALL(call, data) \ 28 | __initializer static void ___init##__LINE__##__FILE__##_lateinitreg(void) { init_register_late_call((void *)&call, data); } 29 | 30 | #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ 31 | 32 | #define BIG_TO_HOST16(x) __builtin_bswap16(x) 33 | #define BIG_TO_HOST32(x) __builtin_bswap32(x) 34 | #define BIG_TO_HOST64(x) __builtin_bswap64(x) 35 | 36 | #define LITTLE_TO_HOST16(x) (x) 37 | #define LITTLE_TO_HOST32(x) (x) 38 | #define LITTLE_TO_HOST64(x) (x) 39 | 40 | #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ 41 | 42 | #define LITTLE_TO_HOST16(x) __builtin_bswap16(x) 43 | #define LITTLE_TO_HOST32(x) __builtin_bswap32(x) 44 | #define LITTLE_TO_HOST64(x) __builtin_bswap64(x) 45 | 46 | #define BIG_TO_HOST16(x) (x) 47 | #define BIG_TO_HOST32(x) (x) 48 | #define BIG_TO_HOST64(x) (x) 49 | 50 | #else 51 | 52 | #error "We only support big and little endian" 53 | 54 | #endif 55 | 56 | 57 | #define HOST_TO_BIG16(x) BIG_TO_HOST16(x) 58 | #define HOST_TO_BIG32(x) BIG_TO_HOST32(x) 59 | #define HOST_TO_BIG64(x) BIG_TO_HOST64(x) 60 | 61 | #define HOST_TO_LITTLE16(x) LITTLE_TO_HOST16(x) 62 | #define HOST_TO_LITTLE32(x) LITTLE_TO_HOST32(x) 63 | #define HOST_TO_LITTLE64(x) LITTLE_TO_HOST64(x) 64 | 65 | 66 | #endif 67 | 68 | -------------------------------------------------------------------------------- /include/thread-bits.h: -------------------------------------------------------------------------------- 1 | #ifndef __THREAD_BITS_H 2 | #define __THREAD_BITS_H 3 | 4 | #define KERNEL_STACK_SIZE 0x2000 5 | #define USER_TLS_SIZE 0x400000 6 | 7 | #endif 8 | 9 | -------------------------------------------------------------------------------- /include/timer.h: -------------------------------------------------------------------------------- 1 | #ifndef __TIMER_H 2 | #define __TIMER_H 3 | 4 | #include 5 | #include 6 | #include 7 | void timer_init(void); 8 | void arch_timer_tick(void); 9 | 10 | enum timer_mode { 11 | TIMER_MODE_ONESHOT, 12 | TIMER_MODE_PERIODIC, 13 | }; 14 | 15 | #define MICROSECONDS_PER_TICK 100 16 | 17 | #define ONE_SECOND 100*1000*1000 18 | 19 | struct timer { 20 | uint64_t initial_ticks; 21 | _Atomic int64_t ticks; 22 | _Atomic int level; 23 | enum timer_mode mode; 24 | void (*call)(void *); 25 | void *data; 26 | struct linkedentry node; 27 | }; 28 | 29 | void timer_add_locked(struct timer *timer, enum timer_mode mode, uint64_t ticks, 30 | void (*fn)(void *), void *data, bool locked); 31 | 32 | #define timer_add(a,b,c,d,e) timer_add_locked(a,b,c,d,e,false) 33 | #define timer_readd(a,b,c,d,e) timer_add_locked(a,b,c,d,e,true) 34 | 35 | void timer_remove(struct timer *timer); 36 | 37 | 38 | typedef long time_t; 39 | typedef long suseconds_t; 40 | struct timespec { time_t tv_sec; long tv_nsec; }; 41 | struct timeval { time_t tv_sec; suseconds_t tv_usec; }; 42 | 43 | time_t time_get_current(void); 44 | int64_t arch_time_getepoch(void); 45 | uint64_t timer_get_counter(void); 46 | #endif 47 | 48 | -------------------------------------------------------------------------------- /include/trace.h: -------------------------------------------------------------------------------- 1 | #ifndef __TRACE_H 2 | #define __TRACE_H 3 | 4 | #if CONFIG_TRACE 5 | #include 6 | #include 7 | struct trace { 8 | const char *name; 9 | struct hashelem elem; 10 | }; 11 | 12 | void __trace(struct trace *trace, const char *message, ...); 13 | void trace_enable(struct trace *trace); 14 | void trace_disable(struct trace *trace); 15 | 16 | #define TRACE(t,m,...) __trace(t, "[%s:%d]: " m "\n", (t)->name, current_thread ? current_thread->tid : 0, ##__VA_ARGS__) 17 | #define TRACE_DEFINE(tn,n) static struct trace tn = {.name=n} 18 | 19 | #else 20 | 21 | #define TRACE(...) 22 | #define TRACE_DEFINE(...) 23 | 24 | #define trace_init() 25 | #define trace_enable(x) 26 | #define trace_disable(x) 27 | 28 | #endif 29 | 30 | #define TRACE_INITIALIZER 1 31 | 32 | #endif 33 | 34 | -------------------------------------------------------------------------------- /include/worker.h: -------------------------------------------------------------------------------- 1 | #ifndef __WORKER_H 2 | #define __WORKER_H 3 | 4 | #include 5 | 6 | #define WORKER_JOIN 1 7 | #define WORKER_EXIT 2 8 | 9 | struct worker { 10 | struct thread *thread; 11 | _Atomic int flags; 12 | void *arg; 13 | _Atomic int exitcode; 14 | }; 15 | 16 | void worker_start(struct worker *worker, void (*fn)(struct worker *), void *data); 17 | void worker_exit(struct worker *w, int code); 18 | bool worker_join(struct worker *w); 19 | 20 | #define worker_arg(worker) worker->arg 21 | 22 | static inline bool worker_notjoining(struct worker *w) 23 | { 24 | return !(atomic_load(&w->flags) & WORKER_JOIN); 25 | } 26 | 27 | /* example worker thread entry function: 28 | * void thingy_entry(struct worker *worker) 29 | * { 30 | * void *arg = worker_arg(worker); 31 | * int exit_code = 0; 32 | * while(worker_notjoining(worker)) { 33 | * ... do work ... 34 | * } 35 | * worker_exit(worker, exit_code); 36 | * } */ 37 | 38 | #endif 39 | 40 | -------------------------------------------------------------------------------- /include/workqueue.h: -------------------------------------------------------------------------------- 1 | #ifndef __WORKQUEUE_H 2 | #define __WORKQUEUE_H 3 | 4 | #include 5 | #include 6 | 7 | struct workitem { 8 | void (*fn)(void *); 9 | void *arg; 10 | struct linkedentry listitem; 11 | }; 12 | 13 | struct workqueue { 14 | struct linkedlist list; 15 | }; 16 | 17 | static inline bool workqueue_empty(struct workqueue *wq) 18 | { 19 | return wq->list.count == 0; 20 | } 21 | 22 | void workqueue_create(struct workqueue *wq); 23 | void workqueue_insert(struct workqueue *wq, struct workitem *item); 24 | bool workqueue_execute(struct workqueue *wq); 25 | 26 | #endif 27 | 28 | -------------------------------------------------------------------------------- /kernel/com.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | static struct device dev; 7 | 8 | char serial_getc(void); 9 | void serial_putc(char); 10 | 11 | static ssize_t _serial_read(struct file *f, 12 | size_t off, size_t len, char *buf) 13 | { 14 | (void)off; 15 | (void)f; 16 | /* TODO: roll out nonblock to everything */ 17 | for(size_t i = 0;i 45 | static void _late_init(void) 46 | { 47 | int ret = sys_mknod("/dev/com0", S_IFCHR | 0666, makedev(dev.devnr, 0)); 48 | assert(ret == 0); 49 | } 50 | 51 | __orderedinitializer(__orderedafter(DEVICE_INITIALIZER_ORDER)) 52 | static void _serial_init(void) 53 | { 54 | spinlock_create(&serial_write_lock); 55 | init_register_late_call(&_late_init, NULL); 56 | dev_register(&dev, &serial_calls, S_IFCHR); 57 | } 58 | 59 | -------------------------------------------------------------------------------- /kernel/debug/include.mk: -------------------------------------------------------------------------------- 1 | C_SOURCES+=kernel/debug/unwind.c kernel/debug/trace.c kernel/debug/perf.c kernel/debug/ubsan.c 2 | -------------------------------------------------------------------------------- /kernel/debug/trace.c: -------------------------------------------------------------------------------- 1 | #if CONFIG_TRACE 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | static struct hash trace_hash; 10 | static bool ready = false; 11 | void __trace(struct trace *trace, const char *message, ...) 12 | { 13 | if(!ready) return; 14 | if(hash_lookup(&trace_hash, trace->name, strlen(trace->name))) { 15 | va_list args; 16 | va_start(args, message); 17 | vprintk(message, args); 18 | va_end(args); 19 | } 20 | } 21 | 22 | __orderedinitializer(TRACE_INITIALIZER) static void trace_init(void) 23 | { 24 | hash_create(&trace_hash, 0, 128); 25 | ready = true; 26 | } 27 | 28 | void trace_enable(struct trace *trace) 29 | { 30 | if(!ready) return; 31 | hash_insert(&trace_hash, trace->name, strlen(trace->name), &trace->elem, trace); 32 | } 33 | 34 | void trace_disable(struct trace *trace) 35 | { 36 | if(!ready) return; 37 | hash_delete(&trace_hash, trace->name, strlen(trace->name)); 38 | } 39 | 40 | #endif 41 | 42 | -------------------------------------------------------------------------------- /kernel/debug/unwind.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #if FEATURE_SUPPORTED_UNWIND 9 | #ifdef __clang__ 10 | __attribute__((no_sanitize("alignment"))) 11 | #else 12 | __attribute__((no_sanitize_undefined)) 13 | #endif 14 | 15 | static void __print_frame(struct frame *frame) 16 | { 17 | const struct ksymbol *sym = ksymbol_find_by_value((void *)frame->pc, true); 18 | if(sym) { 19 | uintptr_t offset = frame->pc - sym->value; 20 | printk(" %lx < %s + %lx >\n", frame->pc, sym ? sym->name : "???", offset); 21 | } 22 | } 23 | #endif 24 | static struct spinlock lock; 25 | static bool init = false; 26 | __initializer static void __init_unwind(void) 27 | { 28 | spinlock_create(&lock); 29 | init = true; 30 | } 31 | 32 | #ifdef __clang__ 33 | __attribute__((no_sanitize("alignment"))) 34 | #else 35 | __attribute__((no_sanitize_undefined)) 36 | #endif 37 | void debug_print_backtrace(void) 38 | { 39 | if(init) 40 | spinlock_acquire(&lock); 41 | #if FEATURE_SUPPORTED_UNWIND 42 | struct frame frame; 43 | frame.pc = (uintptr_t)__builtin_extract_return_addr(__builtin_return_address(0)); 44 | frame.fp = (uintptr_t)__builtin_frame_address(0); 45 | printk("STACK TRACE:\n"); 46 | while(arch_debug_unwind_frame(&frame)) { 47 | __print_frame(&frame); 48 | } 49 | #else 50 | printk("Arch '%s' does not support unwinding.\n", stringify_define(CONFIG_ARCH)); 51 | #endif 52 | if(init) 53 | spinlock_release(&lock); 54 | } 55 | 56 | -------------------------------------------------------------------------------- /kernel/device.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | struct hash blocks; 7 | struct hash chars; 8 | 9 | static _Atomic int _next_maj = 0; 10 | 11 | __orderedinitializer(DEVICE_INITIALIZER_ORDER) static void _init_devs(void) 12 | { 13 | hash_create(&blocks, 0, 32); 14 | hash_create(&chars, 0, 32); 15 | } 16 | 17 | struct device *dev_get(int type, int major) 18 | { 19 | if(S_ISCHR(type)) 20 | return hash_lookup(&chars, &major, sizeof(int)); 21 | else if(S_ISBLK(type)) 22 | return hash_lookup(&blocks, &major, sizeof(int)); 23 | panic(0, "called dev_get on non-device"); 24 | } 25 | 26 | struct file_calls *dev_get_fops(struct inode *node) 27 | { 28 | struct device *dev = dev_get(node->mode, node->major); 29 | if(dev == NULL) 30 | return NULL; 31 | return dev->calls; 32 | } 33 | 34 | int dev_register(struct device *dev, struct file_calls *calls, int type) 35 | { 36 | dev->devnr = ++_next_maj; 37 | dev->calls = calls; 38 | hash_create(&dev->attached, 0, 128); 39 | if(S_ISCHR(type)) { 40 | hash_insert(&chars, &dev->devnr, sizeof(int), &dev->elem, dev); 41 | } else if(S_ISBLK(type)) { 42 | hash_insert(&blocks, &dev->devnr, sizeof(int), &dev->elem, dev); 43 | } else { 44 | assert(0); 45 | } 46 | return dev->devnr; 47 | } 48 | 49 | void dev_attach(struct device *dev, struct attachment *at, int id, void *obj) 50 | { 51 | at->id = id; 52 | at->obj = obj; 53 | hash_insert(&dev->attached, &at->id, sizeof(int), &at->elem, at); 54 | } 55 | 56 | void *dev_get_attached(struct device *dev, int id) 57 | { 58 | struct attachment *at = hash_lookup(&dev->attached, &id, sizeof(int)); 59 | return at ? at->obj : NULL; 60 | } 61 | 62 | -------------------------------------------------------------------------------- /kernel/frame.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | static struct frame *frames; 10 | 11 | __orderedinitializer(0) static void frames_init(void) 12 | { 13 | size_t memlen = machine_get_memlen(); 14 | size_t numframes = (memlen - PHYS_MEMORY_START) / arch_mm_page_size(0); 15 | printk("[kernel]: Allocating %llu MB for page frames\n", __round_up_pow2(numframes * sizeof(struct frame)) / (1024 * 1024)); 16 | frames = (void *)mm_virtual_allocate( __round_up_pow2(numframes * sizeof(struct frame)), true); 17 | } 18 | 19 | struct frame *frame_get_from_address(uintptr_t phys) 20 | { 21 | return &frames[phys / arch_mm_page_size(0)]; 22 | } 23 | 24 | void frame_acquire(uintptr_t phys) 25 | { 26 | frames[phys / arch_mm_page_size(0)].count++; 27 | } 28 | 29 | uintptr_t frame_allocate(int level, int flags) 30 | { 31 | uintptr_t phys = mm_physical_allocate(arch_mm_page_size(level), true); 32 | struct frame *frame = frame_get_from_address(phys); 33 | assert(frame->count == 0); 34 | if(!(flags & FRAME_ZEROCOUNT)) 35 | frame->count = 1; 36 | frame->flags = flags; 37 | return phys; 38 | } 39 | 40 | long frame_release(uintptr_t phys) 41 | { 42 | struct frame *frame = &frames[phys / arch_mm_page_size(0)]; 43 | assert(frame->count > 0); 44 | long c = --frame->count; 45 | if(c == 0 && !(frame->flags & FRAME_PERSIST)) 46 | mm_physical_deallocate(phys); 47 | return c; 48 | } 49 | 50 | -------------------------------------------------------------------------------- /kernel/fs/char.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | /* default char devices */ 11 | 12 | static struct device dev; 13 | 14 | static ssize_t _char_read(struct file *file, size_t off, size_t len, char *b) 15 | { 16 | (void)off; 17 | size_t ret = 0; 18 | struct inode *node = file_get_inode(file); 19 | if(node == NULL) 20 | return -EIO; 21 | if(node->minor == 1) { 22 | memset(b, 0, len); 23 | ret = len; 24 | } else if(node->minor == 2) { 25 | ret = len; 26 | while(len >= 4) { 27 | uint32_t _r = random_u32(); 28 | char *r = (char *)&_r; 29 | for(int i=0;i<4;i++) 30 | *b++ = *r++; 31 | len -= 4; 32 | } 33 | for(unsigned int i=0;iminor != 1 ? len : 0; 52 | inode_put(node); 53 | return ret; 54 | } 55 | 56 | static struct file_calls char_calls = { 57 | .read = _char_read, 58 | .write = _char_write, 59 | .create = 0, .destroy = 0, .ioctl = 0, .poll = 0, .open = 0, .close = 0, 60 | .map = 0, .unmap = 0, 61 | }; 62 | 63 | #include 64 | static void _late_init(void) 65 | { 66 | int ret = sys_mknod("/dev/null", S_IFCHR | 0666, makedev(dev.devnr, 0)); 67 | assert(ret == 0); 68 | ret = sys_mknod("/dev/zero", S_IFCHR | 0666, makedev(dev.devnr, 1)); 69 | assert(ret == 0); 70 | ret = sys_mknod("/dev/random", S_IFCHR | 0666, makedev(dev.devnr, 2)); 71 | assert(ret == 0); 72 | ret = sys_mknod("/dev/urandom", S_IFCHR | 0666, makedev(dev.devnr, 2)); 73 | assert(ret == 0); 74 | } 75 | 76 | __orderedinitializer(__orderedafter(DEVICE_INITIALIZER_ORDER)) static void _init_char(void) 77 | { 78 | init_register_late_call(&_late_init, NULL); 79 | dev_register(&dev, &char_calls, S_IFCHR); 80 | } 81 | 82 | -------------------------------------------------------------------------------- /kernel/fs/include.mk: -------------------------------------------------------------------------------- 1 | C_SOURCES+=kernel/fs/inode.c kernel/fs/dirent.c kernel/fs/file.c kernel/fs/filesystem.c kernel/fs/path.c kernel/fs/ramfs.c kernel/fs/inoderw.c kernel/fs/link.c kernel/fs/pipe.c kernel/fs/socket.c kernel/fs/char.c kernel/fs/proc.c 2 | -------------------------------------------------------------------------------- /kernel/fs/inoderw.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | ssize_t inode_do_read_data(struct inode *ino, size_t off, size_t len, char *buf) 8 | { 9 | size_t pageoff = off % arch_mm_page_size(0); 10 | size_t pagenum = off / arch_mm_page_size(0); 11 | size_t amount = 0; 12 | 13 | if(off + len > ino->length) { 14 | if(off >= ino->length) 15 | return 0; 16 | len = ino->length - off; 17 | } 18 | 19 | while(amount < len) { 20 | size_t thisread = arch_mm_page_size(0) - pageoff; 21 | if(thisread > (len - amount)) 22 | thisread = len - amount; 23 | 24 | struct inodepage *page = inode_get_page(ino, pagenum); 25 | if(!page) { 26 | return amount; 27 | } 28 | memcpy(buf, (void *)(page->frame + PHYS_MAP_START + pageoff), thisread); 29 | inode_release_page(page); 30 | buf += thisread; 31 | pageoff = 0; 32 | pagenum++; 33 | amount += thisread; 34 | } 35 | return amount; 36 | } 37 | 38 | ssize_t inode_read_data(struct file *f, size_t off, size_t len, char *buf) 39 | { 40 | (void)f; /* TODO: use flags */ 41 | struct inode *ino = file_get_inode(f); 42 | if(ino == NULL) { 43 | return -EIO; 44 | } 45 | ssize_t ret = inode_do_read_data(ino, off, len, buf); 46 | inode_put(ino); 47 | return ret; 48 | } 49 | 50 | ssize_t inode_do_write_data(struct inode *ino, size_t off, size_t len, const char *buf) 51 | { 52 | size_t pageoff = off % arch_mm_page_size(0); 53 | size_t pagenum = off / arch_mm_page_size(0); 54 | size_t amount = 0; 55 | 56 | while(amount < len) { 57 | size_t thiswrite = arch_mm_page_size(0) - pageoff; 58 | if(thiswrite > (len - amount)) 59 | thiswrite = len - amount; 60 | 61 | struct inodepage *page = inode_get_page(ino, pagenum); 62 | if(!page) { 63 | return amount; 64 | } 65 | memcpy((void *)(page->frame + PHYS_MAP_START + pageoff), buf, thiswrite); 66 | if(thiswrite + off + amount > ino->length) { 67 | ino->length = thiswrite + off + amount; 68 | blocklist_unblock_all(&ino->readbl); 69 | inode_mark_dirty(ino); 70 | } 71 | page->flags |= INODEPAGE_DIRTY; 72 | inode_release_page(page); 73 | buf += thiswrite; 74 | pageoff = 0; 75 | pagenum++; 76 | amount += thiswrite; 77 | } 78 | return amount; 79 | } 80 | 81 | ssize_t inode_write_data(struct file *f, size_t off, size_t len, const char *buf) 82 | { 83 | (void)f; /* TODO: use flags */ 84 | struct inode *ino = file_get_inode(f); 85 | if(ino == NULL) { 86 | return -EIO; 87 | } 88 | ssize_t ret = inode_do_write_data(ino, off, len, buf); 89 | inode_put(ino); 90 | return ret; 91 | } 92 | 93 | -------------------------------------------------------------------------------- /kernel/include.mk: -------------------------------------------------------------------------------- 1 | C_SOURCES+=kernel/main.c kernel/printk.c kernel/thread.c kernel/mmu.c kernel/processor.c kernel/pm_buddy.c kernel/mutex.c kernel/spinlock.c kernel/timer.c kernel/interrupt.c kernel/slab.c kernel/panic.c kernel/syscall.c kernel/schedule.c kernel/worker.c kernel/workqueue.c kernel/ksymbol.c kernel/random.c kernel/test.c kernel/blocklist.c kernel/ksymbol_weak.c kernel/charbuffer.c kernel/queue.c kernel/kobj_lru.c kernel/mapping.c kernel/frame.c kernel/process.c kernel/elf.c kernel/device.c kernel/com.c kernel/time.c kernel/signal.c kernel/pty.c kernel/wait.c kernel/block.c kernel/synchro.c 2 | 3 | include kernel/debug/include.mk 4 | include kernel/fs/include.mk 5 | include kernel/sys/include.mk 6 | include kernel/net/include.mk 7 | 8 | -------------------------------------------------------------------------------- /kernel/interrupt.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | struct kobj kobj_exception_frame = KOBJ_DEFAULT(exception_frame); 9 | 10 | void interrupt_push_frame(struct arch_exception_frame *af, struct sigaction *action) 11 | { 12 | struct exception_frame *frame = kobj_allocate(&kobj_exception_frame); 13 | memcpy(&frame->arch, af, sizeof(*af)); 14 | memcpy(&frame->mask, ¤t_thread->sigmask, sizeof(frame->mask)); 15 | sigorset(¤t_thread->sigmask, ¤t_thread->sigmask, (sigset_t *)&action->mask); 16 | linkedlist_insert(¤t_thread->saved_exception_frames, &frame->node, frame); 17 | } 18 | 19 | struct exception_frame *interrupt_pop_frame(void) 20 | { 21 | struct exception_frame *frame = linkedlist_remove_head(¤t_thread->saved_exception_frames); 22 | memcpy(¤t_thread->sigmask, &frame->mask, sizeof(sigset_t)); 23 | return frame; 24 | } 25 | 26 | void (*_Atomic hand[MAX_INTERRUPTS][MAX_HANDLERS])(); 27 | 28 | void interrupt_init(void) 29 | { 30 | for(int i=0;i 2 | #include 3 | #include 4 | #include 5 | #include 6 | /* we can't to bounds checking with ubsan here because we'll be replacing these 7 | * symbols with real ones later, and it'll confuse the compiler */ 8 | 9 | extern size_t kernel_symbol_table_length ; 10 | extern const struct ksymbol kernel_symbol_table[]; 11 | 12 | #ifdef __clang__ 13 | __attribute__((no_sanitize("bounds"))) 14 | #else 15 | __attribute__((no_sanitize_undefined)) 16 | #endif 17 | const struct ksymbol *ksymbol_find_by_name(const char *name) 18 | { 19 | for(size_t i=0;i 26 | #ifdef __clang__ 27 | __attribute__((no_sanitize("bounds"))) 28 | #else 29 | __attribute__((no_sanitize_undefined)) 30 | #endif 31 | const struct ksymbol *ksymbol_find_by_value(void *addr, bool range) 32 | { 33 | for(size_t i=0;ivalue == (uintptr_t)addr 36 | || (range 37 | && ((uintptr_t)addr >= sym->value 38 | && (uintptr_t)addr < (sym->value + sym->size)))) { 39 | return sym; 40 | } 41 | } 42 | return NULL; 43 | } 44 | 45 | -------------------------------------------------------------------------------- /kernel/ksymbol_weak.c: -------------------------------------------------------------------------------- 1 | #include 2 | /* right, so, here's some linking magic. 3 | * basically, the kernel references these two symbols in places. 4 | * However, due to the 2-stage linking process, these symbols aren't 5 | * actually defined until the second link, when it links with the generated 6 | * symbol table file. So we need to define them as weak symbols here so that 7 | * our code can link for stage 1. */ 8 | #pragma weak kernel_symbol_table 9 | #pragma weak kernel_symbol_table_length 10 | __attribute__((weak,used)) size_t kernel_symbol_table_length = 0; 11 | const struct ksymbol kernel_symbol_table[] __attribute__ ((weak,used)) = {{0,0,0}}; 12 | 13 | 14 | -------------------------------------------------------------------------------- /kernel/mutex.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | static inline bool _spinlock_first(struct mutex *mutex) 10 | { 11 | /* improve performance with an optimistic view that the mutex 12 | * might get unlocked soon by a thread on a different CPU */ 13 | for(int i=0;i<40;i++) { 14 | int exp = 0; 15 | if(atomic_compare_exchange_weak(&mutex->lock, &exp, 1)) 16 | return true; 17 | /* ...and if that doesn't look like it's working, maybe 18 | * it will get unlocked soon by a thread on the same CPU, 19 | * so we can get away with rescheduling until it unlocks it */ 20 | if(i > 30) 21 | schedule(); 22 | } 23 | /* ...neither of those worked, so indicate that we couldn't grab 24 | * the mutex by spinning, and block. */ 25 | return false; 26 | } 27 | 28 | void mutex_acquire(struct mutex *mutex) 29 | { 30 | #if CONFIG_DEBUG 31 | assert(!current_thread || mutex->owner != current_thread); 32 | #endif 33 | if(!current_thread) 34 | return (void)atomic_fetch_add(&mutex->lock, 1); 35 | /* TODO: what if a fault happens while we're holding a lock? */ 36 | //assert(current_thread->held_spinlocks == 0); 37 | if(!_spinlock_first(mutex)) { 38 | struct blockpoint bp; 39 | blockpoint_create(&bp, BLOCK_UNINTERRUPT, 0); 40 | 41 | blockpoint_startblock(&mutex->wait, &bp); 42 | if(atomic_fetch_add(&mutex->lock, 1) > 0) { 43 | schedule(); 44 | } 45 | enum block_result res = blockpoint_cleanup(&bp); 46 | assert(res == BLOCK_RESULT_UNBLOCKED || res == BLOCK_RESULT_BLOCKED); 47 | } 48 | #if CONFIG_DEBUG 49 | assert(mutex->owner == NULL); 50 | mutex->owner = current_thread; 51 | #endif 52 | } 53 | 54 | void mutex_release(struct mutex *mutex) 55 | { 56 | #if CONFIG_DEBUG 57 | assert(!current_thread || mutex->owner == current_thread); 58 | mutex->owner = NULL; 59 | #endif 60 | if(!current_thread) 61 | return (void)atomic_fetch_sub(&mutex->lock, 1); 62 | if(atomic_fetch_sub(&mutex->lock, 1) != 1) { 63 | blocklist_unblock_one(&mutex->wait); 64 | } 65 | } 66 | 67 | void mutex_create(struct mutex *mutex) 68 | { 69 | mutex->lock = ATOMIC_VAR_INIT(0); 70 | blocklist_create(&mutex->wait); 71 | } 72 | 73 | -------------------------------------------------------------------------------- /kernel/net/ethernet.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | struct ethernet_frame { 6 | uint8_t dest[6]; 7 | uint8_t src[6]; 8 | uint16_t type; 9 | uint8_t data[]; 10 | } __attribute__((packed)); 11 | 12 | enum { 13 | ETHERTYPE_IPV6 = 0x86DD, 14 | }; 15 | 16 | void net_ethernet_drop(struct packet *packet) 17 | { 18 | kobj_putref(packet); 19 | } 20 | 21 | void net_ethernet_receive(struct packet *packet) 22 | { 23 | struct ethernet_frame *ef = packet->data; 24 | packet->network_header = ef->data; 25 | if((ef->dest[0] & 1) //multicast 26 | || (!memcmp(ef->dest, packet->origin->physaddr.octets, 6))) { 27 | switch(BIG_TO_HOST16(ef->type)) { 28 | case ETHERTYPE_IPV6: 29 | ipv6_receive(packet, (struct ipv6_header *)ef->data); 30 | break; 31 | default: 32 | net_ethernet_drop(packet); 33 | } 34 | } else { 35 | net_ethernet_drop(packet); 36 | } 37 | } 38 | 39 | void net_ethernet_send(struct packet *packet, int prot, struct physical_address *addr) 40 | { 41 | struct ethernet_frame *ef = packet->data; 42 | memcpy(ef->dest, addr->octets, 6); 43 | memcpy(ef->src, packet->sender->physaddr.octets, 6); 44 | ef->type = HOST_TO_BIG16(prot); 45 | packet->sender->driver->send(packet->sender, packet); 46 | } 47 | 48 | -------------------------------------------------------------------------------- /kernel/net/include.mk: -------------------------------------------------------------------------------- 1 | C_SOURCES+=kernel/net/unix.c kernel/net/nic.c kernel/net/ethernet.c kernel/net/ipv6.c kernel/net/icmp6.c kernel/net/packet.c kernel/net/udp.c kernel/net/network.c kernel/net/ipv6rawsock.c kernel/net/tcp.c 2 | -------------------------------------------------------------------------------- /kernel/net/network.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | struct nic; 6 | static int (*senders[MAX_AF + 1])(const struct sockaddr *, struct nic *, const void *, size_t, const void *, size_t, int, int) = { 7 | [AF_INET6] = ipv6_network_send, 8 | }; 9 | 10 | static int protocol_map[MAX_AF + 1][MAX_PROT] = { 11 | [AF_INET6] = { [PROT_UDP] = 17, [PROT_TCP] = 6 }, 12 | }; 13 | 14 | #include 15 | int net_network_send(struct socket *sock, const struct sockaddr *dest, const void *trheader, size_t thlen, const void *msg, size_t mlen, int prot, int checksum_offset) 16 | { 17 | if(senders[dest->sa_family]) 18 | return senders[dest->sa_family](dest, sock->nic ? kobj_getref(sock->nic) : NULL, trheader, thlen, msg, mlen, protocol_map[dest->sa_family][prot], checksum_offset); 19 | return -ENOTSUP; 20 | } 21 | 22 | -------------------------------------------------------------------------------- /kernel/net/packet.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | static struct linkedlist buffers; 9 | 10 | static void _packet_put(void *o) 11 | { 12 | struct packet *packet = o; 13 | if(packet->data) { 14 | linkedlist_insert(&buffers, (struct linkedentry *)packet->data, packet->data); 15 | } 16 | if(packet->origin) { 17 | kobj_putref(packet->origin); 18 | } 19 | if(packet->sender) { 20 | kobj_putref(packet->sender); 21 | } 22 | } 23 | 24 | static void _packet_init(void *o) 25 | { 26 | struct packet *p = o; 27 | p->origin = p->sender = NULL; 28 | memset(&p->saddr, 0, sizeof(p->saddr)); 29 | memset(&p->daddr, 0, sizeof(p->daddr)); 30 | } 31 | 32 | struct kobj kobj_packet = { 33 | KOBJ_DEFAULT_ELEM(packet), 34 | .init = _packet_init, .create = NULL, 35 | .put = _packet_put, .destroy = NULL, 36 | }; 37 | 38 | __initializer static void _init_buffers(void) 39 | { 40 | linkedlist_create(&buffers, 0); 41 | } 42 | 43 | void *net_packet_buffer_allocate(void) 44 | { 45 | void *buffer = linkedlist_remove_head(&buffers); 46 | return buffer == NULL ? (void *)mm_virtual_allocate(0x1000, false) : buffer; 47 | } 48 | 49 | struct packet *packet_duplicate(const struct packet *src) 50 | { 51 | struct packet *packet = kobj_allocate(&kobj_packet); 52 | memcpy(packet, src, sizeof(*packet)); 53 | if(packet->origin) 54 | kobj_getref(packet->origin); 55 | if(packet->sender) 56 | kobj_getref(packet->sender); 57 | packet->data = net_packet_buffer_allocate(); 58 | memcpy(packet->data, src->data, src->length); 59 | 60 | return packet; 61 | } 62 | 63 | -------------------------------------------------------------------------------- /kernel/panic.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | noreturn void panic(int flags, const char *fmt, ...) 9 | { 10 | arch_interrupt_set(0); 11 | arch_panic_begin(); 12 | (void)flags; 13 | /* clear interrupts */ 14 | va_list args; 15 | va_start(args, fmt); 16 | printk("panic [tid %ld, cpu %d] - ", current_thread ? current_thread->tid : 0, arch_processor_current_id()); 17 | vprintk(fmt, args); 18 | printk("\n"); 19 | /*if(current_thread) 20 | mm_print_context(current_thread->ctx); 21 | else 22 | mm_print_context(&kernel_context);*/ 23 | #if FEATURE_SUPPORTED_UNWIND 24 | debug_print_backtrace(); 25 | #endif 26 | for(;;); 27 | } 28 | 29 | -------------------------------------------------------------------------------- /kernel/processor.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | extern int initial_boot_stack; 15 | struct processor plist[MAX_PROCESSORS]; 16 | #include 17 | 18 | void processor_add_thread(struct processor *proc, struct thread *thread) 19 | { 20 | if(thread == &proc->idle_thread) 21 | return; 22 | /* NOTE: set the thread's processor first. If we were to schedule 23 | * before doing so, but after we've added the thread to the queue, 24 | * we could have trouble (thread->processor would be null in schedule()). 25 | */ 26 | thread->processor = proc; 27 | if(!(atomic_fetch_or(&thread->flags, THREAD_ONQUEUE) & THREAD_ONQUEUE)) { 28 | priqueue_insert(&proc->runqueue, &thread->runqueue_node, thread, thread_current_priority(thread)); 29 | } 30 | } 31 | 32 | void processor_create(int id, int flags) 33 | { 34 | if(id >= MAX_PROCESSORS) { 35 | printk("warning - refusing to initialize processor %d. Too many processors!\n", id); 36 | return; 37 | } 38 | struct processor *proc = &plist[id]; 39 | proc->flags = flags | PROCESSOR_PRESENT; 40 | proc->preempt_disable = 0; 41 | proc->id = id; 42 | 43 | /* add one, since we're passing a count */ 44 | priqueue_create(&proc->runqueue, MAX_THREAD_PRIORITY + 1); 45 | workqueue_create(&proc->workqueue); 46 | spinlock_create(&proc->schedlock); 47 | proc->running = &proc->idle_thread; 48 | proc->idle_thread.state = THREADSTATE_RUNNING; 49 | if(flags & PROCESSOR_UP) 50 | proc->idle_stack = (void *)&initial_boot_stack; 51 | else 52 | proc->idle_stack = (void *)mm_virtual_allocate(KERNEL_STACK_SIZE, false); 53 | } 54 | 55 | void processor_start_secondaries(void) 56 | { 57 | for(int i=0;itid); 73 | arch_interrupt_set(1); 74 | 75 | kernel_idle_work(); 76 | } 77 | 78 | -------------------------------------------------------------------------------- /kernel/random.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | /* right, so this is just a temporary PRNG. We should probably 5 | * have a real RNG at some point. */ 6 | 7 | typedef struct { uint64_t state; uint64_t inc; } pcg32_random_t; 8 | 9 | static pcg32_random_t __state; 10 | 11 | static uint32_t pcg32_random_r(pcg32_random_t* rng) 12 | { 13 | uint64_t oldstate = rng->state; 14 | rng->state = oldstate * 6364136223846793005ULL + (rng->inc|1); 15 | uint32_t xorshifted = ((oldstate >> 18u) ^ oldstate) >> 27u; 16 | uint32_t rot = oldstate >> 59u; 17 | return (xorshifted >> rot) | (xorshifted << ((-rot) & 31)); 18 | } 19 | 20 | /* ...and this isn't thread-safe, but whatever */ 21 | uint32_t random_u32(void) 22 | { 23 | return pcg32_random_r(&__state); 24 | } 25 | 26 | __initializer static void random_init(void) 27 | { 28 | /* yeah, I dunno. */ 29 | #if FEATURE_SUPPORTED_CYCLE_COUNT 30 | __state.state = arch_processor_get_cycle_count();; 31 | #endif 32 | __state.state = arch_processor_get_nanoseconds(); 33 | __state.inc = 64;// arch_processor_get_nanoseconds(); 34 | pcg32_random_r(&__state); 35 | } 36 | 37 | -------------------------------------------------------------------------------- /kernel/spinlock.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | void spinlock_create(struct spinlock *lock) 7 | { 8 | memset(lock, 0, sizeof(*lock)); 9 | } 10 | 11 | void spinlock_acquire(struct spinlock *lock) 12 | { 13 | int interrupt = arch_interrupt_set(0); 14 | if(current_thread && current_thread->processor) { 15 | int r = current_thread->processor->preempt_disable++; 16 | assert(r >= 0); 17 | } 18 | #if CONFIG_DEBUG 19 | int timeout = 10000000; 20 | #endif 21 | while(atomic_flag_test_and_set(&lock->lock)) { 22 | #if CONFIG_DEBUG 23 | if(--timeout == 0) { 24 | panic(0, "possible deadlock"); 25 | } 26 | #endif 27 | asm("pause"); //TODO: arch-dep 28 | } 29 | #if CONFIG_DEBUG 30 | if(current_thread) 31 | current_thread->held_spinlocks++; 32 | #endif 33 | lock->interrupt = interrupt; 34 | } 35 | 36 | void spinlock_release(struct spinlock *lock) 37 | { 38 | int interrupt = lock->interrupt; 39 | #if CONFIG_DEBUG 40 | if(current_thread) 41 | current_thread->held_spinlocks--; 42 | #endif 43 | atomic_flag_clear(&lock->lock); 44 | if(current_thread && current_thread->processor) { 45 | int r = current_thread->processor->preempt_disable--; 46 | assert(r > 0); 47 | } 48 | arch_interrupt_set(interrupt); 49 | } 50 | 51 | -------------------------------------------------------------------------------- /kernel/syms.c.begin: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | const struct ksymbol kernel_symbol_table[] = { 4 | 5 | -------------------------------------------------------------------------------- /kernel/syms.c.end: -------------------------------------------------------------------------------- 1 | 2 | }; 3 | 4 | -------------------------------------------------------------------------------- /kernel/synchro.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | void sleepflag_create(struct sleepflag *s) 5 | { 6 | blocklist_create(&s->bl); 7 | s->flag = 1; 8 | } 9 | 10 | void sleepflag_sleep(struct sleepflag *s) 11 | { 12 | if(s->flag >= 2) { 13 | s->flag--; 14 | return; 15 | } 16 | assert(s->flag >= 0); 17 | struct blockpoint bp; 18 | blockpoint_create(&bp, 0, 0); 19 | blockpoint_startblock(&s->bl, &bp); 20 | if(--s->flag == 0) { 21 | schedule(); 22 | } 23 | enum block_result res = blockpoint_cleanup(&bp); 24 | if(res != BLOCK_RESULT_UNBLOCKED && res != BLOCK_RESULT_BLOCKED) { 25 | s->flag++; 26 | } 27 | } 28 | 29 | void sleepflag_wake(struct sleepflag *s) 30 | { 31 | s->flag++; 32 | blocklist_unblock_all(&s->bl); 33 | } 34 | 35 | -------------------------------------------------------------------------------- /kernel/sys/ctl.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | sysret_t sys_fcntl(int fd, int cmd, long arg) 8 | { 9 | struct file *file = process_get_file(fd); 10 | if(!file) 11 | return -EBADF; 12 | 13 | long ret = 0; 14 | switch(cmd) { 15 | case F_GETFD: 16 | ret = current_thread->process->files[fd].flags; 17 | break; 18 | case F_SETFD: 19 | current_thread->process->files[fd].flags = arg; 20 | break; 21 | case F_SETFL: 22 | file->flags = (arg & ~(F_READ | F_WRITE)) | (file->flags & (F_READ | F_WRITE)); 23 | break; 24 | case F_GETFL: 25 | ret = file->flags; 26 | break; 27 | case F_DUPFD: 28 | ret = process_allocate_fd(file, (int)arg); 29 | if(ret >= 0) 30 | process_copy_proc_fd(current_thread->process, current_thread->process, fd, ret); 31 | break; 32 | case F_SETOWN: case F_GETOWN: break; 33 | 34 | /* for now, pretend we can lock */ 35 | case F_GETLK: { 36 | struct flock *flock = (void *)arg; 37 | flock->l_type = F_UNLCK; 38 | } break; 39 | 40 | case F_SETLKW: case F_SETLK: break; 41 | default: 42 | ret = -EINVAL; 43 | } 44 | kobj_putref(file); 45 | return ret; 46 | } 47 | 48 | sysret_t sys_ioctl(int fd, int cmd, long arg) 49 | { 50 | struct file *file = process_get_file(fd); 51 | if(!file) 52 | return -EBADF; 53 | long ret = -ENOTSUP; 54 | if(file->ops->ioctl) 55 | ret = file->ops->ioctl(file, cmd & 0xFFFFFFFF /* TODO */, arg); 56 | kobj_putref(file); 57 | return ret; 58 | } 59 | 60 | -------------------------------------------------------------------------------- /kernel/sys/include.mk: -------------------------------------------------------------------------------- 1 | C_SOURCES+=kernel/sys/fork.c kernel/sys/open.c \ 2 | kernel/sys/map.c kernel/sys/execve.c \ 3 | kernel/sys/proc.c kernel/sys/ctl.c \ 4 | kernel/sys/select.c kernel/sys/time.c \ 5 | kernel/sys/path.c kernel/sys/sync.c \ 6 | kernel/sys/thread.c kernel/sys/futex.c \ 7 | kernel/sys/info.c kernel/sys/process.c \ 8 | kernel/sys/poll.c 9 | 10 | -------------------------------------------------------------------------------- /kernel/sys/info.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | struct utsname 4 | { 5 | char sysname[65]; 6 | char nodename[65]; 7 | char release[65]; 8 | char version[65]; 9 | char machine[65]; 10 | char domainname[65]; 11 | }; 12 | 13 | int sys_uname(struct utsname *buf) 14 | { 15 | memset(buf, 0, sizeof(*buf)); 16 | strncpy(buf->sysname, "SeaOS", 64); 17 | strncpy(buf->nodename, "something", 64); 18 | strncpy(buf->release, "0.4", 64); 19 | strncpy(buf->version, "SMP #1", 64); 20 | strncpy(buf->machine, "x86_64", 64); //TODO 21 | 22 | return 0; 23 | } 24 | 25 | -------------------------------------------------------------------------------- /kernel/sys/process.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int sys_setsid(void) 7 | { 8 | if(current_thread->process->pgroupid == current_thread->process->pid) 9 | return -EPERM; 10 | 11 | current_thread->process->seshid = current_thread->process->seshid; 12 | current_thread->process->pgroupid = current_thread->process->pid; 13 | return 0; 14 | } 15 | 16 | sysret_t sys_setgroups(size_t size, const int *list) 17 | { 18 | (void)size; 19 | (void)list; 20 | // TODO 21 | return 0; 22 | } 23 | 24 | int sys_setpgid(int pid, int pg) 25 | { 26 | struct process *proc; 27 | if(pid == 0) { 28 | proc = kobj_getref(current_thread->process); 29 | } else { 30 | proc = process_get_by_pid(pid); 31 | } 32 | if(!proc) 33 | return -ESRCH; 34 | if(proc->pid == proc->seshid) { 35 | kobj_putref(proc); 36 | return -EPERM; 37 | } 38 | /* TODO: security checks */ 39 | if(pg == 0) { 40 | proc->pgroupid = proc->pid; 41 | } else { 42 | proc->pgroupid = pg; 43 | } 44 | kobj_putref(proc); 45 | return 0; 46 | } 47 | 48 | -------------------------------------------------------------------------------- /kernel/sys/select.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | /* TODO: this implementation will block if given a bad FD */ 15 | sysret_t sys_pselect(int nfds, fd_set *readfds, fd_set *writefds, 16 | fd_set *errfds, const struct timespec *timeout, const sigset_t *sigmask) 17 | { 18 | size_t alloc = __round_up_pow2(nfds * sizeof(struct pollfd)); 19 | struct pollfd *pollfds = (void *)mm_virtual_allocate(alloc < MM_BUDDY_MIN_SIZE ? MM_BUDDY_MIN_SIZE : alloc, true); 20 | 21 | for(int i=0;ifd = i; 28 | if(r) p->events |= POLLIN; 29 | if(w) p->events |= POLLOUT; 30 | if(e) p->events |= POLLERR; 31 | } else { 32 | p->fd = -1; 33 | } 34 | } 35 | 36 | sysret_t ret = sys_ppoll(pollfds, nfds, timeout, sigmask); 37 | 38 | if(ret != -EINTR) { 39 | for(int i=0;ifd >= 0) { 43 | if(p->revents & POLLNVAL) { 44 | ret = -EBADF; 45 | } else { 46 | if(readfds) { 47 | FD_CLR(i, readfds); 48 | if((p->revents & POLLIN) || (p->revents & POLLHUP)) 49 | FD_SET(i, readfds); 50 | } 51 | if(writefds) { 52 | FD_CLR(i, writefds); 53 | if((p->revents & POLLOUT) || (p->revents & POLLHUP)) 54 | FD_SET(i, writefds); 55 | } 56 | if(errfds) { 57 | FD_CLR(i, errfds); 58 | if(p->revents & POLLERR) 59 | FD_SET(i, errfds); 60 | } 61 | } 62 | } 63 | } 64 | } 65 | 66 | mm_virtual_deallocate((uintptr_t)pollfds); 67 | return ret; 68 | } 69 | 70 | sysret_t sys_select(int nfds, fd_set *readfds, fd_set *writefds, 71 | fd_set *errfds, struct timeval *timeout) 72 | { 73 | struct timespec time; 74 | time.tv_sec = timeout ? timeout->tv_sec : 0; 75 | time.tv_nsec = timeout ? timeout->tv_usec * 1000 : 0; 76 | 77 | time_t __time = timeout ? timeout->tv_sec * 1000000000 + timeout->tv_usec * 1000 : 0; 78 | time_t end_time = __time + time_get_current(); 79 | sysret_t ret = sys_pselect(nfds, readfds, writefds, errfds, timeout ? &time : NULL, NULL); 80 | time_t rem_time = end_time - time_get_current(); 81 | if(rem_time < 0) rem_time = 0; 82 | 83 | if(timeout) { 84 | timeout->tv_sec = rem_time / 1000000000; 85 | timeout->tv_usec = rem_time % 1000000000; 86 | } 87 | return ret; 88 | } 89 | 90 | -------------------------------------------------------------------------------- /kernel/sys/sync.c: -------------------------------------------------------------------------------- 1 | 2 | sysret_t sys_fsync(int fd) 3 | { 4 | (void)fd; 5 | return 0; 6 | } 7 | 8 | sysret_t sys_sync(void) 9 | { 10 | return 0; 11 | } 12 | 13 | -------------------------------------------------------------------------------- /kernel/sys/thread.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | -------------------------------------------------------------------------------- /kernel/test.c: -------------------------------------------------------------------------------- 1 | 2 | #if CONFIG_RUN_TESTS 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | void perf_print_report(void); 14 | extern unsigned char serial_getc(void); 15 | static void __echo_entry(struct worker *worker) 16 | { 17 | (void)worker; 18 | printk("Starting echo service %ld!\n", current_thread->tid); 19 | for(;;) { 20 | char c = serial_getc(); 21 | if(c == '`') { 22 | printk("==TESTS PASSED==\n"); 23 | arch_processor_reset(); 24 | #if CONFIG_PERF_FUNCTIONS 25 | } else if(c == 'p') { 26 | printk("PERF REPORT\n"); 27 | perf_print_report(); 28 | #endif 29 | } else { 30 | printk("%c", c); 31 | if(c == '\r') 32 | printk("\n"); 33 | } 34 | } 35 | } 36 | 37 | #include 38 | void _thread_hello(void) 39 | { 40 | int r = sys_execve("/test", NULL, NULL); 41 | printk("exec returned %d\n", r); 42 | for(;;); 43 | } 44 | 45 | #include 46 | static void _thread_entry(void *arg) 47 | { 48 | (void)arg; 49 | printk("Test!\n"); 50 | sys_fork((uintptr_t)&_thread_hello, 0); 51 | for(;;); 52 | } 53 | 54 | struct worker echo; 55 | void test_late(void) 56 | { 57 | worker_start(&echo, __echo_entry, NULL); 58 | sys_fork((uintptr_t)&_thread_entry, 0); 59 | } 60 | 61 | void test_secondaries(void) 62 | { 63 | } 64 | 65 | #endif 66 | 67 | -------------------------------------------------------------------------------- /kernel/time.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | time_t time_get_current(void) 5 | { 6 | return arch_processor_get_nanoseconds(); 7 | } 8 | 9 | -------------------------------------------------------------------------------- /kernel/worker.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | void worker_start(struct worker *worker, void (*fn)(struct worker *), void *data) 7 | { 8 | worker->thread = kobj_allocate(&kobj_thread); 9 | worker->flags = 0; 10 | worker->arg = data; 11 | arch_thread_create(worker->thread, (uintptr_t)fn, worker); 12 | struct processor *proc = processor_get_current(); 13 | worker->thread->state = THREADSTATE_RUNNING; 14 | /* inc refs for adding it to the processor */ 15 | kobj_getref(worker->thread); 16 | processor_add_thread(proc, worker->thread); 17 | processor_release(proc); 18 | } 19 | 20 | void worker_exit(struct worker *w, int code) 21 | { 22 | w->exitcode = code; 23 | struct thread *thread = w->thread; 24 | atomic_fetch_or(&w->flags, WORKER_EXIT); 25 | kobj_putref(thread); 26 | thread_exit(thread); 27 | } 28 | 29 | bool worker_join(struct worker *w) 30 | { 31 | atomic_fetch_or(&w->flags, WORKER_JOIN); 32 | return atomic_load(&w->flags) & WORKER_EXIT; 33 | } 34 | 35 | -------------------------------------------------------------------------------- /kernel/workqueue.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | /* NOTE: we need to disable interrupts through 7 | * these functions since we may want to enqueue 8 | * work from inside and interrupt handler, which 9 | * could lead to a deadlock. */ 10 | 11 | void workqueue_create(struct workqueue *wq) 12 | { 13 | linkedlist_create(&wq->list, 0); 14 | } 15 | 16 | void workqueue_insert(struct workqueue *wq, struct workitem *item) 17 | { 18 | int old = arch_interrupt_set(0); 19 | linkedlist_insert(&wq->list, &item->listitem, item); 20 | arch_interrupt_set(old); 21 | } 22 | 23 | bool workqueue_execute(struct workqueue *wq) 24 | { 25 | int old = arch_interrupt_set(0); 26 | struct workitem *item = linkedlist_remove_head(&wq->list); 27 | arch_interrupt_set(old); 28 | 29 | if(item) { 30 | item->fn(item->arg); 31 | return true; 32 | } 33 | return false; 34 | } 35 | 36 | -------------------------------------------------------------------------------- /lib/ds/heap.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #define DEBUG_HEAP 1 7 | 8 | void heap_create(struct heap *heap, int (*comp)(void *, void *), enum heap_type type) 9 | { 10 | spinlock_create(&heap->lock); 11 | heap->count = 0; 12 | heap->type = type; 13 | heap->compare = comp; 14 | heap->end = heap->root = NULL; 15 | } 16 | -------------------------------------------------------------------------------- /lib/ds/include.mk: -------------------------------------------------------------------------------- 1 | C_SOURCES+=lib/ds/stack.c lib/ds/linkedlist.c lib/ds/hash.c lib/ds/qsort.c lib/ds/heap.c 2 | -------------------------------------------------------------------------------- /lib/ds/qsort.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | static void swap(void *base, size_t size, int a, int b) 6 | { 7 | char data[size]; 8 | memcpy(data, (void *)((uintptr_t)base + a * size), size); 9 | memcpy((void *)((uintptr_t)base + a * size), (void *)((uintptr_t)base + b * size), size); 10 | memcpy((void *)((uintptr_t)base + b * size), data, size); 11 | 12 | } 13 | 14 | void qsort (void* base, size_t num, size_t size, int (*compar)(const void*,const void*)) 15 | { 16 | if(num <= 1) 17 | return; 18 | int pivot = random_u32() % num; 19 | 20 | size_t part = 0; 21 | swap(base, size, pivot, 0); 22 | for(size_t i=1;i 0) 31 | qsort(base, part, size, compar); 32 | if(num > part) 33 | qsort((void *)((uintptr_t)base + size * (part + 1)), (num - part) - 1, size, compar); 34 | } 35 | 36 | -------------------------------------------------------------------------------- /lib/ds/stack.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | static struct stack_elem __sentry; 7 | 8 | void stack_create(struct stack *stack, int flags) 9 | { 10 | spinlock_create(&stack->lock); 11 | memset(&__sentry, 0, sizeof(__sentry)); 12 | stack->top = &__sentry; 13 | stack->flags = flags; 14 | } 15 | 16 | void stack_push(struct stack *stack, struct stack_elem *elem, void *obj) 17 | { 18 | if(!(stack->flags & STACK_LOCKLESS)) 19 | spinlock_acquire(&stack->lock); 20 | 21 | stack->top->next = elem; 22 | elem->obj = obj; 23 | elem->next = &__sentry; 24 | elem->prev = stack->top; 25 | stack->top = elem; 26 | stack->count++; 27 | 28 | if(!(stack->flags & STACK_LOCKLESS)) 29 | spinlock_release(&stack->lock); 30 | } 31 | 32 | void stack_delete(struct stack *stack, struct stack_elem *elem) 33 | { 34 | if(!(stack->flags & STACK_LOCKLESS)) 35 | spinlock_acquire(&stack->lock); 36 | 37 | assert(stack->count > 0); 38 | elem->prev->next = elem->next; 39 | elem->next->prev = elem->prev; 40 | if(stack->top == elem) 41 | stack->top = elem->prev; 42 | stack->count--; 43 | 44 | if(!(stack->flags & STACK_LOCKLESS)) 45 | spinlock_release(&stack->lock); 46 | } 47 | 48 | void *stack_pop(struct stack *stack) 49 | { 50 | if(!(stack->flags & STACK_LOCKLESS)) 51 | spinlock_acquire(&stack->lock); 52 | 53 | if(!stack->count) { 54 | if(!(stack->flags & STACK_LOCKLESS)) 55 | spinlock_release(&stack->lock); 56 | return NULL; 57 | } 58 | void *obj = stack->top->obj; 59 | stack->top->prev->next = &__sentry; 60 | stack->top = stack->top->prev; 61 | stack->count--; 62 | 63 | if(!(stack->flags & STACK_LOCKLESS)) 64 | spinlock_release(&stack->lock); 65 | return obj; 66 | } 67 | 68 | -------------------------------------------------------------------------------- /lib/fdt/LICENSE: -------------------------------------------------------------------------------- 1 | LK uses the BSD version of the libfdt license. 2 | -------------------------------------------------------------------------------- /lib/fdt/Makefile.libfdt: -------------------------------------------------------------------------------- 1 | # Makefile.libfdt 2 | # 3 | # This is not a complete Makefile of itself. Instead, it is designed to 4 | # be easily embeddable into other systems of Makefiles. 5 | # 6 | LIBFDT_soname = libfdt.$(SHAREDLIB_EXT).1 7 | LIBFDT_INCLUDES = fdt.h libfdt.h libfdt_env.h 8 | LIBFDT_VERSION = version.lds 9 | LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c fdt_empty_tree.c \ 10 | fdt_addresses.c 11 | LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o) 12 | -------------------------------------------------------------------------------- /lib/fdt/TODO: -------------------------------------------------------------------------------- 1 | - Tree traversal functions 2 | - Graft function 3 | - Complete libfdt.h documenting comments 4 | -------------------------------------------------------------------------------- /lib/fdt/include.mk: -------------------------------------------------------------------------------- 1 | include lib/fdt/Makefile.libfdt 2 | MAKEFILES+=lib/fdt/Makefile.libfdt 3 | C_SOURCES+=$(addprefix lib/fdt/, $(LIBFDT_SRCS)) 4 | CFLAGS+=-Ilib/fdt/include 5 | -------------------------------------------------------------------------------- /lib/fdt/version.lds: -------------------------------------------------------------------------------- 1 | LIBFDT_1.2 { 2 | global: 3 | fdt_next_node; 4 | fdt_check_header; 5 | fdt_move; 6 | fdt_string; 7 | fdt_num_mem_rsv; 8 | fdt_get_mem_rsv; 9 | fdt_subnode_offset_namelen; 10 | fdt_subnode_offset; 11 | fdt_path_offset_namelen; 12 | fdt_path_offset; 13 | fdt_get_name; 14 | fdt_get_property_namelen; 15 | fdt_get_property; 16 | fdt_getprop_namelen; 17 | fdt_getprop; 18 | fdt_get_phandle; 19 | fdt_get_alias_namelen; 20 | fdt_get_alias; 21 | fdt_get_path; 22 | fdt_supernode_atdepth_offset; 23 | fdt_node_depth; 24 | fdt_parent_offset; 25 | fdt_node_offset_by_prop_value; 26 | fdt_node_offset_by_phandle; 27 | fdt_node_check_compatible; 28 | fdt_node_offset_by_compatible; 29 | fdt_setprop_inplace; 30 | fdt_nop_property; 31 | fdt_nop_node; 32 | fdt_create; 33 | fdt_add_reservemap_entry; 34 | fdt_finish_reservemap; 35 | fdt_begin_node; 36 | fdt_property; 37 | fdt_end_node; 38 | fdt_finish; 39 | fdt_open_into; 40 | fdt_pack; 41 | fdt_add_mem_rsv; 42 | fdt_del_mem_rsv; 43 | fdt_set_name; 44 | fdt_setprop; 45 | fdt_delprop; 46 | fdt_add_subnode_namelen; 47 | fdt_add_subnode; 48 | fdt_del_node; 49 | fdt_strerror; 50 | fdt_offset_ptr; 51 | fdt_next_tag; 52 | fdt_appendprop; 53 | fdt_create_empty_tree; 54 | fdt_first_property_offset; 55 | fdt_get_property_by_offset; 56 | fdt_getprop_by_offset; 57 | fdt_next_property_offset; 58 | fdt_first_subnode; 59 | fdt_next_subnode; 60 | 61 | local: 62 | *; 63 | }; 64 | -------------------------------------------------------------------------------- /lib/string/include.mk: -------------------------------------------------------------------------------- 1 | C_SOURCES+=lib/string/mem.c 2 | -------------------------------------------------------------------------------- /machine/pc/devices/keyboard.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | static struct device dev; 13 | 14 | static struct charbuffer keybuf; 15 | 16 | static ssize_t _read(struct file *file, size_t off, size_t len, char *buf) 17 | { 18 | (void)off; 19 | (void)file; 20 | return charbuffer_read(&keybuf, buf, len, ((file->flags & O_NONBLOCK) ? CHARBUFFER_DO_NONBLOCK : 0) | CHARBUFFER_DO_ANY); 21 | } 22 | 23 | static bool _poll(struct file *file, struct pollpoint *point) 24 | { 25 | (void)file; 26 | point->events &= POLLIN; 27 | if(point->events & POLLIN) { 28 | blockpoint_startblock(&keybuf.wait_read, &point->bps[POLL_BLOCK_READ]); 29 | if(charbuffer_pending(&keybuf)) { 30 | *point->revents |= POLLIN; 31 | return true; 32 | } 33 | } 34 | return false; 35 | } 36 | 37 | static struct file_calls keyboard_ops = { 38 | .open = NULL, 39 | .close = NULL, 40 | .create = NULL, 41 | .destroy = NULL, 42 | .map = NULL, 43 | .unmap = NULL, 44 | .ioctl = NULL, 45 | .read = _read, 46 | .write = NULL, 47 | .poll = _poll, 48 | }; 49 | 50 | void flush_port(void) 51 | { 52 | unsigned temp; 53 | do 54 | { 55 | temp = x86_64_inb(0x64); 56 | if((temp & 0x01) != 0) 57 | { 58 | (void)x86_64_inb(0x60); 59 | continue; 60 | } 61 | } while((temp & 0x02) != 0); 62 | } 63 | 64 | static void _key_interrupt(int v, int flags) 65 | { 66 | (void)v; 67 | (void)flags; 68 | unsigned char tmp; 69 | do { 70 | tmp = x86_64_inb(0x64); 71 | if(tmp & 1) { 72 | unsigned char scan = x86_64_inb(0x60); 73 | charbuffer_write(&keybuf, (char *)&scan, 1, CHARBUFFER_DO_NONBLOCK); 74 | } 75 | } while(tmp & 2); 76 | } 77 | 78 | static void _late_init(void) 79 | { 80 | sys_mknod("/dev/keyboard", S_IFCHR | 0600, makedev(dev.devnr, 0)); 81 | } 82 | 83 | #include 84 | __initializer static void _init_keyboard(void) 85 | { 86 | interrupt_register(33, &_key_interrupt); 87 | arch_interrupt_unmask(33); 88 | init_register_late_call(&_late_init, NULL); 89 | dev_register(&dev, &keyboard_ops, S_IFCHR); 90 | charbuffer_create(&keybuf, 0x1000); 91 | flush_port(); 92 | } 93 | 94 | -------------------------------------------------------------------------------- /machine/pc/devices/serial.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | extern void uart_putc(char); 4 | extern unsigned char uart_getc(void); 5 | void serial_putc (char c) 6 | { 7 | uart_putc(c); 8 | if (c == '\n') 9 | { 10 | serial_putc('\r'); 11 | } 12 | } 13 | 14 | void serial_puts(const char * str) 15 | { 16 | while (*str) serial_putc (*str++); 17 | } 18 | 19 | unsigned char serial_getc(void) 20 | { 21 | return uart_getc(); 22 | } 23 | 24 | -------------------------------------------------------------------------------- /machine/pc/devices/uart.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #define PORT 0x3f8 /* COM1 */ 11 | 12 | void uart_init() 13 | { 14 | x86_64_outb(PORT + 3, 0x80); // set up to load divisor latch 15 | x86_64_outb(PORT + 0, 2); // lsb 16 | x86_64_outb(PORT + 1, 0); // msb 17 | x86_64_outb(PORT + 3, 3); // 8N1 18 | x86_64_outb(PORT + 2, 0x07); // enable FIFO, clear, 14-byte threshold 19 | x86_64_outb(PORT + 1, 0x01); 20 | } 21 | static struct charbuffer buffer; 22 | 23 | static int serial_received() 24 | { 25 | return x86_64_inb(PORT + 5) & 1; 26 | } 27 | 28 | static void uart_interrupt(int v, int flags) 29 | { 30 | (void)v; 31 | (void)flags; 32 | uint32_t isr = x86_64_inb(PORT + 2); 33 | if(isr & (1 << 2)) { 34 | while(serial_received()) { 35 | char d = x86_64_inb(PORT); 36 | charbuffer_write(&buffer, &d, 1, CHARBUFFER_DO_NONBLOCK); 37 | } 38 | } 39 | } 40 | 41 | __initializer static void uart_init_second(void) 42 | { 43 | int a = 0x24; 44 | int b = 0x23; 45 | 46 | charbuffer_create(&buffer, 0x1000); 47 | 48 | interrupt_register(a, &uart_interrupt); 49 | interrupt_register(b, &uart_interrupt); 50 | arch_interrupt_unmask(a); 51 | arch_interrupt_unmask(b); 52 | while(serial_received()) { 53 | char d = x86_64_inb(PORT); 54 | charbuffer_write(&buffer, &d, 1, CHARBUFFER_DO_NONBLOCK); 55 | } 56 | } 57 | 58 | static int is_transmit_empty() 59 | { 60 | return x86_64_inb(PORT + 5) & 0x20; 61 | } 62 | 63 | void uart_putc(unsigned char byte) 64 | { 65 | while (is_transmit_empty() == 0); 66 | x86_64_outb(PORT, byte); 67 | } 68 | 69 | unsigned char uart_getc() 70 | { 71 | char c; 72 | charbuffer_read(&buffer, &c, 1, 0); 73 | return c; 74 | } 75 | 76 | -------------------------------------------------------------------------------- /machine/pc/devices/vga.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | static struct device dev; 12 | 13 | static uintptr_t _vga_map(struct file *file, struct map_region *map, ptrdiff_t d) 14 | { 15 | (void)file; 16 | (void)d; 17 | (void)map; 18 | return 0xB8000; 19 | } 20 | 21 | static void setcurs(int x, int y) 22 | { 23 | volatile unsigned short position = (y * 80 + x); 24 | x86_64_outb(0x3D4, 0x0F); 25 | x86_64_outb(0x3D5, (unsigned char)(position&0xFF)); 26 | x86_64_outb(0x3D4, 0x0E); 27 | x86_64_outb(0x3D5, (unsigned char )((position>>8)&0xFF)); 28 | } 29 | 30 | 31 | static int _vga_ioctl(struct file *file, long cmd, long arg) 32 | { 33 | (void)file; 34 | if(cmd == 0) //set cursor 35 | { 36 | setcurs(arg & 0xFFFFFFFF, (arg >> 32) & 0xFFFFFFFF); 37 | return 0; 38 | } 39 | return -EINVAL; 40 | } 41 | 42 | static struct file_calls vga_calls = { 43 | .read = 0, 44 | .write = 0, 45 | .create = 0, .destroy = 0, .ioctl = _vga_ioctl, .poll = 0, .open = 0, .close = 0, 46 | .map = _vga_map, .unmap = 0, 47 | }; 48 | 49 | static void _late_init(void) 50 | { 51 | int ret = sys_mknod("/dev/vga", S_IFCHR | 0600, makedev(dev.devnr, 0)); 52 | assert(ret == 0); 53 | } 54 | 55 | __orderedinitializer(__orderedafter(DEVICE_INITIALIZER_ORDER)) 56 | static void _serial_init(void) 57 | { 58 | dev_register(&dev, &vga_calls, S_IFCHR); 59 | init_register_late_call(&_late_init, NULL); 60 | } 61 | 62 | -------------------------------------------------------------------------------- /machine/pc/include.mk: -------------------------------------------------------------------------------- 1 | KERNEL_LOAD_OFFSET:=0x400000 2 | KERNEL_PHYS_BASE:=0x0 3 | KERNEL_VIRT_BASE:=0xFFFFFFFF80000000 4 | 5 | C_SOURCES+=machine/pc/machine.c \ 6 | machine/pc/devices/serial.c \ 7 | machine/pc/devices/acpi.c \ 8 | machine/pc/devices/vga.c \ 9 | machine/pc/devices/ioapic.c \ 10 | machine/pc/devices/keyboard.c \ 11 | machine/pc/devices/uart.c 12 | 13 | ifneq ($(CONFIG_ARCH),x86_64) 14 | $(error Machine 'pc' only supports x86_64, not $(CONFIG_ARCH)) 15 | endif 16 | -------------------------------------------------------------------------------- /machine/pc/include/machine/acpi.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #define ACPI_INITIALIZER_ORDER 0 4 | void *acpi_find_table(const char *sig); 5 | 6 | struct sdt_header { 7 | char sig[4]; 8 | uint32_t length; 9 | uint8_t rev; 10 | uint8_t checksum; 11 | char oemid[6]; 12 | char oemtableid[8]; 13 | uint32_t oemrev; 14 | uint32_t creatorid; 15 | uint32_t creatorrev; 16 | } __attribute__((packed)); 17 | 18 | -------------------------------------------------------------------------------- /machine/pc/include/machine/machine.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | void machine_init(void); 4 | size_t machine_get_memlen(void); 5 | 6 | struct boot_module { 7 | uintptr_t start; 8 | size_t length; 9 | char name[128]; 10 | }; 11 | 12 | struct boot_module *machine_get_boot_module(int i); 13 | 14 | -------------------------------------------------------------------------------- /machine/pc/include/machine/memmap.h: -------------------------------------------------------------------------------- 1 | #define PHYS_MAP_START 0xFFFF800000000000ULL 2 | 3 | #define MMIO_PHYS_START 0xC0000000UL 4 | #define MMIO_PHYS_LENGTH 0x40000000UL 5 | 6 | #define PHYS_MEMORY_START 0x400000UL 7 | -------------------------------------------------------------------------------- /machine/pc/machine.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | static struct multiboot *multiboot; 10 | 11 | void pc_save_multiboot(void *header) 12 | { 13 | multiboot = header; 14 | } 15 | 16 | struct boot_modules_info { 17 | long count; 18 | struct boot_module modules[]; 19 | }; 20 | 21 | static uintptr_t bootmods_start = 0; 22 | static uintptr_t bootmods_infos = 0; 23 | 24 | struct boot_module *machine_get_boot_module(int i) 25 | { 26 | struct boot_modules_info *bmi = (void *)bootmods_infos; 27 | if(i >= bmi->count) 28 | return NULL; 29 | return &bmi->modules[i]; 30 | } 31 | 32 | void machine_init(void) 33 | { 34 | /* assume that the modules passed to us are vaguely in the same 35 | * place. */ 36 | if(!(multiboot->flags & MULTIBOOT_FLAG_MODS)) 37 | return; 38 | printk("Parsing %d boot modules\n", multiboot->mods_count); 39 | uintptr_t min = multiboot->mods_addr, minpage; 40 | uintptr_t max = min, maxpage; 41 | size_t datalength = 0; 42 | struct mboot_module *mods = (void *)((uintptr_t)multiboot->mods_addr); 43 | struct mboot_module saved_mod_infos[multiboot->mods_count]; 44 | char saved_names[multiboot->mods_count][128]; 45 | for(uint32_t i=0;imods_count;i++, mods++) { 46 | if(mods->start < min) 47 | min = mods->start; 48 | if(mods->end > max) 49 | max = mods->end; 50 | memcpy(saved_names[i], (void *)(uintptr_t)mods->string, 128); 51 | datalength += (mods->end - mods->start) + sizeof(struct boot_module); 52 | memcpy(&saved_mod_infos[i], mods, sizeof(*mods)); 53 | } 54 | minpage = (min & ~(0x1000 - 1)); 55 | maxpage = (max & ~(0x1000 - 1)) + 0x1000; 56 | printk("Allocating %ld KB (%lx - %lx) for boot modules\n", (maxpage - minpage) / 1024, min, max); 57 | 58 | bootmods_start = mm_physical_allocate(maxpage - minpage, false); 59 | memmove((void *)bootmods_start, (void *)minpage, (maxpage - minpage)); 60 | 61 | bootmods_infos = mm_physical_allocate(__round_up_pow2(multiboot->mods_count * sizeof(struct boot_module)), true); 62 | 63 | struct boot_modules_info *bmi = (void *)(bootmods_infos); 64 | bmi->count = multiboot->mods_count; 65 | 66 | for(int i=0;icount;i++) { 67 | bmi->modules[i].start = (saved_mod_infos[i].start - minpage) + bootmods_start + PHYS_MAP_START; 68 | bmi->modules[i].length = saved_mod_infos[i].end - saved_mod_infos[i].start; 69 | memcpy(bmi->modules[i].name, saved_names[i], 128); 70 | } 71 | } 72 | 73 | size_t machine_get_memlen(void) 74 | { 75 | if(!(multiboot->flags & MULTIBOOT_FLAG_MEM)) 76 | panic(0, "don't know how to detect memory!"); 77 | return multiboot->mem_upper * 1024 - PHYS_MEMORY_START; 78 | } 79 | 80 | -------------------------------------------------------------------------------- /machine/virt/include.mk: -------------------------------------------------------------------------------- 1 | KERNEL_LOAD_OFFSET:=0x10000 2 | KERNEL_PHYS_BASE:=0x40000000 3 | KERNEL_VIRT_BASE:=0xFFFF000000000000 4 | 5 | C_SOURCES+=$(MACHINEDIR)/kernel/init.c 6 | LIBRARIES+=fdt 7 | 8 | ifneq ($(CONFIG_ARCH),aarch64) 9 | ifneq ($(CONFIG_ARCH),arm) 10 | $(error Machine 'virt' only supports arm and aarch64, not $(CONFIG_ARCH)) 11 | endif 12 | endif 13 | -------------------------------------------------------------------------------- /machine/virt/include/machine/gic.h: -------------------------------------------------------------------------------- 1 | #ifndef __MACHINE_GIC_H 2 | #define __MACHINE_GIC_H 3 | 4 | #include 5 | #include 6 | 7 | #define GIC_DIST_BASE (0x8000000ULL + PHYS_MAP_START) 8 | #define GIC_CPU_BASE (0x8010000ULL + PHYS_MAP_START) 9 | 10 | void gic_init_percpu(void); 11 | void gic_init(void); 12 | uint32_t gic_read_interrupt_number(void); 13 | void gic_signal_eoi(uint32_t vector); 14 | void gic_enable_vector(int vector); 15 | void gic_disable_vector(int vector); 16 | 17 | #endif 18 | 19 | -------------------------------------------------------------------------------- /machine/virt/include/machine/machine.h: -------------------------------------------------------------------------------- 1 | #ifndef __MACHINE_MACHINE_H 2 | #define __MACHINE_MACHINE_H 3 | #include 4 | #define MAX_INT 128 5 | size_t machine_get_memlen(void); 6 | 7 | #define TIMER_INTERRUPT 30 8 | #define UART_INT(n) (33+n) 9 | 10 | void machine_init(void); 11 | 12 | #endif 13 | 14 | -------------------------------------------------------------------------------- /machine/virt/include/machine/memmap.h: -------------------------------------------------------------------------------- 1 | #ifndef __MACHINE_MEMMEP_H 2 | #define __MACHINE_MEMMEP_H 3 | 4 | #define MMIO_PHYS_START 0 5 | #define MMIO_PHYS_LENGTH 0x40000000UL 6 | 7 | #define PHYS_MEMORY_START 0x40000000UL 8 | 9 | #define UART(n) (0x9000000) 10 | #define UART_SERIAL 0 11 | 12 | #define PHYS_MAP_START 0xFFFFFC0000000000ULL 13 | 14 | #endif 15 | 16 | -------------------------------------------------------------------------------- /machine/virt/kernel/init.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | static uint64_t memlen; 6 | size_t machine_get_memlen(void) 7 | { 8 | return memlen; 9 | } 10 | 11 | static void parse_device_tree(void) 12 | { 13 | const void *fdt = (void *)KERNEL_VIRT_BASE; 14 | int err = fdt_check_header(fdt); 15 | if(err >= 0) { 16 | int depth = 0; 17 | int offset = 0; 18 | for (;;) { 19 | offset = fdt_next_node(fdt, offset, &depth); 20 | if (offset < 0) 21 | break; 22 | 23 | /* get the name */ 24 | const char *name = fdt_get_name(fdt, offset, NULL); 25 | if (!name) 26 | continue; 27 | if (strcmp(name, "memory") == 0) { 28 | int lenp; 29 | const void *prop_ptr = fdt_getprop(fdt, offset, "reg", &lenp); 30 | if (prop_ptr && lenp == 0x10) { 31 | /* we're looking at a memory descriptor */ 32 | uint64_t len = fdt64_to_cpu(*((const uint64_t *)prop_ptr + 1)); 33 | memlen = len; 34 | /* trim size on certain platforms */ 35 | } 36 | } else if(!strcmp(name, "psci")) { 37 | int lenp; 38 | const void *prop_ptr = fdt_getprop(fdt, offset, "method", &lenp); 39 | assert(strcmp(prop_ptr, "hvc") == 0); 40 | } else if (!strncmp(name, "cpu@", 4)) { 41 | int lenp; 42 | const void *prop_ptr = fdt_getprop(fdt, offset, "reg", &lenp); 43 | int id = *((unsigned int *)prop_ptr) >> 24; 44 | processor_create(id, id == 0 ? PROCESSOR_UP : 0); 45 | 46 | } 47 | } 48 | } else { 49 | panic(0, "failed to parse device tree"); 50 | } 51 | } 52 | 53 | void machine_init(void) 54 | { 55 | parse_device_tree(); 56 | } 57 | 58 | -------------------------------------------------------------------------------- /ports/clean.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | if [[ "$1" == "" ]]; then 3 | echo Specify port to clean 4 | exit 1 5 | fi 6 | 7 | rm -rf build/$1 2> /dev/null 8 | 9 | -------------------------------------------------------------------------------- /ports/get.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | 4 | if [[ "$1" == "" ]]; then 5 | echo Specify a list of packages to download 6 | exit 1 7 | fi 8 | 9 | if [[ "$ARCH" == "" ]]; then 10 | echo Specify \$ARCH 11 | exit 1 12 | fi 13 | 14 | if [[ "$SYSROOT" == "" ]]; then 15 | echo Specify a sysroot. 16 | exit 1 17 | fi 18 | 19 | SYSROOT=$(realpath $SYSROOT) 20 | 21 | REPO=http://googoo-16.ssrc.ucsc.edu/dbittman/repo/$ARCH 22 | 23 | TMPDIR=$(mktemp -d -t seaos-repo-download.XXXXXXXXXX) || exit 1 24 | 25 | install_package() { 26 | set -e 27 | grep "^$1:" repo.dat | tail -1 > /dev/null 28 | if [[ "${PIPESTATUS[0]}" != "0" ]]; then 29 | echo $1 was not found! 30 | exit 0 31 | fi 32 | 33 | LINE=$(grep "^$1:" repo.dat | tail -1) 34 | local NAME 35 | local VERSION 36 | local REQ 37 | IFS=: read NAME VERSION REQ <<< "$LINE" 38 | 39 | for i in $REQ; do 40 | install_package $i 41 | done 42 | 43 | if [ -e $SYSROOT/usr/packs/installed/$NAME-$VERSION.manifest ]; then 44 | return 0 45 | fi 46 | 47 | if ! curl --fail $REPO/pkg/$NAME-$VERSION.tar.xz > $NAME-$VERSION.tar.xz; then 48 | echo failed to download $1 49 | exit 1 50 | fi 51 | echo installing $NAME-$VERSION 52 | mkdir -p $NAME-$VERSION 53 | ( 54 | set -e 55 | cd $NAME-$VERSION 56 | tar xf ../$NAME-$VERSION.tar.xz 57 | ) 58 | cp -af $NAME-$VERSION/root/* $SYSROOT/ 59 | mkdir -p $SYSROOT/usr/packs/installed 60 | cp $NAME-$VERSION/*.manifest $SYSROOT/usr/packs/installed/$NAME-$VERSION.manifest 61 | 62 | return 0 63 | } 64 | 65 | ( 66 | # exit the subshell on error, but still clean up 67 | set -e 68 | cd $TMPDIR 69 | echo "Updating repo.dat..." 70 | curl $REPO/repo.dat > repo.dat 71 | if [[ "$1" == "--all" ]]; then 72 | (while IFS=: read P J; do 73 | install_package $P 74 | done) < repo.dat 75 | else 76 | for pkg in $@; do 77 | install_package $pkg 78 | done 79 | fi 80 | ) 81 | 82 | echo cleaning up... 83 | rm -rf $TMPDIR 84 | 85 | -------------------------------------------------------------------------------- /ports/p.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [[ "$1" == "" ]]; then 4 | echo Specify URL 5 | exit 1 6 | fi 7 | 8 | if [[ "$2" == "" ]]; then 9 | echo Specify DESC 10 | exit 1 11 | fi 12 | 13 | NAME=$(basename $1 | sed -rns 's/(\w+)-(.*)\.tar.*/\1/p') 14 | VER=$(basename $1 | sed -rns 's/(\w+)-(.*)\.tar.*/\2/p') 15 | mkdir -p ports/$NAME 16 | cat > ports/$NAME/build.sh <> $REPO/$ARCH/repo.dat 33 | tar -c -C build/$1/install-$ARCH-elf-linux-musl -f $REPO/$ARCH/pkg/$NAME-$VERSION-$REV.tar.xz . 34 | return 0 35 | } 36 | 37 | mkdir -p $REPO/$ARCH/pkg 38 | 39 | for i in $@; do 40 | package_program $i 41 | done 42 | 43 | -------------------------------------------------------------------------------- /ports/ports/autoconf/build.sh: -------------------------------------------------------------------------------- 1 | NAME='autoconf' 2 | VERSION='2.69' 3 | DESC='GNU autotools, autoconf' 4 | REQUIRES=() 5 | 6 | SOURCES=('http://ftp.gnu.org/gnu/autoconf/autoconf-2.69.tar.xz') 7 | PATCHES=('autoconf-2.69-seaos.patch') 8 | ALLFILES= 9 | 10 | prepare() { 11 | standard_prepare 12 | } 13 | 14 | build() { 15 | standard_build "$STDCONF" "$STDMAKE" "$STDINSTALL" 16 | } 17 | -------------------------------------------------------------------------------- /ports/ports/automake/build.sh: -------------------------------------------------------------------------------- 1 | NAME='automake' 2 | VERSION='1.15' 3 | DESC='GNU autotools, automake' 4 | REQUIRES=() 5 | 6 | SOURCES=('http://ftp.gnu.org/gnu/automake/automake-1.15.tar.xz') 7 | PATCHES=() 8 | ALLFILES= 9 | 10 | prepare() { 11 | standard_prepare 12 | } 13 | 14 | build() { 15 | standard_build "$STDCONF" "$STDMAKE" "$STDINSTALL" 16 | } 17 | -------------------------------------------------------------------------------- /ports/ports/bash/bash-4.3-seaos.patch: -------------------------------------------------------------------------------- 1 | diff -uprN bash-4.3/configure bash-4.3-patched/configure 2 | --- bash-4.3/configure 2014-02-11 07:38:00.000000000 -0800 3 | +++ bash-4.3-patched/configure 2016-06-04 16:16:40.502634477 -0700 4 | @@ -5278,7 +5278,7 @@ if ${ac_cv_rl_version+:} false; then : 5 | $as_echo_n "(cached) " >&6 6 | else 7 | if test "$cross_compiling" = yes; then : 8 | - ac_cv_rl_version='4.2' 9 | + ac_cv_rl_version='6.3' 10 | else 11 | cat confdefs.h - <<_ACEOF >conftest.$ac_ext 12 | /* end confdefs.h. */ 13 | -------------------------------------------------------------------------------- /ports/ports/bash/build.sh: -------------------------------------------------------------------------------- 1 | NAME='bash' 2 | VERSION='4.3' 3 | DESC='Fast Lexical Analyzer' 4 | REQUIRES=('ncurses' 'readline') 5 | 6 | SOURCES=('http://ftp.gnu.org/gnu/bash/bash-4.3.tar.gz') 7 | PATCHES=('bash-4.3-seaos.patch') 8 | ALLFILES=${PATCHES[@]} 9 | 10 | prepare() { 11 | standard_prepare 12 | } 13 | 14 | build() { 15 | standard_build "$STDCONF --enable-curses --without-bash-malloc --enable-history --prefix=/ --enable-readline --with-installed-readline --disable-nls" "$STDMAKE" "$STDINSTALL" 16 | } 17 | 18 | -------------------------------------------------------------------------------- /ports/ports/binutils/build.sh: -------------------------------------------------------------------------------- 1 | NAME='binutils' 2 | VERSION='2.26' 3 | DESC='GNU Utilities for Working With Executable Files' 4 | REQUIRES=('libz') 5 | 6 | SOURCES=('http://ftp.gnu.org/gnu/binutils/binutils-2.26.tar.gz') 7 | PATCHES=() 8 | ALLFILES= 9 | 10 | prepare() { 11 | standard_prepare 12 | } 13 | 14 | build() { 15 | standard_build "$STDCONF --enable-host-shared --with-system-zlib --enable-shared enable_shared=yes --disable-nls" "$STDMAKE" "$STDINSTALL" 16 | } 17 | -------------------------------------------------------------------------------- /ports/ports/bison/build.sh: -------------------------------------------------------------------------------- 1 | NAME='bison' 2 | VERSION='3.0.4' 3 | DESC='Parser generator' 4 | REQUIRES=() 5 | 6 | SOURCES=('http://ftp.gnu.org/gnu/bison/bison-3.0.4.tar.xz') 7 | PATCHES=() 8 | ALLFILES= 9 | 10 | prepare() { 11 | standard_prepare 12 | } 13 | 14 | build() { 15 | standard_build "$STDCONF" "$STDMAKE" "$STDINSTALL" 16 | } 17 | -------------------------------------------------------------------------------- /ports/ports/coreutils/build.sh: -------------------------------------------------------------------------------- 1 | NAME='coreutils' 2 | VERSION='8.25' 3 | DESC='GNU Core System Utilities' 4 | REQUIRES=() 5 | 6 | SOURCES=('ftp://ftp.gnu.org/gnu/coreutils/coreutils-8.25.tar.xz') 7 | PATCHES=('coreutils-8.25-seaos.patch') 8 | ALLFILES= 9 | 10 | prepare() { 11 | standard_prepare 12 | } 13 | 14 | build() { 15 | standard_build "$STDCONF" "$STDMAKE" "$STDINSTALL -i" 16 | } 17 | -------------------------------------------------------------------------------- /ports/ports/coreutils/coreutils-8.25-seaos.patch: -------------------------------------------------------------------------------- 1 | diff -uprN coreutils-8.25/Makefile.in coreutils-8.25-patched/Makefile.in 2 | --- coreutils-8.25/Makefile.in 2016-01-20 02:55:18.000000000 -0800 3 | +++ coreutils-8.25-patched/Makefile.in 2016-05-29 15:16:35.988989149 -0700 4 | @@ -14390,12 +14390,12 @@ $(ALL_MANS): $(mandeps) 5 | install) prog='ginstall'; argv=$$name;; \ 6 | test) prog='['; argv='[';; \ 7 | *) prog=$$name; argv=$$prog;; \ 8 | - esac; \ 9 | - rm -f $@ $@-t \ 10 | + esac; 11 | + -rm -f $@ $@-t \ 12 | && t=$*.td \ 13 | && rm -rf $$t \ 14 | && $(MKDIR_P) $$t \ 15 | - && (cd $$t && $(LN_S) '$(abs_top_builddir)/src/'$$prog$(EXEEXT) \ 16 | + && (cd $$t && $(LN_S) $$prog$(EXEEXT) \ 17 | $$argv$(EXEEXT)) \ 18 | && : $${SOURCE_DATE_EPOCH=`cat $(srcdir)/.timestamp 2>/dev/null || :`} \ 19 | && export SOURCE_DATE_EPOCH && $(run_help2man) \ 20 | -------------------------------------------------------------------------------- /ports/ports/curl/build.sh: -------------------------------------------------------------------------------- 1 | NAME='curl' 2 | VERSION='7.50.3' 3 | DESC='Commandline data transfer via URLs' 4 | REQUIRES=() 5 | 6 | SOURCES=('https://curl.haxx.se/download/curl-7.50.3.tar.bz2') 7 | PATCHES=() 8 | ALLFILES= 9 | 10 | prepare() { 11 | standard_prepare 12 | } 13 | 14 | build() { 15 | standard_build "$STDCONF" "$STDMAKE" "$STDINSTALL" 16 | } 17 | -------------------------------------------------------------------------------- /ports/ports/diffutils/build.sh: -------------------------------------------------------------------------------- 1 | NAME='diffutils' 2 | VERSION='3.3' 3 | DESC='Tools for making, comparing, and patching diffs' 4 | REQUIRES=() 5 | 6 | SOURCES=('http://ftp.gnu.org/gnu/diffutils/diffutils-3.3.tar.xz') 7 | PATCHES=() 8 | ALLFILES= 9 | 10 | prepare() { 11 | standard_prepare 12 | } 13 | 14 | build() { 15 | standard_build "$STDCONF" "$STDMAKE" "$STDINSTALL" 16 | } 17 | -------------------------------------------------------------------------------- /ports/ports/dropbear/build.sh: -------------------------------------------------------------------------------- 1 | NAME='dropbear' 2 | VERSION='2016.74' 3 | DESC='SSH' 4 | REQUIRES=() 5 | 6 | SOURCES=('https://matt.ucc.asn.au/dropbear/dropbear-2016.74.tar.bz2') 7 | PATCHES=('dropbear-2016.74-seaos-all.patch') 8 | ALLFILES= 9 | 10 | prepare() { 11 | standard_prepare 12 | } 13 | 14 | build() { 15 | cp -rf ../$NAME-$VERSION/* . 16 | if ! ./configure $STDCONF; then 17 | return 1 18 | fi 19 | if ! make $STDMAKE; then 20 | return 1 21 | fi 22 | if ! make $STDINSTALL; then 23 | return 1 24 | fi 25 | 26 | standard_build "$STDCONF" "$STDMAKE" "$STDINSTALL" 27 | } 28 | 29 | -------------------------------------------------------------------------------- /ports/ports/dropbear/dropbear-2016.74-seaos-all.patch: -------------------------------------------------------------------------------- 1 | diff -uprN dropbear-2016.74/debug.h dropbear-2016.74-seaos/debug.h 2 | --- dropbear-2016.74/debug.h 2016-09-25 22:54:25.232577102 -0700 3 | +++ dropbear-2016.74-seaos/debug.h 2016-09-25 22:54:42.929039533 -0700 4 | @@ -39,7 +39,7 @@ 5 | * Caution: Don't use this in an unfriendly environment (ie unfirewalled), 6 | * since the printing may not sanitise strings etc. This will add a reasonable 7 | * amount to your executable size. */ 8 | -/*#define DEBUG_TRACE*/ 9 | +#define DEBUG_TRACE 1 10 | 11 | /* All functions writing to the cleartext payload buffer call 12 | * CHECKCLEARTOWRITE() before writing. This is only really useful if you're 13 | diff -uprN dropbear-2016.74/includes.h dropbear-2016.74-seaos/includes.h 14 | --- dropbear-2016.74/includes.h 2016-07-21 08:17:09.000000000 -0700 15 | +++ dropbear-2016.74-seaos/includes.h 2016-09-25 15:21:24.263916592 -0700 16 | @@ -156,11 +156,6 @@ typedef unsigned int u_int32_t; 17 | typedef u_int32_t uint32_t; 18 | #endif /* HAVE_UINT32_T */ 19 | 20 | -#ifdef SO_PRIORITY 21 | -#include 22 | -#include 23 | -#endif 24 | - 25 | #include "fake-rfc2553.h" 26 | 27 | #ifndef LOG_AUTHPRIV 28 | diff -uprN dropbear-2016.74/netio.c dropbear-2016.74-seaos/netio.c 29 | --- dropbear-2016.74/netio.c 2016-07-21 08:17:09.000000000 -0700 30 | +++ dropbear-2016.74-seaos/netio.c 2016-09-25 15:21:39.627091816 -0700 31 | @@ -306,9 +306,6 @@ void set_sock_priority(int sock, enum dr 32 | #ifdef IPTOS_LOWDELAY 33 | int iptos_val = 0; 34 | #endif 35 | -#ifdef SO_PRIORITY 36 | - int so_prio_val = 0; 37 | -#endif 38 | 39 | 40 | /* Don't log ENOTSOCK errors so that this can harmlessly be called 41 | @@ -333,19 +330,6 @@ void set_sock_priority(int sock, enum dr 42 | } 43 | #endif 44 | 45 | -#ifdef SO_PRIORITY 46 | - if (prio == DROPBEAR_PRIO_LOWDELAY) { 47 | - so_prio_val = TC_PRIO_INTERACTIVE; 48 | - } else if (prio == DROPBEAR_PRIO_BULK) { 49 | - so_prio_val = TC_PRIO_BULK; 50 | - } 51 | - /* linux specific, sets QoS class. see tc-prio(8) */ 52 | - rc = setsockopt(sock, SOL_SOCKET, SO_PRIORITY, (void*) &so_prio_val, sizeof(so_prio_val)); 53 | - if (rc < 0 && errno != ENOTSOCK) 54 | - dropbear_log(LOG_WARNING, "Couldn't set SO_PRIORITY (%s)", 55 | - strerror(errno)); 56 | -#endif 57 | - 58 | } 59 | 60 | /* Listen on address:port. 61 | diff -uprN dropbear-2016.74/options.h dropbear-2016.74-seaos/options.h 62 | --- dropbear-2016.74/options.h 2016-07-21 08:17:09.000000000 -0700 63 | +++ dropbear-2016.74-seaos/options.h 2016-09-25 22:46:10.285080057 -0700 64 | @@ -352,5 +352,5 @@ be overridden at runtime with -I. 0 disa 65 | /* Some other defines (that mostly should be left alone) are defined 66 | * in sysoptions.h */ 67 | #include "sysoptions.h" 68 | - 69 | +#undef DROPBEAR_SERVER_TCP_FAST_OPEN 70 | #endif /* DROPBEAR_OPTIONS_H_ */ 71 | -------------------------------------------------------------------------------- /ports/ports/findutils/build.sh: -------------------------------------------------------------------------------- 1 | NAME='findutils' 2 | VERSION='4.6.0' 3 | DESC='Find command, and associated stuff' 4 | REQUIRES=() 5 | 6 | SOURCES=('http://ftp.gnu.org/gnu/findutils/findutils-4.6.0.tar.gz') 7 | PATCHES=() 8 | ALLFILES= 9 | 10 | prepare() { 11 | standard_prepare 12 | } 13 | 14 | build() { 15 | standard_build "$STDCONF" "$STDMAKE" "$STDINSTALL" 16 | } 17 | -------------------------------------------------------------------------------- /ports/ports/flex/build.sh: -------------------------------------------------------------------------------- 1 | NAME='flex' 2 | VERSION='2.6.0' 3 | DESC='Fast Lexical Analyzer' 4 | REQUIRES=('m4') 5 | 6 | SOURCES=('http://dbittman.github.io/mirror/flex-2.6.0.tar.bz2') 7 | PATCHES=('flex-2.6.0-seaos.patch') 8 | ALLFILES=${PATCHES[@]} 9 | 10 | prepare() { 11 | standard_prepare 12 | } 13 | 14 | build() { 15 | standard_build "$STDCONF" "$STDMAKE" "$STDINSTALL" 16 | } 17 | 18 | -------------------------------------------------------------------------------- /ports/ports/flex/flex-2.6.0-seaos.patch: -------------------------------------------------------------------------------- 1 | diff -uprN flex-2.6.0/Makefile.in flex-2.6.0-patched/Makefile.in 2 | --- flex-2.6.0/Makefile.in 2015-11-17 08:19:45.000000000 -0800 3 | +++ flex-2.6.0-patched/Makefile.in 2016-05-27 14:20:20.313563278 -0700 4 | @@ -450,7 +450,6 @@ SUBDIRS = \ 5 | doc \ 6 | examples \ 7 | po \ 8 | - tests \ 9 | tools 10 | 11 | all: all-recursive 12 | diff -uprN flex-2.6.0/src/config.h.in flex-2.6.0-patched/src/config.h.in 13 | --- flex-2.6.0/src/config.h.in 2015-11-17 08:19:45.000000000 -0800 14 | +++ flex-2.6.0-patched/src/config.h.in 2016-05-27 14:19:53.867217736 -0700 15 | @@ -215,3 +215,12 @@ 16 | 17 | /* Define as `fork' if `vfork' does not work. */ 18 | #undef vfork 19 | + 20 | + 21 | + 22 | +#include 23 | +void *rpl_malloc(size_t); 24 | +void rpl_free(void *); 25 | +void *rpl_realloc(void *, size_t); 26 | + 27 | + 28 | -------------------------------------------------------------------------------- /ports/ports/gawk/build.sh: -------------------------------------------------------------------------------- 1 | NAME='gawk' 2 | VERSION='4.1.3' 3 | DESC='GNU awk' 4 | REQUIRES=() 5 | 6 | SOURCES=('http://ftp.gnu.org/gnu/gawk/gawk-4.1.3.tar.xz') 7 | PATCHES=() 8 | ALLFILES= 9 | 10 | prepare() { 11 | standard_prepare 12 | } 13 | 14 | build() { 15 | standard_build "$STDCONF" "$STDMAKE" "$STDINSTALL" 16 | } 17 | -------------------------------------------------------------------------------- /ports/ports/gcc/build.sh: -------------------------------------------------------------------------------- 1 | NAME='gcc' 2 | VERSION='5.3.0' 3 | DESC='GNU Compiler Collection' 4 | REQUIRES=('mpc' 'mpfr' 'gmp') 5 | 6 | SOURCES=('http://mirrors.concertpass.com/gcc/releases/gcc-5.3.0/gcc-5.3.0.tar.bz2') 7 | PATCHES=('gcc-5.3.0-seaos.patch') 8 | ALLFILES= 9 | 10 | prepare() { 11 | standard_prepare 12 | } 13 | 14 | build() { 15 | standard_build "$STDCONF --enable-host-shared --enable-shared enable_shared=yes --enable-languages=c,c++ --enable-lto --disable-nls --disable-werror --target=$TARGET --with-build-sysroot=$SYSROOT" "all-gcc all-target-libgcc all-target-libstdc++-v3" "install-gcc install-target-libgcc install-target-libstdc++-v3 $STDDESTDIR" 16 | } 17 | -------------------------------------------------------------------------------- /ports/ports/gdbm/build.sh: -------------------------------------------------------------------------------- 1 | NAME='gdbm' 2 | VERSION='1.12' 3 | DESC='GNU Database Manager' 4 | REQUIRES=() 5 | 6 | SOURCES=('ftp://ftp.gnu.org/gnu/gdbm/gdbm-1.12.tar.gz') 7 | PATCHES=() 8 | ALLFILES= 9 | 10 | prepare() { 11 | standard_prepare 12 | } 13 | 14 | build() { 15 | standard_build "$STDCONF" "$STDMAKE" "$STDINSTALL" 16 | } 17 | -------------------------------------------------------------------------------- /ports/ports/git/build.sh: -------------------------------------------------------------------------------- 1 | NAME='git' 2 | VERSION='2.10.0' 3 | DESC='Version Control System' 4 | REQUIRES=() 5 | 6 | SOURCES=('https://github.com/git/git/archive/v2.10.0.tar.gz') 7 | PATCHES=() 8 | ALLFILES= 9 | 10 | prepare() { 11 | standard_prepare 12 | cd git-$VERSION 13 | autoconf 14 | cd .. 15 | } 16 | 17 | build() { 18 | cp -rf ../git-$VERSION/* . 19 | standard_build "$STDCONF ac_cv_fread_reads_directories=no ac_cv_snprintf_returns_bogus=no --with-editor=vim --with-pager=less --with-shell=sh --with-perl=perl --with-python=python" "$STDMAKE" "$STDINSTALL" 20 | } 21 | -------------------------------------------------------------------------------- /ports/ports/gmp/build.sh: -------------------------------------------------------------------------------- 1 | NAME='gmp' 2 | VERSION='6.1.0' 3 | DESC='Library for arbitrary precision math' 4 | REQUIRES=() 5 | 6 | SOURCES=('https://gmplib.org/download/gmp/gmp-6.1.0.tar.xz') 7 | PATCHES=() 8 | ALLFILES= 9 | 10 | prepare() { 11 | standard_prepare 12 | } 13 | 14 | build() { 15 | standard_build "$STDCONF" "$STDMAKE" "$STDINSTALL" 16 | } 17 | -------------------------------------------------------------------------------- /ports/ports/grep/build.sh: -------------------------------------------------------------------------------- 1 | NAME='grep' 2 | VERSION='2.25' 3 | DESC='Regular Expression Search Tool' 4 | REQUIRES=() 5 | 6 | SOURCES=('http://ftp.gnu.org/gnu/grep/grep-2.25.tar.xz') 7 | PATCHES=() 8 | ALLFILES= 9 | 10 | prepare() { 11 | standard_prepare 12 | } 13 | 14 | build() { 15 | standard_build "$STDCONF" "$STDMAKE" "$STDINSTALL" 16 | } 17 | -------------------------------------------------------------------------------- /ports/ports/groff/build.sh: -------------------------------------------------------------------------------- 1 | NAME='groff' 2 | VERSION='1.22.3' 3 | DESC='GNU Troff' 4 | REQUIRES=() 5 | 6 | SOURCES=('http://ftp.gnu.org/gnu/groff/groff-1.22.3.tar.gz') 7 | PATCHES=('groff-1.22.3-seaos.patch') 8 | ALLFILES= 9 | 10 | prepare() { 11 | standard_prepare 12 | } 13 | 14 | build() { 15 | standard_build "$STDCONF --with-doc=no" "$STDMAKE" "$STDINSTALL" 16 | } 17 | -------------------------------------------------------------------------------- /ports/ports/groff/groff-1.22.3-seaos.patch: -------------------------------------------------------------------------------- 1 | diff -uprN groff-1.22.3/Makefile.in groff-1.22.3-patched/Makefile.in 2 | --- groff-1.22.3/Makefile.in 2014-11-04 00:38:35.145524997 -0800 3 | +++ groff-1.22.3-patched/Makefile.in 2016-06-01 00:12:08.592422897 -0700 4 | @@ -702,20 +702,6 @@ OTHERDIRS=\ 5 | src/utils/afmtodit \ 6 | font/devpdf \ 7 | arch/mingw \ 8 | - contrib/chem \ 9 | - contrib/eqn2graph \ 10 | - contrib/gdiffmk \ 11 | - contrib/glilypond \ 12 | - contrib/gperl \ 13 | - contrib/gpinyin \ 14 | - contrib/grap2graph \ 15 | - contrib/groff_filenames \ 16 | - contrib/groffer \ 17 | - contrib/hdtbl \ 18 | - contrib/mm \ 19 | - contrib/pdfmark \ 20 | - contrib/pic2graph \ 21 | - contrib/mom \ 22 | doc \ 23 | man \ 24 | src/roff/grog \ 25 | @@ -741,14 +727,6 @@ EXTRADIRS=\ 26 | NOMAKEDIRS=\ 27 | m4 \ 28 | arch/djgpp \ 29 | - contrib/chem/examples \ 30 | - contrib/chem/examples/122 \ 31 | - contrib/hdtbl/examples \ 32 | - contrib/mm/examples \ 33 | - contrib/mm/mm \ 34 | - contrib/mom/examples \ 35 | - contrib/mom/momdoc \ 36 | - contrib/gdiffmk/tests \ 37 | src/libs/snprintf \ 38 | src/libs/gnulib/lib \ 39 | src/libs/gnulib/lib/uniwidth \ 40 | -------------------------------------------------------------------------------- /ports/ports/gzip/build.sh: -------------------------------------------------------------------------------- 1 | NAME='gzip' 2 | VERSION='1.8' 3 | DESC='GNU zip' 4 | REQUIRES=() 5 | 6 | SOURCES=('http://mirrors.kernel.org/gnu/gzip/gzip-1.8.tar.xz') 7 | PATCHES=() 8 | ALLFILES= 9 | 10 | prepare() { 11 | standard_prepare 12 | } 13 | 14 | build() { 15 | standard_build "$STDCONF" "$STDMAKE" "$STDINSTALL" 16 | } 17 | -------------------------------------------------------------------------------- /ports/ports/less/build.sh: -------------------------------------------------------------------------------- 1 | NAME='less' 2 | VERSION='481' 3 | DESC='Terminal pager' 4 | REQUIRES=() 5 | 6 | SOURCES=('http://ftp.gnu.org/gnu/less/less-481.tar.gz') 7 | PATCHES=() 8 | ALLFILES= 9 | 10 | prepare() { 11 | standard_prepare 12 | } 13 | 14 | build() { 15 | standard_build "$STDCONF" "$STDMAKE" "$STDINSTALL" 16 | } 17 | -------------------------------------------------------------------------------- /ports/ports/libpipeline/build.sh: -------------------------------------------------------------------------------- 1 | NAME='libpipeline' 2 | VERSION='1.4.1' 3 | DESC='Pipelining library' 4 | REQUIRES=() 5 | 6 | SOURCES=('http://download.savannah.gnu.org/releases/libpipeline/libpipeline-1.4.1.tar.gz') 7 | PATCHES=() 8 | ALLFILES= 9 | 10 | prepare() { 11 | standard_prepare 12 | } 13 | 14 | build() { 15 | standard_build "$STDCONF" "$STDMAKE" "$STDINSTALL" 16 | } 17 | -------------------------------------------------------------------------------- /ports/ports/libz/build.sh: -------------------------------------------------------------------------------- 1 | NAME='libz' 2 | VERSION='1.2.8.2015.12.26' 3 | DESC='Port of zlib for Sortix.' 4 | REQUIRES=() 5 | 6 | SOURCES=('https://sortix.org/libz/release/libz-1.2.8.2015.12.26.tar.gz') 7 | PATCHES=() 8 | ALLFILES= 9 | 10 | prepare() { 11 | standard_prepare 12 | } 13 | 14 | build() { 15 | standard_build "$STDCONF" "$STDMAKE" "$STDINSTALL" 16 | } 17 | -------------------------------------------------------------------------------- /ports/ports/lynx/build.sh: -------------------------------------------------------------------------------- 1 | NAME='lynx' 2 | VERSION='2.8.8' 3 | DESC='Text-based web browser' 4 | REQUIRES=() 5 | 6 | SOURCES=('http://invisible-mirror.net/archives/lynx/tarballs/lynx2.8.8rel.2.tar.bz2') 7 | PATCHES=() 8 | ALLFILES= 9 | 10 | prepare() { 11 | standard_prepare 12 | rm -rf lynx-$VERSION 13 | mv lynx2-8-8 lynx-2.8.8 14 | } 15 | 16 | build() { 17 | standard_build "$STDCONF --enable-ipv6 cf_cv_getaddrinfo=yes" "$STDMAKE" "$STDINSTALL" 18 | } 19 | -------------------------------------------------------------------------------- /ports/ports/m4/build.sh: -------------------------------------------------------------------------------- 1 | NAME='m4' 2 | VERSION='1.4.17' 3 | DESC='M4 Unix Macro System' 4 | REQUIRES=() 5 | 6 | SOURCES=('http://ftp.gnu.org/gnu/m4/m4-1.4.17.tar.xz') 7 | PATCHES=() 8 | ALLFILES=${PATCHES[@]} 9 | 10 | prepare() { 11 | standard_prepare 12 | } 13 | 14 | build() { 15 | standard_build "$STDCONF" "$STDMAKE -j4" "$STDINSTALL" 16 | } 17 | 18 | -------------------------------------------------------------------------------- /ports/ports/make/build.sh: -------------------------------------------------------------------------------- 1 | NAME='make' 2 | VERSION='4.2' 3 | DESC='GNU make' 4 | REQUIRES=() 5 | 6 | SOURCES=('http://ftp.gnu.org/gnu/make/make-4.2.tar.gz') 7 | PATCHES=() 8 | ALLFILES= 9 | 10 | prepare() { 11 | standard_prepare 12 | } 13 | 14 | build() { 15 | standard_build "$STDCONF --without-guile" "$STDMAKE" "$STDINSTALL" 16 | } 17 | -------------------------------------------------------------------------------- /ports/ports/man-db/build.sh: -------------------------------------------------------------------------------- 1 | NAME='man-db' 2 | VERSION='2.7.5' 3 | DESC='Man page viewer' 4 | REQUIRES=() 5 | 6 | SOURCES=('http://download.savannah.gnu.org/releases/man-db/man-db-2.7.5.tar.xz') 7 | PATCHES=() 8 | ALLFILES= 9 | 10 | prepare() { 11 | standard_prepare 12 | } 13 | 14 | build() { 15 | export PKG_CONFIG_PATH=$SYSROOT:$SYSROOT/usr 16 | export PKG_CONFIG_LIBPATH=$SYSROOT/usr/lib 17 | standard_build "$STDCONF libpipeline_CFLAGS= libpipeline_LIBS=" "$STDMAKE" "$STDINSTALL -i" 18 | } 19 | -------------------------------------------------------------------------------- /ports/ports/mpc/build.sh: -------------------------------------------------------------------------------- 1 | NAME='mpc' 2 | VERSION='1.0.3' 3 | DESC='Multiprecision library' 4 | REQUIRES=('mpfr' 'gmp') 5 | 6 | SOURCES=('ftp://ftp.gnu.org/gnu/mpc/mpc-1.0.3.tar.gz') 7 | PATCHES=() 8 | ALLFILES= 9 | 10 | prepare() { 11 | standard_prepare 12 | } 13 | 14 | build() { 15 | standard_build "$STDCONF CC=$TARGET-gcc" "$STDMAKE" "$STDINSTALL" 16 | } 17 | -------------------------------------------------------------------------------- /ports/ports/mpfr/build.sh: -------------------------------------------------------------------------------- 1 | NAME='mpfr' 2 | VERSION='3.1.5' 3 | DESC='C library for multiple-precision floating-point computations' 4 | REQUIRES=('gmp') 5 | 6 | SOURCES=('http://www.mpfr.org/mpfr-current/mpfr-3.1.5.tar.xz') 7 | PATCHES=() 8 | ALLFILES= 9 | 10 | prepare() { 11 | standard_prepare 12 | } 13 | 14 | build() { 15 | standard_build "$STDCONF CC=$TARGET-gcc" "$STDMAKE" "$STDINSTALL" 16 | } 17 | -------------------------------------------------------------------------------- /ports/ports/ncurses/build.sh: -------------------------------------------------------------------------------- 1 | NAME='ncurses' 2 | VERSION='6.0' 3 | DESC='Curses Library' 4 | REQUIRES=() 5 | 6 | SOURCES=('ftp://ftp.gnu.org/gnu/ncurses/ncurses-6.0.tar.gz') 7 | PATCHES=('ncurses-6.0-seaos.patch') 8 | ALLFILES=${PATCHES[@]} 9 | 10 | prepare() { 11 | standard_prepare 12 | } 13 | 14 | build() { 15 | standard_build "$STDCONF --with-shared --enable-widec" "$STDMAKE -j4" "$STDINSTALL" 16 | } 17 | 18 | -------------------------------------------------------------------------------- /ports/ports/openssl/build.sh: -------------------------------------------------------------------------------- 1 | NAME='openssl' 2 | VERSION='1.1.0a' 3 | DESC='SSL and Crypto Libraries' 4 | REQUIRES=() 5 | 6 | SOURCES=('https://www.openssl.org/source/openssl-1.1.0a.tar.gz') 7 | PATCHES=() 8 | ALLFILES= 9 | 10 | prepare() { 11 | standard_prepare 12 | } 13 | 14 | build() { 15 | cp -rf ../$NAME-$VERSION/* . 16 | if ! ./Configure --prefix=/usr --cross-compile-prefix=$TARGET- -DOPENSSL_NO_ASYNC linux-$TARGETARCH; then 17 | return 1 18 | fi 19 | if ! make -j4; then 20 | return 1 21 | fi 22 | if ! make $STDINSTALL; then 23 | return 1 24 | fi 25 | } 26 | -------------------------------------------------------------------------------- /ports/ports/readline/build.sh: -------------------------------------------------------------------------------- 1 | NAME='readline' 2 | VERSION='6.3' 3 | DESC='GNU readline library' 4 | REQUIRES=('ncurses') 5 | 6 | SOURCES=('ftp://ftp.gnu.org/gnu/readline/readline-6.3.tar.gz') 7 | PATCHES=() 8 | ALLFILES= 9 | 10 | prepare() { 11 | standard_prepare 12 | } 13 | 14 | build() { 15 | standard_build "$STDCONF --enable-shared bash_cv_wcwidth_broken=no" "$STDMAKE" "$STDINSTALL" 16 | } 17 | -------------------------------------------------------------------------------- /ports/ports/rsync/build.sh: -------------------------------------------------------------------------------- 1 | NAME='rsync' 2 | VERSION='3.1.2' 3 | DESC='Remote File Transfer' 4 | REQUIRES=() 5 | 6 | SOURCES=('https://download.samba.org/pub/rsync/src/rsync-3.1.2.tar.gz') 7 | PATCHES=() 8 | ALLFILES= 9 | 10 | prepare() { 11 | standard_prepare 12 | } 13 | 14 | build() { 15 | standard_build "$STDCONF" "$STDMAKE" "$STDINSTALL" 16 | } 17 | -------------------------------------------------------------------------------- /ports/ports/seaosbase/build.sh: -------------------------------------------------------------------------------- 1 | NAME='seaosbase' 2 | VERSION='0.4' 3 | DESC='Base configuration and directory layout for SeaOS' 4 | REQUIRES=() 5 | 6 | SOURCES=() 7 | PATCHED=() 8 | ALLFILES=() 9 | 10 | prepare() { 11 | return 0 12 | } 13 | 14 | build() { 15 | echo $INSTALLDIR 16 | mkdir -p $INSTALLDIR/{var/cache,tmp,etc,bin,users/root} 17 | ln -s bash $INSTALLDIR/bin/sh 18 | cat > $INSTALLDIR/etc/bashrc < $INSTALLDIR/etc/passwd < $INSTALLDIR/etc/profile < 10 | #include 11 | #include 12 | #include 13 | #include 14 | struct cell { 15 | uint8_t character; 16 | uint8_t attr; 17 | }; 18 | 19 | struct pty { 20 | _Atomic int masterfd; 21 | struct cell lines[LINES][80]; 22 | _Atomic int cx, cy, sp, s_cy, s_cx; 23 | bool cursor_invisible; 24 | uint8_t cattr; 25 | struct termios term; 26 | struct winsize win; 27 | thrd_t thread; 28 | }; 29 | 30 | extern struct pty *ptys[MAX_TERMS]; 31 | extern struct pty * _Atomic current_pty; 32 | extern int keyfd; 33 | 34 | void read_keyboard(void); 35 | void process_output(struct pty *pty); 36 | void init_screen(void); 37 | void clear(struct pty *pty); 38 | int scroll_down(struct pty *pty, int n); 39 | int scroll_up(struct pty *pty, int n); 40 | void update_cursor(struct pty *pty); 41 | void switch_console(int); 42 | void flip(struct pty *pty); 43 | void update_cursor(struct pty *pty); 44 | bool pty_is_icanon(struct pty *pty); 45 | -------------------------------------------------------------------------------- /sysroot/usr/src/cond/include.mk: -------------------------------------------------------------------------------- 1 | _COND_SRC=cond.c keyboard.c output.c 2 | COND_SRC=$(addprefix $(SYSROOT)/usr/src/cond/,$(_COND_SRC)) 3 | initrd/bin/cond: $(COND_SRC) 4 | @mkdir -p initrd/bin 5 | $(TOOLCHAIN_PREFIX)linux-musl-gcc -static -O2 -g -o $@ $^ -Wall 6 | 7 | -------------------------------------------------------------------------------- /sysroot/usr/src/include.mk: -------------------------------------------------------------------------------- 1 | 2 | USRPROGS_NAMES=cond init syslogd sctl ps thr udps lookup ping netcat 3 | 4 | USRPROGS=$(addprefix initrd/bin/,$(USRPROGS_NAMES)) 5 | 6 | initrd/bin/netcat: $(SYSROOT)/usr/src/netcat.c 7 | @mkdir -p initrd/bin 8 | $(TOOLCHAIN_PREFIX)linux-musl-gcc -static -O2 -g -o $@ $< 9 | 10 | initrd/bin/ping: $(SYSROOT)/usr/src/ping.c 11 | @mkdir -p initrd/bin 12 | $(TOOLCHAIN_PREFIX)linux-musl-gcc -static -O2 -g -o $@ $< 13 | 14 | initrd/bin/lookup: $(SYSROOT)/usr/src/lookup.c 15 | @mkdir -p initrd/bin 16 | $(TOOLCHAIN_PREFIX)linux-musl-gcc -static -O2 -g -o $@ $< 17 | 18 | initrd/bin/udps: $(SYSROOT)/usr/src/udps.c 19 | @mkdir -p initrd/bin 20 | $(TOOLCHAIN_PREFIX)linux-musl-gcc -static -O2 -g -o $@ $< 21 | 22 | initrd/bin/thr: $(SYSROOT)/usr/src/thr.c 23 | @mkdir -p initrd/bin 24 | $(TOOLCHAIN_PREFIX)linux-musl-gcc -static -O2 -g -o $@ $< -Wall 25 | 26 | initrd/bin/init: $(SYSROOT)/usr/src/init.c 27 | @mkdir -p initrd/bin 28 | $(TOOLCHAIN_PREFIX)linux-musl-gcc -static -O2 -g -o $@ $< -Wall 29 | 30 | initrd/bin/ps: $(SYSROOT)/usr/src/ps.c 31 | @mkdir -p initrd/bin 32 | $(TOOLCHAIN_PREFIX)linux-musl-gcc -static -O2 -g -o $@ $< -Wall 33 | 34 | initrd/bin/sctl: $(SYSROOT)/usr/src/sctl.c 35 | @mkdir -p initrd/bin 36 | $(TOOLCHAIN_PREFIX)linux-musl-gcc -static -O2 -g -o $@ $< -Wall 37 | 38 | initrd/bin/syslogd: $(SYSROOT)/usr/src/syslogd.c 39 | @mkdir -p initrd/bin 40 | $(TOOLCHAIN_PREFIX)linux-musl-gcc -static -O2 -g -o $@ $< -Wall 41 | 42 | include $(SYSROOT)/usr/src/cond/include.mk 43 | MAKEFILES+=$(SYSROOT)/usr/src/cond/include.mk 44 | 45 | clean_progs: 46 | -rm $(USRPROGS) 47 | 48 | -------------------------------------------------------------------------------- /sysroot/usr/src/init.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | int main() 13 | { 14 | sigset_t set; 15 | int status; 16 | 17 | if (getpid() != 1) return 1; 18 | 19 | sigfillset(&set); 20 | sigprocmask(SIG_BLOCK, &set, 0); 21 | 22 | if (fork()) { 23 | for (;;) wait(&status); 24 | } 25 | 26 | sigprocmask(SIG_UNBLOCK, &set, 0); 27 | 28 | setsid(); 29 | setpgid(0, 0); 30 | 31 | switch(fork()) { 32 | int logfd; 33 | case 0: 34 | logfd = open("/dev/com0", O_RDWR); 35 | if(logfd == -1) 36 | exit(1); 37 | dup2(logfd, 0); 38 | dup2(logfd, 1); 39 | dup2(logfd, 2); 40 | execl("/bin/syslogd", "syslogd", (char *)NULL); 41 | exit(1); 42 | case -1: 43 | return 1; 44 | } 45 | 46 | int fd; 47 | while((fd = open("/dev/log", O_WRONLY)) == -1) 48 | ; 49 | close(fd); 50 | 51 | openlog("init", 0, LOG_DAEMON); 52 | 53 | syslog(LOG_NOTICE, "mounting root"); 54 | 55 | if(mount("/dev/ada0", "/mnt", NULL, 0, NULL) == -1) { 56 | syslog(LOG_EMERG, "failed to mount root device: %s", strerror(errno)); 57 | exit(1); 58 | } 59 | mkdir("/mnt/dev", 0777); 60 | if(mount("/dev", "/mnt/dev", NULL, MS_BIND, NULL) == -1) { 61 | syslog(LOG_EMERG, "failed to remount devfs: %s", strerror(errno)); 62 | exit(1); 63 | } 64 | 65 | mkdir("/mnt/proc", 0777); 66 | if(mount("/proc", "/mnt/proc", NULL, MS_BIND, NULL) == -1) { 67 | syslog(LOG_EMERG, "failed to remount procfs: %s", strerror(errno)); 68 | exit(1); 69 | } 70 | 71 | 72 | syslog(LOG_NOTICE, "chrooting"); 73 | if(chdir("/mnt") == -1) { 74 | syslog(LOG_EMERG, "failed to chdir: %s", strerror(errno)); 75 | exit(1); 76 | } 77 | if(chroot("/mnt") == -1) { 78 | syslog(LOG_EMERG, "failed to chroot: %s", strerror(errno)); 79 | exit(1); 80 | } 81 | 82 | mkdir("/tmp", 0777); 83 | //mount(NULL, "/tmp", "ramfs", 0, NULL); 84 | return execl("/bin/cond", "cond", "-a", "bash --login", "-1", "bash --login", (char *)NULL); 85 | } 86 | 87 | -------------------------------------------------------------------------------- /sysroot/usr/src/lookup.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | int main(int argc, char *argv[]) 11 | { 12 | struct addrinfo hints; 13 | struct addrinfo *result, *rp; 14 | int sfd, s; 15 | struct sockaddr_storage peer_addr; 16 | socklen_t peer_addr_len; 17 | ssize_t nread; 18 | 19 | if (argc != 2) { 20 | fprintf(stderr, "Usage: %s name\n", argv[0]); 21 | exit(EXIT_FAILURE); 22 | } 23 | 24 | memset(&hints, 0, sizeof(struct addrinfo)); 25 | hints.ai_family = AF_INET6; 26 | hints.ai_socktype = 0; 27 | hints.ai_flags = AI_CANONNAME | AI_V4MAPPED; 28 | hints.ai_protocol = 0; 29 | hints.ai_canonname = NULL; 30 | hints.ai_addr = NULL; 31 | hints.ai_next = NULL; 32 | 33 | s = getaddrinfo(argv[1], NULL, &hints, &result); 34 | if (s != 0) { 35 | fprintf(stderr, "getaddrinfo: %d: %s\n", s, gai_strerror(s)); 36 | exit(EXIT_FAILURE); 37 | } 38 | 39 | for (rp = result; rp != NULL; rp = rp->ai_next) { 40 | char buf[128]; 41 | struct sockaddr_in6 *sa = (void *)rp->ai_addr; 42 | printf("%s\n", inet_ntop(AF_INET6, &sa->sin6_addr, buf, 128)); 43 | } 44 | return 0; 45 | } 46 | 47 | -------------------------------------------------------------------------------- /sysroot/usr/src/ps.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | bool all = false; 10 | 11 | static bool give_up; 12 | #define HASH_SIZE (1 << 16) 13 | static int seen[HASH_SIZE]; 14 | 15 | static bool saw_this_pid(int pid) 16 | { 17 | pid++; 18 | if(give_up) 19 | return false; 20 | 21 | uint32_t idx = ((uint32_t)pid * (uint32_t)2654435761u); 22 | for(uint32_t i=0;ipw_name : "???", link); 82 | } 83 | 84 | static void print_procs(void) 85 | { 86 | DIR *dir = opendir("/proc"); 87 | struct dirent *de; 88 | printf(" PID USER EXECUTABLE\n"); 89 | while((de = readdir(dir))) { 90 | int pid, end; 91 | int r = sscanf(de->d_name, "%d%n", &pid, &end); 92 | if(r == 1 && end == strlen(de->d_name)) { 93 | print_proc(pid); 94 | } 95 | } 96 | } 97 | 98 | int main(int argc, char **argv) 99 | { 100 | int c; 101 | while((c = getopt(argc, argv, "a")) != EOF) { 102 | switch(c) { 103 | case 'a': 104 | all = true; 105 | } 106 | } 107 | 108 | print_procs(); 109 | 110 | return 0; 111 | } 112 | 113 | -------------------------------------------------------------------------------- /sysroot/usr/src/pswitch.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | void *rxbuf, *txbuf, *ctlbuf; 10 | 11 | int main(int argc, char **argv) 12 | { 13 | int rfd = open("/dev/lo", O_RDWR); 14 | rxbuf = mmap(NULL, 0x1000 * 32, PROT_READ, MAP_PRIVATE, rfd, 0); 15 | txbuf = mmap(NULL, 0x1000 * 32, PROT_READ | PROT_WRITE, MAP_PRIVATE, rfd, 0x1000); 16 | ctlbuf = mmap(NULL, 0x1000 * 32, PROT_READ | PROT_WRITE, MAP_PRIVATE, rfd, 0x2000); 17 | 18 | strcpy(txbuf, "Hello, World!"); 19 | size_t pos = 1; 20 | ioctl(rfd, 1, &pos); 21 | 22 | size_t rp = 0; 23 | while(rp == 0) { 24 | ioctl(rfd, 2, &rp); 25 | printf(":: %ld\n", rp); 26 | printf("-> %s\n", (char *)rxbuf); 27 | } 28 | } 29 | 30 | -------------------------------------------------------------------------------- /sysroot/usr/src/sctl.c: -------------------------------------------------------------------------------- 1 | int main(int argc, char **argv) 2 | { 3 | if(argc == 1) 4 | return 0; 5 | 6 | switch(argv[1][0]) { 7 | case '0': 8 | syscall(512); 9 | } 10 | return 0; 11 | } 12 | 13 | -------------------------------------------------------------------------------- /sysroot/usr/src/syslogd.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | int handle_client(int client) 11 | { 12 | char buffer[1024]; 13 | ssize_t amount = read(client, buffer, 1023); 14 | if(amount < 0 && errno == EAGAIN) { 15 | return 0; 16 | } 17 | if(amount < 0) { 18 | perror("read from client"); 19 | return -1; 20 | } else if(amount == 0) { 21 | close(client); 22 | return -1; 23 | } 24 | buffer[amount] = 0; 25 | fprintf(stderr, "%s", buffer); 26 | return 0; 27 | } 28 | 29 | int main(int argc, char **argv) 30 | { 31 | (void)argc; 32 | (void)argv; 33 | 34 | fprintf(stderr, "Hello world from syslogd!\n"); 35 | unlink("/dev/log"); 36 | 37 | int master = socket(AF_UNIX, SOCK_STREAM, 0); 38 | printf("Started syslogd with socket %d\n", master); 39 | struct sockaddr_un addr = { 40 | AF_UNIX, "/dev/log" 41 | }; 42 | 43 | if(bind(master, (struct sockaddr *)&addr, sizeof(addr)) == -1) { 44 | perror("bind"); 45 | exit(1); 46 | } 47 | 48 | if(listen(master, 20) == -1) { 49 | perror("listen"); 50 | exit(1); 51 | } 52 | 53 | fd_set active_fds, read_fds, err_fds; 54 | FD_ZERO(&active_fds); 55 | FD_SET(master, &active_fds); 56 | while(true) { 57 | read_fds = active_fds; 58 | err_fds = active_fds; 59 | select(FD_SETSIZE, &read_fds, NULL, &err_fds, NULL); 60 | for(int i=0;i 0) { 68 | FD_SET(client, &active_fds); 69 | } else { 70 | perror("accept"); 71 | } 72 | int flags; 73 | if((flags = fcntl(client, F_GETFL)) < 0) { 74 | perror("fcntl"); 75 | FD_CLR(client, &active_fds); 76 | } else { 77 | if(fcntl(client, F_SETFL, flags | O_NONBLOCK) < 0) { 78 | perror("fcntl"); 79 | FD_CLR(client, &active_fds); 80 | } 81 | } 82 | } else { 83 | if(handle_client(i) < 0) { 84 | close(i); 85 | FD_CLR(i, &active_fds); 86 | } 87 | } 88 | } else if(FD_ISSET(i, &err_fds)) { 89 | if(i == master) { 90 | fprintf(stderr, "syslogd: found error condition on /dev/log.\n"); 91 | } else { 92 | fprintf(stderr, "closing client %d due to error\n", i); 93 | close(i); 94 | FD_CLR(i, &active_fds); 95 | } 96 | } 97 | } 98 | 99 | } 100 | 101 | return 0; 102 | } 103 | 104 | -------------------------------------------------------------------------------- /sysroot/usr/src/thr.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #define N 3 6 | #define P 1 7 | static _Atomic int done[N] = { 0 }; 8 | 9 | pthread_mutex_t lock; 10 | int t = 0; 11 | void sync_printf(const char *format, ...) 12 | { 13 | va_list args; 14 | va_start(args, format); 15 | 16 | pthread_mutex_lock(&lock); 17 | vprintf(format, args); 18 | t++; 19 | pthread_mutex_unlock(&lock); 20 | 21 | va_end(args); 22 | } 23 | 24 | void *func(void *d) 25 | { 26 | int id = (int)(long)d; 27 | for(int i=0;i 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #define MAXBUF 65536 12 | 13 | int main() 14 | { 15 | int sock; 16 | int status; 17 | struct sockaddr_in6 sin6; 18 | int sin6len; 19 | char buffer[MAXBUF]; 20 | 21 | sock = socket(PF_INET6, SOCK_DGRAM,0); 22 | 23 | sin6len = sizeof(struct sockaddr_in6); 24 | printf(":: %d %d %d %d\n", sin6len, sizeof(sa_family_t), sizeof(struct in6_addr), sizeof(in_port_t)); 25 | 26 | memset(&sin6, 0, sin6len); 27 | 28 | /* just use the first address returned in the structure */ 29 | 30 | sin6.sin6_port = htons(1234); 31 | sin6.sin6_family = AF_INET6; 32 | sin6.sin6_addr = in6addr_any; 33 | 34 | struct ifreq ifr; 35 | memset(&ifr, 0, sizeof(ifr)); 36 | snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "nic0"); 37 | if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr)) < 0) { 38 | perror(":("); 39 | } 40 | 41 | 42 | status = bind(sock, (struct sockaddr *)&sin6, sin6len); 43 | if(-1 == status) 44 | perror("bind"), exit(1); 45 | 46 | status = getsockname(sock, (struct sockaddr *)&sin6, &sin6len); 47 | 48 | printf("%d\n", ntohs(sin6.sin6_port)); 49 | 50 | while(1) { 51 | status = recvfrom(sock, buffer, MAXBUF, 0, 52 | (struct sockaddr *)&sin6, &sin6len); 53 | printf("buffer : %s\n", buffer); 54 | const char *res = "This is a response!\n"; 55 | sendto(sock, res, strlen(res), 0, (struct sockaddr *)&sin6, sin6len); 56 | } 57 | shutdown(sock, 2); 58 | close(sock); 59 | return 0; 60 | } 61 | 62 | -------------------------------------------------------------------------------- /tests/build-opts-test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | export QEMU_FLAGS+=-no-reboot 3 | INIT_QF=$QEMU_FLAGS 4 | change_option() { 5 | sed -i -e "s/$1=$2/$1=$3/g" config.cfg 6 | } 7 | 8 | compile() { 9 | echo ' * Compiling...' 10 | if ! make clean all -j6 &> test.log; then 11 | echo COMPILE FAILED 12 | exit 1 13 | fi 14 | } 15 | 16 | test() { 17 | echo ' *' "Testing ($INIT_QF $@)..." 18 | QEMU_FLAGS="$INIT_QF $@" make test > test.log & 19 | echo "test!" > /tmp/test_fifo 20 | sleep 0.1 21 | echo '````````````````' >> /tmp/test_fifo 22 | echo '````````````````' >> /tmp/test_fifo 23 | wait 24 | sleep 0.1 25 | if ! (tail -n4 test.log | grep '==TESTS PASSED=='); then 26 | echo TEST FAILED 27 | exit 1 28 | fi 29 | } 30 | 31 | run_tests() { 32 | rm /tmp/test_fifo 33 | mkfifo /tmp/test_fifo 34 | compile 35 | for var in "$@"; do 36 | test $var 37 | done 38 | } 39 | 40 | function finish { 41 | echo Cleaning up... 42 | cp config.cfg.old config.cfg 43 | } 44 | trap finish EXIT 45 | 46 | cp config.cfg config.cfg.old 47 | make clean 48 | main_tests() { 49 | cp config.cfg config.cfg.old 50 | echo Resetting tests... 51 | change_option CONFIG_RUN_TESTS n y 52 | change_option CONFIG_UBSAN n y 53 | change_option CONFIG_BUILD_LTO y n 54 | change_option CONFIG_BUILD_WERROR n y 55 | change_option CONFIG_DEBUG n y 56 | 57 | echo 'Clang, -O3' 58 | change_option CONFIG_BUILD_CLANG n y 59 | change_option CONFIG_BUILD_OPTIMIZATION 0 3 60 | change_option CONFIG_BUILD_OPTIMIZATION 1 3 61 | change_option CONFIG_BUILD_OPTIMIZATION 2 3 62 | change_option CONFIG_BUILD_OPTIMIZATION s 3 63 | change_option CONFIG_BUILD_OPTIMIZATION g 3 64 | change_option CONFIG_BUILD_OPTIMIZATION fast 3 65 | run_tests "$@" 66 | 67 | echo 'Clang, -Os' 68 | change_option CONFIG_BUILD_OPTIMIZATION 3 s 69 | run_tests "$@" 70 | 71 | echo 'Clang, -O0' 72 | change_option CONFIG_BUILD_OPTIMIZATION s 0 73 | run_tests "$@" 74 | 75 | echo 'GCC, -O0' 76 | change_option CONFIG_BUILD_CLANG y n 77 | run_tests "$@" 78 | 79 | echo 'GCC, -Os' 80 | change_option CONFIG_BUILD_OPTIMIZATION 0 s 81 | run_tests "$@" 82 | 83 | echo 'GCC, -O3' 84 | change_option CONFIG_BUILD_OPTIMIZATION s 3 85 | run_tests "$@" 86 | 87 | #change_option CONFIG_UBSAN y n 88 | #echo 'GCC, -O3, LTO' 89 | #change_option CONFIG_BUILD_LTO n y 90 | #run_tests "$@" 91 | 92 | #echo 'GCC, -Os, LTO' 93 | #change_option CONFIG_BUILD_OPTIMIZATION 3 s 94 | #run_tests "$@" 95 | 96 | #echo 'GCC, -O0, LTO' 97 | #change_option CONFIG_BUILD_OPTIMIZATION s 0 98 | #run_tests "$@" 99 | } 100 | 101 | if [ "$#" -eq 0 ]; then 102 | main_tests " " "-smp 2" "-enable-kvm" "-enable-kvm -smp 4" 103 | else 104 | main_tests "$@" 105 | fi 106 | 107 | -------------------------------------------------------------------------------- /tools/qemu-ifup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ip link set up dev tap0 3 | ip addr add 10.0.0.1/8 dev tap0 4 | ip addr add fe80::1 dev tap0 5 | 6 | -------------------------------------------------------------------------------- /tools/strip-all.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | cd sysroot 3 | LIST=$(find . -executable -type f -exec file {} \; | grep -i elf | sed -r 's/^([^:]+):.*$/\1/p') 4 | for i in $LIST; do 5 | x86_64-elf-linux-musl-strip --strip-all $i 6 | done 7 | --------------------------------------------------------------------------------