├── kernel ├── dev │ └── chr │ │ ├── pty │ │ ├── pts.c │ │ ├── ptmx.c │ │ └── ptmxdev.c │ │ ├── cpu │ │ └── cpu.c │ │ ├── console │ │ ├── earlycons.c │ │ └── console.c │ │ ├── timers │ │ └── timers.c │ │ ├── ps2 │ │ ├── kbd.c │ │ └── mouse.c │ │ └── pseudodev │ │ ├── null.c │ │ ├── zero.c │ │ ├── full.c │ │ └── random.c ├── include │ ├── core │ │ ├── module.h │ │ ├── misc.h │ │ ├── jiffies.h │ │ └── swap.h │ ├── sync │ │ ├── assert.h │ │ ├── cond.h │ │ └── preempt.h │ ├── arch │ │ ├── x86_64 │ │ │ ├── signal.h │ │ │ ├── cpu.h │ │ │ ├── thread.h │ │ │ ├── ipi.h │ │ │ ├── context.h │ │ │ ├── isr.h │ │ │ └── system.h │ │ ├── types.h │ │ ├── chipset.h │ │ ├── signal.h │ │ ├── lapic.h │ │ ├── firmware │ │ │ └── bios.h │ │ ├── traps.h │ │ ├── ucontext.h │ │ └── thread.h │ ├── dev │ │ ├── uart.h │ │ ├── console.h │ │ ├── rtc.h │ │ ├── limeterm.h │ │ ├── cga.h │ │ ├── hpet.h │ │ ├── clocks.h │ │ ├── pty.h │ │ └── fb.h │ ├── sys │ │ ├── sleep.h │ │ ├── sysprot.h │ │ ├── mman │ │ │ └── mman.h │ │ ├── sysproc.h │ │ └── _utsname.h │ ├── lib │ │ ├── stdlib.h │ │ ├── ctype.h │ │ ├── stdint.h │ │ ├── stdnoreturn.h │ │ ├── stdalign.h │ │ ├── stdbool.h │ │ └── string.h │ ├── bits │ │ ├── utsname.h │ │ ├── fcntl.h │ │ ├── dirent.h │ │ ├── waitflags.h │ │ └── waitstatus.h │ ├── ginger │ │ └── types.h │ ├── video │ │ └── lfbterm.h │ ├── mm │ │ ├── pmm.h │ │ ├── page_flags.h │ │ ├── vmm.h │ │ └── kalloc.h │ ├── font │ │ └── tinyfont.h │ ├── fs │ │ ├── fcntl.h │ │ ├── ramfs2.h │ │ ├── cred.h │ │ ├── sysfs.h │ │ ├── procfs.h │ │ ├── tmpfs.h │ │ ├── devtmpfs.h │ │ ├── mount.h │ │ └── icache.h │ ├── ds │ │ ├── stack.h │ │ ├── ringbuf.h │ │ └── hash.h │ ├── modules │ │ └── module.h │ └── boot │ │ └── boot.h ├── sys │ ├── threads │ │ ├── proc.c │ │ └── tgroup_suspend.c │ ├── signals │ │ ├── sigpending.c │ │ ├── alarm.c │ │ └── sigaction.c │ ├── syscall │ │ ├── time.c │ │ ├── proc.c │ │ ├── misc.c │ │ ├── fork.c │ │ └── exit.c │ └── sleep.c ├── core │ ├── misc.c │ ├── modules.c │ ├── jiffies.c │ ├── swap.c │ └── clock.c ├── fs │ ├── vfs_threads.c │ ├── mkdir.c │ ├── mknod.c │ └── devtmpfs │ │ └── devtmpfs.c ├── arch │ ├── signal.c │ ├── x86_64 │ │ ├── ipi.c │ │ ├── swtch.asm │ │ └── trampoline.asm │ ├── chipset │ │ ├── pit.c │ │ └── pic.c │ ├── thread.c │ └── firmware │ │ └── acpi.c ├── boot │ ├── multiboot.asm │ └── init.c ├── mm │ └── liballoc │ │ └── liballoc_hooks.c ├── test │ └── test_threads.c ├── kernel.ld ├── lib │ └── ctype.c ├── sync │ └── cond.c └── kernel.c ├── usr ├── lib │ ├── stdlib │ │ ├── errno.c │ │ ├── labs.c │ │ ├── atof.c │ │ ├── abort.c │ │ ├── bsearch.c │ │ ├── atexit.c │ │ ├── rand.c │ │ ├── div.c │ │ └── qsort.c │ ├── stdio │ │ ├── perror.c │ │ ├── puts.c │ │ ├── tmpfile.c │ │ └── scanf.c │ ├── lib.c │ ├── wchar │ │ ├── wcslen.c │ │ ├── wcscpy.c │ │ ├── wcsncpy.c │ │ ├── wcscmp.c │ │ ├── wcscat.c │ │ ├── wcstok.c │ │ └── wcstol.c │ ├── liballoc_hooks.c │ └── ctype.c ├── include │ ├── types.h │ ├── errno.h │ ├── termios.h │ ├── termio.h │ ├── ginger │ │ ├── ginger.h │ │ ├── rtc.h │ │ ├── liballoc_1_1.h │ │ └── spinlock.h │ ├── sys │ │ ├── mount.h │ │ ├── shm.h │ │ ├── fswait.h │ │ ├── times.h │ │ ├── ioctl.h │ │ ├── param.h │ │ ├── ptrace.h │ │ ├── utsname.h │ │ ├── time.h │ │ ├── mman.h │ │ ├── types.h │ │ └── system.h │ ├── _cheader.h │ ├── setjmp.h │ ├── ctype.h │ ├── utime.h │ ├── bits │ │ ├── utsname.h │ │ ├── fcntl.h │ │ ├── dirent.h │ │ ├── waitflags.h │ │ ├── waitstatus.h │ │ └── stat.h │ ├── api.h │ ├── stdnoreturn.h │ ├── wchar.h │ ├── stdalign.h │ ├── time.h │ ├── stdbool.h │ ├── string.h │ └── stdlib.h ├── start.asm ├── app │ ├── shell.c │ ├── test.c │ └── init.c └── linker.ld ├── font.tf ├── mkdisk ├── ramfs ├── font.tf ├── Vera.sfn ├── chrome.sfn └── kernel.ld ├── screenshots ├── qemu0.png └── vbox0.png ├── CONTRIBUTING.md ├── iso └── boot │ └── grub │ └── grub.cfg ├── .gitignore ├── LICENSE └── roadmap.md /kernel/dev/chr/pty/pts.c: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /usr/lib/stdlib/errno.c: -------------------------------------------------------------------------------- 1 | int errno = 0; -------------------------------------------------------------------------------- /kernel/include/core/module.h: -------------------------------------------------------------------------------- 1 | #pragma once -------------------------------------------------------------------------------- /usr/include/types.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include -------------------------------------------------------------------------------- /usr/include/errno.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include -------------------------------------------------------------------------------- /kernel/include/sync/assert.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include -------------------------------------------------------------------------------- /usr/include/termios.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | -------------------------------------------------------------------------------- /font.tf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Emment-Yamikani/gingerOs-x86_64/HEAD/font.tf -------------------------------------------------------------------------------- /mkdisk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Emment-Yamikani/gingerOs-x86_64/HEAD/mkdisk -------------------------------------------------------------------------------- /ramfs/font.tf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Emment-Yamikani/gingerOs-x86_64/HEAD/ramfs/font.tf -------------------------------------------------------------------------------- /usr/include/termio.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | -------------------------------------------------------------------------------- /usr/lib/stdlib/labs.c: -------------------------------------------------------------------------------- 1 | long int labs(long int j) { 2 | return (j < 0) ? -j : j; 3 | } 4 | -------------------------------------------------------------------------------- /kernel/include/arch/x86_64/signal.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | extern void x86_64_signal_return(void); -------------------------------------------------------------------------------- /kernel/include/dev/uart.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | int uart_putc(char c); 4 | int uart_dev_init(void); -------------------------------------------------------------------------------- /ramfs/Vera.sfn: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Emment-Yamikani/gingerOs-x86_64/HEAD/ramfs/Vera.sfn -------------------------------------------------------------------------------- /ramfs/chrome.sfn: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Emment-Yamikani/gingerOs-x86_64/HEAD/ramfs/chrome.sfn -------------------------------------------------------------------------------- /kernel/include/arch/x86_64/cpu.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | int bsp_init(void); -------------------------------------------------------------------------------- /screenshots/qemu0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Emment-Yamikani/gingerOs-x86_64/HEAD/screenshots/qemu0.png -------------------------------------------------------------------------------- /screenshots/vbox0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Emment-Yamikani/gingerOs-x86_64/HEAD/screenshots/vbox0.png -------------------------------------------------------------------------------- /kernel/include/core/misc.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | 6 | extern void bzero(void *b, usize sz); -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributions 2 | 3 | Contributions to this Repo will be invited as soon as the base project is stable ;). 4 | -------------------------------------------------------------------------------- /kernel/include/sys/sleep.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | long sleep(long); 6 | 7 | int park(void); 8 | int unpark(tid_t); -------------------------------------------------------------------------------- /usr/include/ginger/ginger.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | typedef struct meminfo_t { 4 | size_t free; 5 | size_t used; 6 | } meminfo_t; -------------------------------------------------------------------------------- /usr/lib/stdlib/atof.c: -------------------------------------------------------------------------------- 1 | /* Really bad atof */ 2 | 3 | #include 4 | 5 | double atof(const char * nptr) { 6 | return strtod(nptr, NULL); 7 | } 8 | -------------------------------------------------------------------------------- /usr/lib/stdlib/abort.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void abort(void) { 5 | sys_exit(-1); 6 | __builtin_unreachable(); 7 | } 8 | -------------------------------------------------------------------------------- /kernel/dev/chr/cpu/cpu.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | static int cpudev_init(void) { 5 | return 0; 6 | } 7 | 8 | MODULE_INIT(cpu, NULL, cpudev_init, NULL); -------------------------------------------------------------------------------- /usr/lib/stdio/perror.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void perror(const char *s) { 5 | fprintf(stderr, "%s: %s\n", s, strerror(errno)); 6 | } 7 | -------------------------------------------------------------------------------- /kernel/sys/threads/proc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | 8 | -------------------------------------------------------------------------------- /usr/lib/lib.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | dev_t mkdev(int major, int minor) { 4 | return ((devid_t)(((devid_t)(minor) << 8) & 0xff00) | ((devid_t)(major) & 0xff)); 5 | } -------------------------------------------------------------------------------- /kernel/include/arch/types.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | typedef union pte pte_t; 4 | typedef union viraddr viraddr_t; 5 | typedef struct __context_t context_t; -------------------------------------------------------------------------------- /usr/lib/wchar/wcslen.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | size_t wcslen(const wchar_t * s) { 4 | size_t out = 0; 5 | while (*s) { 6 | out++; 7 | s++; 8 | } 9 | return out; 10 | } 11 | -------------------------------------------------------------------------------- /iso/boot/grub/grub.cfg: -------------------------------------------------------------------------------- 1 | set timeout=1 2 | set default=0 3 | 4 | menuentry "gingerOS"{ 5 | multiboot --quirk-modules-after-kernel /boot/lime.elf 6 | module /modules/ramfs ramfs2 7 | boot 8 | } -------------------------------------------------------------------------------- /kernel/core/misc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void bzero(void *b, usize sz) { 6 | assert(b, "No block\n"); 7 | memset(b, 0, sz); 8 | } -------------------------------------------------------------------------------- /kernel/include/dev/console.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | extern int earlycons_use_gfx; 4 | extern int use_earlycons; 5 | 6 | void earlycons_usefb(void); 7 | int earlycons_putc(int c); 8 | 9 | int console_putc(int c); -------------------------------------------------------------------------------- /usr/include/sys/mount.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include <_cheader.h> 4 | 5 | _Begin_C_Header 6 | extern int mount(char * source, char * target, char * type, unsigned long flags, void * data); 7 | _End_C_Header 8 | -------------------------------------------------------------------------------- /kernel/include/lib/stdlib.h: -------------------------------------------------------------------------------- 1 | #ifndef CORE_STDLIB 2 | #define CORE_STDLIB 1 3 | 4 | #define RAND_MAX 2147483647 5 | 6 | extern int rand(void); 7 | extern void srand(unsigned int __seed); 8 | 9 | #endif // CORE_STDLIB -------------------------------------------------------------------------------- /usr/lib/stdio/puts.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int puts(const char *s) { 5 | /* eof? */ 6 | fwrite(s, 1, strlen(s), stdout); 7 | fwrite("\n", 1, 1, stdout); 8 | return 0; 9 | } 10 | -------------------------------------------------------------------------------- /usr/lib/wchar/wcscpy.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | wchar_t * wcscpy(wchar_t * restrict dest, const wchar_t * restrict src) { 4 | wchar_t * out = dest; 5 | for (; (*dest=*src); src++, dest++); 6 | return out; 7 | } 8 | -------------------------------------------------------------------------------- /usr/include/_cheader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef __cplusplus 4 | # define _Begin_C_Header extern "C" { 5 | # define _End_C_Header } 6 | #else 7 | # define _Begin_C_Header 8 | # define _End_C_Header 9 | #endif 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /iso/boot/*.elf 2 | /iso/modules/* 3 | /.vscode 4 | serial.log 5 | serial0.log 6 | lime.asm 7 | serial 8 | /ramfs/* 9 | /usr/*/*.o 10 | /usr/*/*.so 11 | /usr/*/*.a 12 | /usr/*/*.d 13 | /usr/*/*.a 14 | *.iso 15 | *.a 16 | *.d 17 | *.o -------------------------------------------------------------------------------- /usr/start.asm: -------------------------------------------------------------------------------- 1 | bits 64 2 | 3 | extern main 4 | global start 5 | extern sys_exit 6 | 7 | section .text 8 | start: 9 | call main 10 | mov rdi, rax 11 | call sys_exit 12 | jmp $ 13 | 14 | section .data 15 | .__data_section: db 0 -------------------------------------------------------------------------------- /kernel/include/arch/chipset.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | int ioapic_init(void); 4 | void ioapic_enable(int irq, int cpunum); 5 | 6 | void pic_enable(int irq); 7 | void pic_init(void); 8 | void pit_init(void); 9 | void pit_intr(void); 10 | void pit_wait(double s); -------------------------------------------------------------------------------- /usr/include/sys/shm.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include <_cheader.h> 4 | #include 5 | 6 | _Begin_C_Header 7 | extern void * shm_obtain(const char * path, size_t * size); 8 | extern int shm_release(const char * path); 9 | _End_C_Header 10 | 11 | -------------------------------------------------------------------------------- /kernel/sys/signals/sigpending.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | -------------------------------------------------------------------------------- /usr/lib/wchar/wcsncpy.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | wchar_t * wcsncpy(wchar_t * dest, const wchar_t * src, size_t n) { 4 | wchar_t * out = dest; 5 | while (n > 0) { 6 | *dest = *src; 7 | if (!*src) break; 8 | dest++; 9 | src++; 10 | n--; 11 | } 12 | return out; 13 | } 14 | -------------------------------------------------------------------------------- /usr/include/setjmp.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include <_cheader.h> 4 | 5 | _Begin_C_Header 6 | 7 | /* i386 */ 8 | #define _JBLEN 9 9 | 10 | typedef long long jmp_buf[_JBLEN]; 11 | 12 | extern void longjmp(jmp_buf j, int r); 13 | extern int setjmp(jmp_buf j); 14 | 15 | _End_C_Header 16 | -------------------------------------------------------------------------------- /usr/include/sys/fswait.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include <_cheader.h> 4 | 5 | _Begin_C_Header 6 | extern int fswait(int count, int * fds); 7 | extern int fswait2(int count, int * fds, int timeout); 8 | extern int fswait3(int count, int * fds, int timeout, int * out); 9 | _End_C_Header 10 | -------------------------------------------------------------------------------- /usr/include/ctype.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | int isalpha(int); 4 | int isdigit(int); 5 | int isupper(int); 6 | int islower(int); 7 | int toupper(int); 8 | int tolower(int); 9 | int isspace(int); 10 | int isxdigit(int); 11 | int isalphanum(int); 12 | int atoi(const char *); 13 | long atol(const char *); -------------------------------------------------------------------------------- /kernel/include/lib/ctype.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | int isalpha(int); 4 | int isdigit(int); 5 | int isupper(int); 6 | int islower(int); 7 | int toupper(int); 8 | int tolower(int); 9 | int isspace(int); 10 | int isxdigit(int); 11 | int isalphanum(int); 12 | int atoi(const char *); 13 | long atol(const char *); -------------------------------------------------------------------------------- /usr/include/utime.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include <_cheader.h> 4 | #include 5 | 6 | _Begin_C_Header 7 | 8 | struct utimbuf { 9 | time_t actime; 10 | time_t modtime; 11 | }; 12 | 13 | extern int utime(const char *filename, const struct utimbuf *times); 14 | 15 | _End_C_Header 16 | -------------------------------------------------------------------------------- /usr/lib/stdio/tmpfile.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | FILE * tmpfile(void) { 5 | static int tmpfile_num = 1; 6 | 7 | char tmp[100]; 8 | sprintf(tmp, "/tmp/tmp%d.%d", getpid(), tmpfile_num++); 9 | 10 | FILE * out = fopen(tmp, "w+b"); 11 | 12 | unlink(tmp); 13 | 14 | return out; 15 | } 16 | -------------------------------------------------------------------------------- /usr/include/sys/times.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include <_cheader.h> 4 | #include 5 | 6 | _Begin_C_Header 7 | 8 | struct tms { 9 | clock_t tms_utime; 10 | clock_t tms_stime; 11 | clock_t tms_cutime; 12 | clock_t tms_cstime; 13 | }; 14 | 15 | extern clock_t times(struct tms *buf); 16 | 17 | _End_C_Header 18 | -------------------------------------------------------------------------------- /kernel/include/sys/sysprot.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | uid_t getuid(void); 6 | gid_t getgid(void); 7 | uid_t geteuid(void); 8 | gid_t getegid(void); 9 | 10 | int setuid(uid_t uid); 11 | int setgid(gid_t gid); 12 | int seteuid(uid_t euid); 13 | int setegid(gid_t egid); 14 | 15 | int getcwd(char *buf, size_t size); 16 | int chdir(const char *path); -------------------------------------------------------------------------------- /kernel/include/arch/signal.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | int arch_signal_dispatch( 9 | arch_thread_t *tarch, 10 | thread_entry_t entry, 11 | siginfo_t *info, 12 | sigaction_t *sigact 13 | ); 14 | 15 | void arch_signal_return(void); -------------------------------------------------------------------------------- /kernel/include/sys/mman/mman.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | extern int getpagesize(void); 7 | extern void *mmap(void *__addr, size_t __len, int __prot, 8 | int __flags, int __fd, off_t __offset); 9 | 10 | extern int munmap(void *addr, size_t length); 11 | extern int mprotect(void *addr, size_t len, int prot); -------------------------------------------------------------------------------- /usr/include/sys/ioctl.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #define IOCTLDTYPE 0x4F00 6 | 7 | #define IOCTL_DTYPE_UNKNOWN -1 8 | #define IOCTL_DTYPE_FILE 1 9 | #define IOCTL_DTYPE_TTY 2 10 | 11 | #define IOCTLTTYNAME 0x4F01 12 | #define IOCTLTTYLOGIN 0x4F02 13 | #define IOCTLSYNC 0x4F03 14 | 15 | #define IOCTL_PACKETFS_QUEUED 0x5050 16 | 17 | 18 | -------------------------------------------------------------------------------- /usr/include/sys/param.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define __LITTLE_ENDIAN 1234 9 | #define __BIG_ENDIAN 4321 10 | #define __BYTE_ORDER __LITLE_ENDIAN 11 | 12 | #define BIG_ENDIAN __BIG_ENDIAN 13 | #define LITTLE_ENDIAN __LITTLE_ENDIAN 14 | #define BYTE_ORDER __BYTE_ORDER 15 | -------------------------------------------------------------------------------- /usr/include/ginger/rtc.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | typedef struct rtc_time { 6 | uint8_t sec; 7 | uint8_t min; 8 | uint8_t hrs; 9 | uint8_t day; 10 | uint8_t mon; 11 | uint16_t year; 12 | uint8_t cent; 13 | } rtc_time_t; 14 | 15 | #define RTC_GETTIME 0 16 | #define RTC_SETTIME 1 17 | #define RTC_SETALRM 2 -------------------------------------------------------------------------------- /kernel/include/bits/utsname.h: -------------------------------------------------------------------------------- 1 | #ifndef _UTSNAME 2 | #define _UTSNAME 3 | 4 | #define MAX_LENGTH 64 5 | 6 | struct utsname { 7 | char sysname[MAX_LENGTH]; 8 | char nodename[MAX_LENGTH]; 9 | char release[MAX_LENGTH]; 10 | char version[MAX_LENGTH]; 11 | char machine[MAX_LENGTH]; 12 | }; 13 | 14 | int uname(struct utsname *name); 15 | 16 | #endif /* ! _UTSNAME */ 17 | -------------------------------------------------------------------------------- /usr/include/bits/utsname.h: -------------------------------------------------------------------------------- 1 | #ifndef _UTSNAME 2 | #define _UTSNAME 3 | 4 | #define MAX_LENGTH 64 5 | 6 | struct utsname { 7 | char sysname[MAX_LENGTH]; 8 | char nodename[MAX_LENGTH]; 9 | char release[MAX_LENGTH]; 10 | char version[MAX_LENGTH]; 11 | char machine[MAX_LENGTH]; 12 | }; 13 | 14 | int uname(struct utsname *name); 15 | 16 | #endif /* ! _UTSNAME */ 17 | -------------------------------------------------------------------------------- /kernel/include/ginger/types.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | typedef char i8; 4 | typedef short i16; 5 | typedef int i32; 6 | typedef long i64; 7 | typedef long isize; 8 | 9 | typedef unsigned char u8; 10 | typedef unsigned short u16; 11 | typedef unsigned int u32; 12 | typedef unsigned long u64; 13 | typedef unsigned long usize; 14 | -------------------------------------------------------------------------------- /kernel/sys/syscall/time.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | 9 | 10 | int gettimeofday(struct timeval *restrict tp, void *restrict tzp __unused) { 11 | time_t time = rtc_gettime(); 12 | tp->tv_usec = 0; 13 | tp->tv_sec = time; 14 | return 0; 15 | } -------------------------------------------------------------------------------- /kernel/include/arch/lapic.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | extern int lapic_id(void); 7 | extern int lapic_init(void); 8 | extern void lapic_eoi(void); 9 | extern void lapic_timerintr(void); 10 | // extern void lapic_setaddr(uintptr_t); 11 | void lapic_send_ipi(int ipi, int dst); 12 | void lapic_recalibrate(long hz); 13 | extern void lapic_startup(int id, u16 addr); -------------------------------------------------------------------------------- /kernel/include/lib/stdint.h: -------------------------------------------------------------------------------- 1 | #ifndef _GCC_WRAP_STDINT_H 2 | #if __STDC_HOSTED__ 3 | # if defined __cplusplus && __cplusplus >= 201103L 4 | # undef __STDC_LIMIT_MACROS 5 | # define __STDC_LIMIT_MACROS 6 | # undef __STDC_CONSTANT_MACROS 7 | # define __STDC_CONSTANT_MACROS 8 | # endif 9 | # include_next 10 | #else 11 | # include "stdint-gcc.h" 12 | #endif 13 | #define _GCC_WRAP_STDINT_H 14 | #endif 15 | -------------------------------------------------------------------------------- /usr/lib/stdlib/bsearch.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void *bsearch(const void *key, const void *base, size_t nmemb, size_t size, 4 | int (*compar)(const void *, const void *)) { 5 | /* Stupid naive implementation */ 6 | const char * b = base; 7 | size_t i = 0; 8 | while (i < nmemb) { 9 | const void * a = b; 10 | if (!compar(a,key)) return (void *)a; 11 | i++; 12 | b += size; 13 | } 14 | return NULL; 15 | } 16 | -------------------------------------------------------------------------------- /usr/lib/wchar/wcscmp.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int wcscmp(const wchar_t *l, const wchar_t *r) { 4 | for (; *l == *r && *l; l++, r++); 5 | return *(unsigned int *)l - *(unsigned int *)r; 6 | } 7 | 8 | int wcsncmp(const wchar_t *s1, const wchar_t *s2, size_t n) { 9 | if (n == 0) return 0; 10 | 11 | while (n-- && *s1 == *s2) { 12 | if (!n || !*s1) break; 13 | s1++; 14 | s2++; 15 | } 16 | return (*s1) - (*s2); 17 | } 18 | -------------------------------------------------------------------------------- /kernel/include/dev/rtc.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #define RTC_GETTIME 0 6 | #define RTC_SETTIME 1 7 | #define RTC_SETALM 2 8 | 9 | typedef struct rtc_time { 10 | uint8_t rtc_sec; 11 | uint8_t rtc_min; 12 | uint8_t rtc_hrs; 13 | uint8_t rtc_day; 14 | uint8_t rtc_mon; 15 | uint16_t rtc_year; 16 | uint8_t rtc_cent; 17 | } rtc_time_t; 18 | 19 | void rtc_intr(void); 20 | usize rtc_gettime(void); -------------------------------------------------------------------------------- /kernel/include/sys/sysproc.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | pid_t fork(void); 6 | void exit(int exit_code); 7 | pid_t getpid(void); 8 | pid_t getppid(void); 9 | 10 | pid_t getsid(pid_t pid); 11 | int setsid(void); 12 | pid_t getpgrp(void); 13 | int setpgrp(void); 14 | int getpgid(pid_t pid); 15 | pid_t setpgid(pid_t pid, pid_t pgid); 16 | 17 | int execve(const char *pathname, char *const argv[], 18 | char *const envp[]); -------------------------------------------------------------------------------- /kernel/include/dev/limeterm.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #define _SC_UP 0xE2 6 | #define _SC_LEFT 0xE4 7 | #define _SC_RIGHT 0xE5 8 | #define _SC_DOWN 0xE3 9 | 10 | int limeterm_init(void); 11 | void limeterm_clrscrn(void); 12 | void limeterm_scroll(void); 13 | void limeterm_putc(int c); 14 | size_t limeterm_puts(const char *s); 15 | void limeterm_sputc(int c); 16 | void limeterm_clrscrn(void); 17 | 18 | extern volatile int use_limeterm_cons; -------------------------------------------------------------------------------- /kernel/sys/syscall/proc.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | pid_t getpid(void) { 4 | return curproc ? curproc->pid : 0; 5 | } 6 | 7 | pid_t getppid(void) { 8 | pid_t pid = 0; 9 | 10 | proc_lock(curproc); 11 | 12 | if (curproc->parent == NULL) { 13 | proc_unlock(curproc); 14 | return -1; 15 | } 16 | 17 | proc_lock(curproc->parent); 18 | pid = curproc->parent->pid; 19 | proc_unlock(curproc->parent); 20 | 21 | return pid; 22 | } -------------------------------------------------------------------------------- /usr/lib/stdlib/atexit.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | static void (*_atexit_handlers[32])(void) = {NULL}; 4 | static int _atexit_count = 0; 5 | 6 | void _handle_atexit(void) { 7 | if (!_atexit_count) return; 8 | do { 9 | _atexit_count--; 10 | _atexit_handlers[_atexit_count](); 11 | } while (_atexit_count); 12 | } 13 | 14 | int atexit(void (*h)(void)) { 15 | if (_atexit_count == ATEXIT_MAX) return 1; 16 | _atexit_handlers[_atexit_count++] = h; 17 | return 0; 18 | } 19 | 20 | -------------------------------------------------------------------------------- /usr/lib/stdlib/rand.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | // #include 4 | 5 | static uint32_t x = 123456789; 6 | static uint32_t y = 362436069; 7 | static uint32_t z = 521288629; 8 | static uint32_t w = 88675123; 9 | 10 | int rand(void) { 11 | uint32_t t; 12 | 13 | t = x ^ (x << 11); 14 | x = y; y = z; z = w; 15 | w = w ^ (w >> 19) ^ t ^ (t >> 8); 16 | 17 | return (w & RAND_MAX); 18 | } 19 | 20 | void srand(unsigned int seed) { 21 | w ^= seed; 22 | } 23 | -------------------------------------------------------------------------------- /kernel/include/core/jiffies.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | typedef unsigned int jiffies32_t; 6 | typedef unsigned long jiffies64_t; 7 | 8 | #if defined (__x86_64__) 9 | typedef jiffies64_t jiffies_t; 10 | #elif (__x86__) 11 | typedef jiffies32_t jiffies_t; 12 | #endif 13 | 14 | extern void jiffies_update(void); 15 | extern jiffies_t jiffies_get(void); 16 | extern void jiffies_wait(jiffies_t jiffies); 17 | extern void jiffies_wait_nosleep(jiffies_t jiffies); -------------------------------------------------------------------------------- /kernel/include/arch/firmware/bios.h: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: Banda Emment Yamikani 3 | * @Date: 2021-12-19 17:11:35 4 | * @Last Modified by: Banda Emment Yamikani 5 | * @Last Modified time: 2021-12-19 18:56:28 6 | */ 7 | #ifndef BIOS_H 8 | #define BIOS_H 9 | 10 | #include 11 | 12 | //bios data area 13 | #define BDA 0x400 14 | //extended bios data area 15 | #define EBDA ((uintptr_t)(*((uint16_t *)(VMA2HI(BDA + 0xe)))) << 4) 16 | //bios rom below 1M 17 | #define BIOSROM 0xe0000 18 | 19 | #endif //BIOS_H -------------------------------------------------------------------------------- /kernel/fs/vfs_threads.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | __noreturn void icache_sync(void) { 5 | BUILTIN_THREAD_ANOUNCE("icache_sync"); 6 | loop() { 7 | jiffies_sleep(5); 8 | } 9 | } 10 | 11 | // BUILTIN_THREAD(icache_sync, icache_sync, NULL); 12 | 13 | 14 | __noreturn void icache_prefetch(void) { 15 | BUILTIN_THREAD_ANOUNCE("PREFETCH thread"); 16 | loop() { 17 | jiffies_sleep(5); 18 | } 19 | } 20 | // BUILTIN_THREAD(icache_prefetch, icache_prefetch, NULL); -------------------------------------------------------------------------------- /usr/app/shell.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void main(void) { 4 | struct utsname name; 5 | char *console = "/dev/console"; 6 | dev_t dev = mkdev(5, 1); 7 | 8 | mknod(console, S_IFCHR | 0777, dev); 9 | 10 | int f = open(console, O_RDWR, 0); 11 | 12 | printf("f is open at: %d\n", f); 13 | 14 | write(f, "Hello, device", 14); 15 | 16 | uname(&name); 17 | 18 | 19 | 20 | printf("[%s-%s %s]$ ", 21 | name.sysname, 22 | name.nodename, 23 | name.sysname 24 | ); 25 | 26 | loop(); 27 | } -------------------------------------------------------------------------------- /kernel/include/core/swap.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | extern void swapi8(char *dst, char *src); 4 | extern void swapi16(short *dst, short *src); 5 | extern void swapi32(int *dst, int *src); 6 | extern void swapi64(long *dst, long *src); 7 | extern void swapptr(void **p0, void **p1); 8 | 9 | extern void swapu8(unsigned char *dst, unsigned char *src); 10 | extern void swapu16(unsigned short *dst, unsigned short *src); 11 | extern void swapu32(unsigned int *dst, unsigned int *src); 12 | extern void swapu64(unsigned long *dst, unsigned long *src); -------------------------------------------------------------------------------- /kernel/arch/signal.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | 6 | void arch_signal_return(void) { 7 | #if defined (__x86_64__) 8 | x86_64_signal_return(); 9 | #endif 10 | } 11 | 12 | int arch_signal_dispatch( 13 | arch_thread_t *thread, 14 | thread_entry_t entry, 15 | siginfo_t *info, 16 | sigaction_t *sigact 17 | ) { 18 | #if defined (__x86_64__) 19 | return x86_64_signal_dispatch( 20 | thread, 21 | entry, 22 | info, 23 | sigact 24 | ); 25 | #endif 26 | } -------------------------------------------------------------------------------- /kernel/include/arch/x86_64/thread.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | extern void x86_64_thread_exit(uintptr_t exit_code); 6 | extern int x86_64_uthread_init(arch_thread_t *arch, thread_entry_t entry, void *arg); 7 | extern int x86_64_kthread_init(arch_thread_t *arch, thread_entry_t entry, void *arg); 8 | extern int x86_64_thread_execve(arch_thread_t *arch, thread_entry_t entry, 9 | int argc, const char *argp[], const char *envp[]); 10 | extern int x86_64_thread_setkstack(arch_thread_t *arch); 11 | extern int x86_64_thread_fork(arch_thread_t *dst, arch_thread_t *src); -------------------------------------------------------------------------------- /kernel/include/video/lfbterm.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define NTTY 4 4 | #define _SC_UP 0xE2 5 | #define _SC_LEFT 0xE4 6 | #define _SC_RIGHT 0xE5 7 | #define _SC_DOWN 0xE3 8 | 9 | extern volatile int use_gfx_cons; 10 | 11 | int lfbterm_init(void); 12 | void lfbterm_putc(int c); 13 | int lfbterm_sputc(int c); 14 | int lfb_console_init(void); 15 | void lfbterm_clrscrn(void); 16 | void lfbterm_savecolor(void); 17 | void lfbterm_restorecolor(void); 18 | int lfbterm_puts(const char *s); 19 | void lfbterm_setcolor(int bg, int fg); 20 | void lfbterm_fill_rect(int x, int y, int w, int h, int color); 21 | -------------------------------------------------------------------------------- /kernel/include/arch/traps.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define IRQ_OFFSET 32 4 | #define IRQ(i) ((i) + IRQ_OFFSET) 5 | 6 | 7 | #define PS2_KBD 1 8 | #define T_FPU_NM 7 9 | #define T_SIMD_XM 19 10 | #define T_PGFAULT 14 11 | #define TLBSHOOTDWN 17 12 | 13 | #define LEG_PIT 2 14 | #define HPET 2 15 | #define IRQ_RTC 8 16 | #define LAPIC_ERROR IRQ(18) 17 | #define LAPIC_SPURIOUS IRQ(19) 18 | #define LAPIC_TIMER IRQ(20) 19 | #define TLB_SHTDWN IRQ(31) 20 | 21 | #define LAPIC_IPI IRQ(32) 22 | 23 | #define T_LEG_SYSCALL 128 24 | -------------------------------------------------------------------------------- /usr/lib/wchar/wcscat.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | wchar_t * wcscat(wchar_t *dest, const wchar_t *src) { 5 | wchar_t * end = dest; 6 | while (*end != 0) { 7 | ++end; 8 | } 9 | while (*src) { 10 | *end = *src; 11 | end++; 12 | src++; 13 | } 14 | *end = 0; 15 | return dest; 16 | } 17 | 18 | wchar_t * wcsncat(wchar_t *dest, const wchar_t * src, size_t n) { 19 | wchar_t * end = dest; 20 | size_t c = 0; 21 | while (*end != 0) { 22 | ++end; 23 | } 24 | while (*src && c < n) { 25 | *end = *src; 26 | end++; 27 | src++; 28 | c++; 29 | } 30 | *end = 0; 31 | return dest; 32 | } 33 | -------------------------------------------------------------------------------- /kernel/include/sync/cond.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | typedef struct cond { 7 | atomic_t count; 8 | queue_t waiters; 9 | spinlock_t guard; 10 | } cond_t; 11 | 12 | #define COND_INIT() ((cond_t){0}) 13 | #define COND_NEW() (&COND_INIT()) 14 | #define COND_VAR(name) cond_t *name = COND_NEW() 15 | 16 | int cond_new(cond_t **ref); 17 | int cond_wait(cond_t *cond); 18 | void cond_free(cond_t *cond); 19 | void cond_signal(cond_t *cond); 20 | void cond_broadcast(cond_t *cond); 21 | int cond_init(cond_t *c, cond_t **ref); 22 | int cond_wait_releasing(cond_t *cond, spinlock_t *lk); -------------------------------------------------------------------------------- /usr/include/sys/ptrace.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include <_cheader.h> 4 | #include 5 | 6 | _Begin_C_Header 7 | 8 | enum __ptrace_request { 9 | PTRACE_ATTACH, 10 | PTRACE_CONT, 11 | PTRACE_DETACH, 12 | PTRACE_TRACEME, 13 | PTRACE_GETREGS, 14 | PTRACE_PEEKDATA, 15 | PTRACE_SIGNALS_ONLY_PLZ, 16 | PTRACE_POKEDATA, 17 | PTRACE_SINGLESTEP 18 | }; 19 | 20 | enum __ptrace_event { 21 | PTRACE_EVENT_SYSCALL_ENTER, 22 | PTRACE_EVENT_SYSCALL_EXIT, 23 | PTRACE_EVENT_SINGLESTEP, 24 | }; 25 | 26 | #ifndef __kernel__ 27 | extern long ptrace(enum __ptrace_request request, pid_t pid, void * addr, void * data); 28 | #endif 29 | 30 | _End_C_Header 31 | -------------------------------------------------------------------------------- /usr/include/bits/fcntl.h: -------------------------------------------------------------------------------- 1 | #ifndef _FCNTL_H 2 | #define _FCNTL_H 1 3 | 4 | #define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR) 5 | 6 | #define O_RDONLY 0x000000 7 | #define O_WRONLY 0x000001 8 | #define O_RDWR 0x000002 9 | #define O_APPEND 0x000008 10 | #define O_CREAT 0x000200 11 | #define O_TRUNC 0x000400 12 | #define O_EXCL 0x000800 13 | #define O_SYNC 0x002000 14 | #define O_DSYNC O_SYNC 15 | #define O_RSYNC O_SYNC 16 | #define O_NONBLOCK 0x004000 17 | #define O_NOCTTY 0x008000 18 | #define O_CLOEXEC 0x040000 19 | #define O_NOFOLLOW 0x100000 20 | #define O_DIRECTORY 0x200000 21 | #define O_EXEC 0x400000 22 | #define O_SEARCH O_EXEC 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /kernel/include/bits/fcntl.h: -------------------------------------------------------------------------------- 1 | #ifndef _FCNTL_H 2 | #define _FCNTL_H 1 3 | 4 | #define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR) 5 | 6 | #define O_RDONLY 0x000000 7 | #define O_WRONLY 0x000001 8 | #define O_RDWR 0x000002 9 | #define O_APPEND 0x000008 10 | #define O_CREAT 0x000200 11 | #define O_TRUNC 0x000400 12 | #define O_EXCL 0x000800 13 | #define O_SYNC 0x002000 14 | #define O_DSYNC O_SYNC 15 | #define O_RSYNC O_SYNC 16 | #define O_NONBLOCK 0x004000 17 | #define O_NOCTTY 0x008000 18 | #define O_CLOEXEC 0x040000 19 | #define O_NOFOLLOW 0x100000 20 | #define O_DIRECTORY 0x200000 21 | #define O_EXEC 0x400000 22 | #define O_SEARCH O_EXEC 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /usr/app/test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void main(void) { 5 | int err = 0; 6 | __unused int pts = 0; 7 | int ptmx = 0; 8 | mode_t mode = S_IFCHR | S_IRUSR | S_IWUSR | 9 | S_IRGRP | S_IWGRP | S_IROTH; 10 | dev_t dev = mkdev(5, 2); 11 | 12 | if ((err = mknod("/dev/ptmx", mode, dev))) 13 | panic("Failed to make device node. err= %d\n", err); 14 | 15 | if ((err = ptmx = open("/dev/ptmx", O_RDWR, 0)) < 0) 16 | panic("Failed to open ptmx,, err: %d\n", err); 17 | 18 | write(ptmx, "Hello world. :)\n", 17); 19 | 20 | panic("Sucessfully opened device\n"); 21 | } -------------------------------------------------------------------------------- /kernel/sys/syscall/misc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int uname (utsname_t *utsname __unused) { 7 | if (utsname == NULL) 8 | return -EFAULT; 9 | 10 | snprintf(utsname->machine, _UTSNAME_LENGTH, "ginger-os-test kit"); 11 | snprintf(utsname->nodename, _UTSNAME_LENGTH, "n/a"); 12 | snprintf(utsname->release, _UTSNAME_LENGTH, "0.0"); 13 | snprintf(utsname->sysname, _UTSNAME_LENGTH, "gingerOs"); 14 | snprintf(utsname->version, _UTSNAME_LENGTH, "0.0"); 15 | 16 | return 0; 17 | } 18 | 19 | 20 | int isatty(int fd __unused) { 21 | return -ENOSYS; 22 | } 23 | -------------------------------------------------------------------------------- /usr/linker.ld: -------------------------------------------------------------------------------- 1 | ENTRY(start) 2 | 3 | SECTIONS { 4 | . = 0x4000000; 5 | phys = .; 6 | 7 | .text BLOCK(4K) : ALIGN(4K) { 8 | code = .; 9 | KEEP (*(.text)) 10 | } 11 | 12 | .rodata BLOCK(4K) : ALIGN(4K) { 13 | KEEP (*(.rodata)) 14 | } 15 | 16 | .data BLOCK(4K) : ALIGN(4K) { 17 | KEEP (*(.data)) 18 | } 19 | 20 | .bss BLOCK(4K) : ALIGN(4K) { 21 | *(COMMON) 22 | KEEP (*(.bss)) 23 | } 24 | 25 | .eh_frame BLOCK(4K) : ALIGN(4K) { 26 | KEEP (*(.eh_frame)) 27 | } 28 | 29 | .init_array : { 30 | PROVIDE_HIDDEN (__init_array_start = .); 31 | *(.init_array); 32 | PROVIDE_HIDDEN (__init_array_end = .); 33 | } 34 | 35 | end = .; 36 | 37 | /DISCARD/ : { 38 | *(.comment) 39 | *(.note.gnu.build-id) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /kernel/arch/x86_64/ipi.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | void tlb_shootdown_handler(void) { 12 | wrcr3(rdcr3()); 13 | } 14 | 15 | int tlb_shootdown(uintptr_t pml4, uintptr_t viraddr) { 16 | (void)pml4; 17 | (void)viraddr; 18 | lapic_send_ipi(TLB_SHTDWN, IPI_ALLXSELF); 19 | return 0; 20 | } 21 | 22 | void send_tlb_shootdown(uintptr_t pml4, uintptr_t viraddr) { 23 | invlpg(viraddr); 24 | tlb_shootdown(pml4, viraddr); 25 | } 26 | 27 | int i64_send_ipi(int dst, int ipi, void *arg0, void *arg1, void *arg2); -------------------------------------------------------------------------------- /kernel/sys/threads/tgroup_suspend.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int tgroup_suspend(queue_t *tgroup) { 4 | tgroup_lock(tgroup); 5 | queue_foreach(thread_t *, thread, tgroup) { 6 | if (current == thread) 7 | continue; 8 | thread_lock(thread); 9 | thread_set_suspend(thread); 10 | thread_unlock(thread); 11 | } 12 | tgroup_unlock(tgroup); 13 | return 0; 14 | } 15 | 16 | int tgroup_unsuspend(queue_t *tgroup) { 17 | tgroup_lock(tgroup); 18 | queue_foreach(thread_t *, thread, tgroup) { 19 | if (current == thread) 20 | continue; 21 | thread_lock(thread); 22 | 23 | thread_unlock(thread); 24 | } 25 | tgroup_unlock(tgroup); 26 | return 0; 27 | } -------------------------------------------------------------------------------- /kernel/include/sync/preempt.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | static inline void pushcli(void) { 11 | uint64_t intena = is_intena(); 12 | cli(); 13 | if (intena) 14 | cpu->intena = intena; 15 | cpu->ncli++; 16 | } 17 | 18 | static inline void popcli(void) { 19 | assert_msg(!is_intena(), "%s:%d: error: interrupts enabled before popcli()!", __FILE__, __LINE__); 20 | assert_msg((cpu->ncli >= 1), "%s:%d: error: ncli == %d\n", __FILE__, __LINE__, cpu->ncli); 21 | if ((--cpu->ncli == 0) && cpu->intena) 22 | { 23 | cpu->intena = 0; 24 | sti(); 25 | } 26 | } -------------------------------------------------------------------------------- /kernel/include/sys/_utsname.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define _UTSNAME_LENGTH 65 4 | 5 | typedef struct utsname { 6 | char sysname[_UTSNAME_LENGTH]; // Name of this implementation of the operating system. 7 | char nodename[_UTSNAME_LENGTH]; // Name of this node within the communications network to which this node is attached, if any. 8 | char release[_UTSNAME_LENGTH]; // Current release level of this implementation. 9 | char version[_UTSNAME_LENGTH]; // Current version level of this release. 10 | char machine[_UTSNAME_LENGTH]; // Name of the hardware type on which the system is running. 11 | } utsname_t; 12 | // The character arrays are of unspecified size, but the data stored in them shall be terminated by a null byte. 13 | 14 | int uname(utsname_t *); -------------------------------------------------------------------------------- /kernel/include/dev/cga.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | extern int use_cga; 7 | 8 | #define CGA_BLACK 0 9 | #define CGA_BLUE 1 10 | #define CGA_GREEN 2 11 | #define CGA_CYAN 3 12 | #define CGA_RED 4 13 | #define CGA_MAGENTA 5 14 | #define CGA_BROWN 6 15 | #define CGA_LIGHT_GREY 7 16 | #define CGA_DARK_GREY 8 17 | #define CGA_LIGHT_BLUE 9 18 | #define CGA_LIGHT_GREEN 10 19 | #define CGA_LIGHT_CYAN 11 20 | #define CGA_LIGHT_RED 12 21 | #define CGA_LIGHT_MAGENTA 13 22 | #define CGA_YELLOW 14 23 | #define CGA_WHITE 15 24 | 25 | int cga_init(void); 26 | void cga_putc(const int); 27 | size_t cga_puts(const char *s); -------------------------------------------------------------------------------- /kernel/core/modules.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int modules_init(void) { 8 | int err = 0; 9 | int retval = 0; 10 | size_t up = 0, valid = 0; 11 | module_sym_t *mod = __builtin_mods; 12 | size_t nr = __builtin_mods_end - __builtin_mods; 13 | 14 | for (size_t i = 0; i < nr; ++i, mod++) { 15 | if (!mod->mod_init) 16 | continue; 17 | valid++; 18 | if ((err = (mod->mod_init)(mod->mod_arg))) 19 | return err; 20 | if (!retval) 21 | up++; 22 | } 23 | 24 | if (up != valid) 25 | printk("WARNING: some devices did not start successfully\n"); 26 | 27 | return 0; 28 | } -------------------------------------------------------------------------------- /kernel/boot/multiboot.asm: -------------------------------------------------------------------------------- 1 | [bits 32] 2 | 3 | MODS_ALIGN EQU (1 << 0) 4 | MEMINFO EQU (1 << 1) 5 | GFXMODE EQU (0 << 2) 6 | MAGIC EQU (0x1BADB002);(0xE85250D6); 7 | FLAGS EQU (MODS_ALIGN | MEMINFO | GFXMODE) 8 | CHECKSUM EQU -(MAGIC + FLAGS) 9 | 10 | section .multiboot 11 | align 4 12 | 13 | mboot: 14 | dd MAGIC 15 | dd FLAGS 16 | dd CHECKSUM 17 | 18 | ; section header info (Not of concern) 19 | 20 | dd 0x00 21 | dd 0x00 22 | dd 0x00 23 | dd 0x00 24 | dd 0x00 25 | 26 | ; gfx parameters 27 | LFB_GFX EQU (0) 28 | EGA_TXT EQU (1) 29 | GFX_WIDTH EQU (1024) 30 | GFX_HEIGHT EQU (768) 31 | GFX_DEPTH EQU (32) 32 | 33 | dd LFB_GFX 34 | dd GFX_WIDTH 35 | dd GFX_HEIGHT 36 | dd GFX_DEPTH 37 | ; -------------------------------------------------------------------------------- /usr/include/sys/utsname.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define _UTSNAME_LENGTH 65 4 | 5 | typedef struct utsname { 6 | char sysname[_UTSNAME_LENGTH]; // Name of this implementation of the operating system. 7 | char nodename[_UTSNAME_LENGTH]; // Name of this node within the communications 8 | // network to which this node is attached, if any. 9 | char release[_UTSNAME_LENGTH]; // Current release level of this implementation. 10 | char version[_UTSNAME_LENGTH]; // Current version level of this release. 11 | char machine[_UTSNAME_LENGTH]; // Name of the hardware type on which the system is running. 12 | } utsname_t; 13 | // The character arrays are of unspecified size, but the data stored in them shall be terminated by a null byte. 14 | 15 | int uname(utsname_t *); -------------------------------------------------------------------------------- /kernel/include/arch/x86_64/ipi.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define NIPI 8 4 | 5 | #define IPI_ALL (-2) // broadcast to all. 6 | #define IPI_SELF (-1) // send to self. 7 | #define IPI_ALLXSELF (-3) // broadcast to all except self. 8 | 9 | #define IPI_SYNC 0 10 | #define IPI_TLBSHTDWN 1 11 | 12 | typedef struct ipi_t { 13 | int src; 14 | void *arg0; 15 | void *arg1; 16 | void *arg2; 17 | } ipi_t; 18 | 19 | typedef struct tlb_entry_t { 20 | uintptr_t pml4; 21 | long count; 22 | uintptr_t viraddr; 23 | } tlb_entry_t; 24 | 25 | void tlb_shootdown_handler(void); 26 | int tlb_shootdown(uintptr_t pml4, uintptr_t viraddr); 27 | void send_tlb_shootdown(uintptr_t pml4, uintptr_t viraddr); 28 | int i64_send_ipi(int dst, int ipi, void *arg0, void *arg1, void *arg2); -------------------------------------------------------------------------------- /usr/lib/stdlib/div.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | div_t div(int numerator, int denominator) { 4 | div_t out; 5 | out.quot = numerator / denominator; 6 | out.rem = numerator % denominator; 7 | 8 | if (numerator >= 0 && out.rem < 0) { 9 | out.quot++; 10 | out.rem -= denominator; 11 | } else if (numerator < 0 && out.rem > 0) { 12 | out.quot--; 13 | out.rem += denominator; 14 | } 15 | 16 | return out; 17 | } 18 | 19 | ldiv_t ldiv(long numerator, long denominator) { 20 | ldiv_t out; 21 | out.quot = numerator / denominator; 22 | out.rem = numerator % denominator; 23 | 24 | if (numerator >= 0 && out.rem < 0) { 25 | out.quot++; 26 | out.rem -= denominator; 27 | } else if (numerator < 0 && out.rem > 0) { 28 | out.quot--; 29 | out.rem += denominator; 30 | } 31 | 32 | return out; 33 | } 34 | -------------------------------------------------------------------------------- /kernel/include/dev/hpet.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | typedef struct 8 | { 9 | int t_id; // timer ID. 10 | unsigned t_flags; // timer operation flags. 11 | uint64_t t_value; // initial counter value. 12 | } hpet_timer_t; 13 | 14 | 15 | #define HPET_TMR_32 BS(0) 16 | #define HPET_TMR_PER BS(1) 17 | #define HPET_TMR_LVL BS(2) 18 | 19 | #define HPET_TMR_IS32(flags) BTEST(flags, 0) 20 | #define HPET_TMR_ISPER(flags) BTEST(flags, 1) 21 | #define HPET_TMR_ISLVL(flags) BTEST(flags, 2) 22 | 23 | int hpet_init(void); 24 | void hpet_intr(void); 25 | long hpet_freq(void); 26 | void hpet_wait(double s); 27 | size_t hpet_rdmcnt(void); 28 | int hpet_timer_init(const hpet_timer_t *tmr); -------------------------------------------------------------------------------- /kernel/include/mm/pmm.h: -------------------------------------------------------------------------------- 1 | #ifndef PMM_H 2 | #define PMM_H 1 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | // physical memory manager entries 11 | struct pmman { 12 | int (*init)(void); // initialize the physical memory manager. 13 | uintptr_t (*alloc)(void); // allocate a 4K page. 14 | void (*free)(uintptr_t); // free a 4K page. 15 | int (*get_page)(gfp_t gfp, void **ppa); 16 | int (*get_pages)(gfp_t gfp, size_t order, void **ppa); 17 | size_t (*mem_used)(void); // used space (in KBs). 18 | size_t (*mem_free)(void); // free space (in KBs). 19 | }; 20 | 21 | extern struct pmman pmman; 22 | 23 | int physical_memory_init(void); 24 | 25 | #endif //PMM_H -------------------------------------------------------------------------------- /usr/include/api.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | // #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | dev_t mkdev(int major, int minor); -------------------------------------------------------------------------------- /usr/include/bits/dirent.h: -------------------------------------------------------------------------------- 1 | #ifndef _BITS_DIRENT_H 2 | #define _BITS_DIRENT_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #define MAX_NAME_LEN 256 9 | 10 | 11 | struct dirent { 12 | ino_t d_ino; /* Inode number */ 13 | off_t d_off; /* Not an offset; see below */ 14 | unsigned short d_reclen; /* Length of this record */ 15 | unsigned char d_type; /* Type of file; not supported 16 | by all filesystem types */ 17 | char d_name[MAX_NAME_LEN]; /* Null-terminated filename */ 18 | }; 19 | 20 | typedef struct { 21 | int fd; // open file descriptoy 22 | int next; 23 | } DIR; 24 | 25 | DIR *fdopendir(int fd); 26 | DIR *opendir(const char *fn); 27 | int readdir(int fd, struct dirent *dirent); 28 | int closedir(DIR *dir); 29 | 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /kernel/include/bits/dirent.h: -------------------------------------------------------------------------------- 1 | #ifndef _BITS_DIRENT_H 2 | #define _BITS_DIRENT_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #define MAX_NAME_LEN 256 9 | 10 | 11 | struct dirent 12 | { 13 | ino_t d_ino; /* Inode number */ 14 | off_t d_off; /* Not an offset; see below */ 15 | unsigned short d_reclen; /* Length of this record */ 16 | unsigned char d_type; /* Type of file; not supported 17 | by all filesystem types */ 18 | char d_name[MAX_NAME_LEN]; /* Null-terminated filename */ 19 | }; 20 | 21 | typedef struct 22 | { 23 | int fd; // open file descriptoy 24 | int next; 25 | } DIR; 26 | 27 | DIR *fdopendir(int fd); 28 | DIR *opendir(const char *fn); 29 | int readdir(int fd, struct dirent *dirent); 30 | int closedir(DIR *dir); 31 | 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /kernel/include/mm/page_flags.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | 7 | #define PG_X BS(0) // page is executable. 8 | #define PG_R BS(1) // page is readable. 9 | #define PG_W BS(2) // page is writable. 10 | #define PG_U BS(3) // page is user. 11 | #define PG_VALID BS(4) // page is valid in physical. 12 | #define PG_SHARED BS(5) // shared page. 13 | 14 | #define PG_D BS(6) // page is dirty. 15 | #define PG_WRITEBACK BS(7) // page needs writeback 16 | #define PG_SWAPPABLE BS(8) // page swapping is allowed. 17 | #define PG_SWAPPED BS(9) // page is swapped out. 18 | #define PG_L BS(10) // page is locked in memory. 19 | #define PG_C BS(11) // page is cached. 20 | 21 | #define PG_RX (PG_R | PG_X) 22 | #define PG_RW (PG_R | PG_W) 23 | #define PG_RWX (PG_RW| PG_X) -------------------------------------------------------------------------------- /kernel/dev/chr/console/earlycons.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | int use_cga = 0; 9 | int use_earlycons = 1; 10 | int earlycons_use_gfx = 0; 11 | 12 | int earlycons_init(void) { 13 | int err = 0; 14 | 15 | uart_dev_init(); 16 | err = framebuffer_gfx_init(); 17 | if (err == -ENOENT) { 18 | cga_init(); 19 | use_cga = 1; 20 | } 21 | return 0; 22 | } 23 | 24 | void earlycons_usefb(void) { 25 | if (earlycons_use_gfx) { 26 | if (!limeterm_init()) 27 | use_cga = 0; 28 | } 29 | else use_cga = 1; 30 | } 31 | 32 | int earlycons_putc(int c) { 33 | if (use_limeterm_cons) { 34 | limeterm_putc(c); 35 | return 0; 36 | } else if (earlycons_use_gfx) { 37 | limeterm_sputc(c); 38 | return 0; 39 | } 40 | cga_putc(c); 41 | return 0; 42 | } -------------------------------------------------------------------------------- /kernel/include/mm/vmm.h: -------------------------------------------------------------------------------- 1 | #ifndef VMM_H 2 | #define VMM_H 1 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | // virtual memory manager 9 | struct vmman 10 | { 11 | int (*init)(void); 12 | uintptr_t (*alloc)(size_t); // allocate an 'n'(kib), address is page aligned and size must be a multiple of 4Kib 13 | void (*free)(uintptr_t); // deallocates a region of virtual memory 14 | size_t (*getfreesize)(void); //returns available virtual memory space 15 | size_t (*getinuse)(void); // returns the size of used virtual memory space 16 | }; 17 | 18 | extern struct vmman vmman; 19 | 20 | int vmm_active(void); 21 | uintptr_t mapped_alloc(size_t); 22 | void mapped_free(uintptr_t, size_t); 23 | void memory_usage(void); 24 | 25 | int getpagesize(void); 26 | 27 | void dump_free_node_list(void); 28 | void dump_freevmr_list(void); 29 | void dump_usedvmr_list(void); 30 | void dump_all_lists(void); 31 | 32 | 33 | #endif // VMM_H -------------------------------------------------------------------------------- /kernel/include/font/tinyfont.h: -------------------------------------------------------------------------------- 1 | #ifndef _TINYFONT_H 2 | #define _TINYFONT_H 3 | 4 | struct font { 5 | int rows, cols; /* glyph bitmap rows and columns */ 6 | int n; /* number of font glyphs */ 7 | int *glyphs; /* glyph unicode character codes */ 8 | char *data; /* glyph bitmaps */ 9 | }; 10 | 11 | /* 12 | * This tinyfont header is followed by: 13 | * 14 | * glyphs[n] unicode character codes (int) 15 | * bitmaps[n] character bitmaps (char[rows * cols]) 16 | */ 17 | struct tinyfont { 18 | char sig[8]; /* tinyfont signature; "tinyfont" */ 19 | int ver; /* version; 0 */ 20 | int n; /* number of glyphs */ 21 | int rows, cols; /* glyph dimensions */ 22 | }; 23 | 24 | int fontctx_alloc(struct font **ref); 25 | struct font *font_open(char *path); 26 | int font_bitmap(struct font *font, void *dst, int c); 27 | void font_free(struct font *font); 28 | int font_rows(struct font *font); 29 | int font_cols(struct font *font); 30 | 31 | extern char _binary_font_tf_end[]; 32 | extern char _binary_font_tf_size[]; 33 | extern char _binary_font_tf_start[]; 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /kernel/include/fs/fcntl.h: -------------------------------------------------------------------------------- 1 | #ifndef FCNTL_H 2 | # define FCNTL_H 3 | 4 | #define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR) 5 | 6 | #define O_RDONLY 0x000000 7 | #define O_WRONLY 0x000001 8 | #define O_RDWR 0x000002 9 | #define O_APPEND 0x000008 10 | #define O_CREAT 0x000200 11 | #define O_TRUNC 0x000400 12 | #define O_EXCL 0x000800 13 | #define O_SYNC 0x002000 14 | #define O_DSYNC O_SYNC 15 | #define O_RSYNC O_SYNC 16 | #define O_NONBLOCK 0x004000 17 | #define O_NOCTTY 0x008000 18 | #define O_CLOEXEC 0x040000 19 | #define O_NOFOLLOW 0x100000 20 | #define O_DIRECTORY 0x200000 21 | #define __O_TMPFILE (020000000 | O_DIRECTORY) 22 | #define O_EXEC 0x400000 23 | #define O_SEARCH O_EXEC 24 | 25 | int chown(const char *path, uid_t owner, gid_t group); 26 | 27 | int fchown(int fd, uid_t owner, gid_t group); 28 | 29 | int fchownat(int fd, const char *path, uid_t owner, gid_t group, int flag); 30 | 31 | #endif -------------------------------------------------------------------------------- /kernel/include/ds/stack.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | typedef struct stack { 6 | queue_t s_queue; 7 | spinlock_t s_lock; 8 | } stack_t; 9 | 10 | #define stack_assert(s) ({assert(s, "No stack"); }) 11 | #define stack_lock(s) ({stack_assert(s); spin_lock(&(s)->s_lock); }) 12 | #define stack_unlock(s) ({stack_assert(s); spin_unlock(&(s)->s_lock); }) 13 | #define stack_islocked(s) ({stack_assert(s); spin_islocked(&(s)->s_lock); }) 14 | #define stack_assert_locked(s) ({stack_assert(s); spin_assert_locked(&(s)->s_lock); }) 15 | 16 | #define STACK_INIT() ((stack_t){0}) 17 | #define STACK_NEW() (&(stack_t){0}) 18 | 19 | int stack_init(stack_t *s); 20 | int stack_push(stack_t *s, void *pd); 21 | int stack_pop(stack_t *s, void **pdp); 22 | int stack_remove(stack_t *s, void *data); 23 | int stack_contains(stack_t *s, void *data); 24 | size_t stack_size(stack_t *s); 25 | int stack_flush(stack_t *s); 26 | int stack_alloc(stack_t **psp); 27 | void stack_free(stack_t *s); 28 | int stack_peek(stack_t *s, int top, void **pdp); -------------------------------------------------------------------------------- /kernel/include/fs/ramfs2.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #define RAMFS2_INV 0 7 | #define RAMFS2_REG 1 8 | #define RAMFS2_DIR 2 9 | 10 | #define __magic_len 16 11 | #define __max_fname 64 12 | 13 | typedef struct ramfs2_node { 14 | int mode; 15 | int type; 16 | int uid, gid; 17 | uint32_t size; 18 | uint32_t offset; 19 | char name[__max_fname]; 20 | } ramfs2_node_t; 21 | 22 | typedef struct ramfs2_super_header { 23 | char magic[__magic_len]; 24 | uint32_t nfile; 25 | uint32_t checksum; // checksum of magic, node->size(s), ramfs2_size and super_size. 26 | uint32_t file_size; 27 | uint32_t ramfs2_size; 28 | uint32_t super_size; 29 | uint32_t data_offset; 30 | } ramfs2_super_header_t; 31 | 32 | typedef struct ramfs2_super { 33 | ramfs2_super_header_t header; 34 | ramfs2_node_t nodes[]; 35 | } ramfs2_super_t; 36 | 37 | int ramfs2_init(void); 38 | int ramfs2_validate(ramfs2_super_t *sb); 39 | int ramfs2_find(ramfs2_super_t *super, const char *fn, ramfs2_node_t **pnode); -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Emment Yamikani Banda 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /kernel/include/arch/x86_64/context.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #define x86_64_tf_isuser(tf) ({((tf)->errno & 0x4) ? 1 : 0; }) 7 | 8 | typedef struct __context_t { 9 | context_t *link; 10 | u64 r15; 11 | u64 r14; 12 | u64 r13; 13 | u64 r12; 14 | u64 r11; 15 | u64 rbx; 16 | u64 rbp; 17 | u64 rip; 18 | } context_t; 19 | 20 | // No. of registers in caller-callee context. 21 | #define NREGCTX ((sizeof (context_t)) / sizeof (uintptr_t)) 22 | 23 | enum { 24 | CXT_LINK, 25 | #define CTX_LINK CTX_LINK 26 | CTX_R15, 27 | #define CTX_R15 CTX_R15 28 | CTX_R14, 29 | #define CTX_R14 CTX_R14 30 | CTX_R13, 31 | #define CTX_R13 CTX_R13 32 | CTX_R12, 33 | #define CTX_R12 CTX_R12 34 | CTX_R11, 35 | #define CTX_R11 CTX_R11 36 | CTX_RBX, 37 | #define CTX_RBX CTX_RBX 38 | CTX_RBP, 39 | #define CTX_RBP CTX_RBP 40 | CTX_RIP, 41 | #define CTX_RIP CTX_RIP 42 | }; 43 | 44 | extern void trapret(void); 45 | extern void dump_ctx(context_t *ctx, int halt); 46 | extern void swtch(context_t **old, context_t *new); 47 | extern void context_switch(context_t **pcontext); -------------------------------------------------------------------------------- /usr/lib/liballoc_hooks.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #if !defined(MAP_ANONYMOUS) && defined(MAP_ANON) 4 | # define MAP_ANONYMOUS MAP_ANON 5 | #endif 6 | #if !defined(MAP_FAILED) 7 | # define MAP_FAILED ((char*)-1) 8 | #endif 9 | 10 | #ifndef MAP_NORESERVE 11 | # ifdef MAP_AUTORESRV 12 | # define MAP_NORESERVE MAP_AUTORESRV 13 | # else 14 | # define MAP_NORESERVE 0 15 | # endif 16 | #endif 17 | 18 | static int page_size = -1; 19 | static spinlock_t *liballoc_lk = SPINLOCK_NEW(); 20 | 21 | 22 | int liballoc_lock() { 23 | spin_lock(liballoc_lk); 24 | return 0; 25 | } 26 | 27 | int liballoc_unlock() { 28 | spin_unlock(liballoc_lk); 29 | return 0; 30 | } 31 | 32 | void* liballoc_alloc( int pages ) { 33 | if ( page_size < 0 ) page_size = getpagesize(); 34 | unsigned int size = pages * page_size; 35 | 36 | char *p2 = (char*)mmap(0, size, PROT_NONE, MAP_PRIVATE|/*MAP_NORESERVE|*/MAP_ANONYMOUS, -1, 0); 37 | if ( p2 == MAP_FAILED) return NULL; 38 | 39 | if(mprotect(p2, size, PROT_READ|PROT_WRITE) != 0) { 40 | munmap(p2, size); 41 | return NULL; 42 | } 43 | 44 | return p2; 45 | } 46 | 47 | int liballoc_free( void* ptr, int pages ) { 48 | return munmap( ptr, pages * page_size ); 49 | } -------------------------------------------------------------------------------- /kernel/include/ds/ringbuf.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #define RINGBUF_INDEX(ring, i) ((i) % ((ring)->size)) 6 | 7 | typedef struct ringbuf { 8 | char *buf; 9 | size_t size; 10 | size_t head; 11 | size_t tail; 12 | size_t count; 13 | spinlock_t lock; 14 | }ringbuf_t; 15 | 16 | #define RINGBUF_NEW(nam, sz) (&(ringbuf_t){.buf = (char[sz]){0}, .size = sz, .head = 0, .tail = 0, .lock = SPINLOCK_INIT()}) 17 | 18 | #define ringbuf_assert(r) ({ assert(r, "no ringbuf"); }) 19 | #define ringbuf_lock(r) ({ ringbuf_assert(r); spin_lock(&(r)->lock); }) 20 | #define ringbuf_unlock(r) ({ ringbuf_assert(r); spin_unlock(&(r)->lock); }) 21 | #define ringbuf_assert_locked(r) ({ ringbuf_assert(r); spin_assert_locked(&(r)->lock); }) 22 | 23 | void ringbuf_debug(ringbuf_t *ring); 24 | 25 | int ringbuf_new(size_t size, ringbuf_t **); 26 | int ringbuf_init(isize size, ringbuf_t *ring); 27 | 28 | void ringbuf_free(ringbuf_t *ring); 29 | int ringbuf_isfull(ringbuf_t *ring); 30 | int ringbuf_isempty(ringbuf_t *ring); 31 | size_t ringbuf_available(ringbuf_t *ring); 32 | 33 | size_t ringbuf_read(ringbuf_t *ring, char *buf, size_t n); 34 | size_t ringbuf_write(ringbuf_t *ring, char *buf, size_t n); -------------------------------------------------------------------------------- /kernel/include/modules/module.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | typedef struct { 6 | char *mod_name; 7 | void *mod_arg; 8 | int (*mod_init)(); 9 | int (*mod_fini)(); 10 | } module_sym_t; 11 | 12 | extern module_sym_t __builtin_mods[]; 13 | extern module_sym_t __builtin_mods_end[]; 14 | 15 | #define MODULE_INIT(name, a, i, f) \ 16 | module_sym_t __used_section(.__builtin_mods) \ 17 | __mod_##name = { \ 18 | .mod_name = #name, \ 19 | .mod_arg = a, \ 20 | .mod_init = i, \ 21 | .mod_fini = f, \ 22 | } 23 | 24 | typedef struct { 25 | char *sym_name; 26 | void *sym_addr; 27 | } symbl_t; 28 | 29 | extern symbl_t ksym_table[]; 30 | extern symbl_t ksym_table_end[]; 31 | 32 | #define EXPORT_SYMBOL(name) \ 33 | symbl_t __attribute__((used, section(".ksym_table"))) __exported_##name = { \ 34 | .sym_name = #name, \ 35 | .sym_addr = &name, \ 36 | }; 37 | 38 | int modules_init(); -------------------------------------------------------------------------------- /usr/app/init.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void main(void) { 5 | pid_t sh = 0; 6 | int staloc = 0; 7 | char *const envp[] = { 8 | "SHELL=/test", 9 | "INIT=/ramfs/init", 10 | NULL 11 | }; 12 | char *const argp[] = { 13 | "/ramfs/test", 14 | NULL 15 | }; 16 | 17 | int err = 0; 18 | int fd = 0; 19 | struct stat st; 20 | char *buf = NULL; 21 | 22 | if ((err = stat("/ramfs/dev", &st))) 23 | panic("error: %d.", err); 24 | 25 | if (NULL == (buf = malloc(st.st_size + 1))) 26 | panic("Failed to allocate memory."); 27 | 28 | memset(buf, 0, st.st_size); 29 | 30 | if ((err = fd = open("/ramfs/dev", O_RDONLY, 0))) 31 | panic("Failed to read device lookup list. err: %d", err); 32 | 33 | read(fd, buf, st.st_size); 34 | 35 | loop() { 36 | if ((sh = fork()) < 0) 37 | panic("Failed to fork test\n"); 38 | else if (sh != 0) { 39 | sh = wait(&staloc); 40 | if (staloc) panic("%d: Ended with error: %d\n", sh, staloc); 41 | } else { 42 | if ((execve(*argp, argp, envp))) 43 | panic("Failed to exec test\n"); 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /kernel/dev/chr/timers/timers.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | static atomic_t hpet_avl = {0}; 10 | 11 | int timer_init(void) { 12 | int err = 0; 13 | printk("Initializing timers...\n"); 14 | if ((err = hpet_init())) 15 | pit_init(); // if failed to initalized HPET use PIT. 16 | else 17 | atomic_write(&hpet_avl, 1); 18 | printk("Timers initalized successfully.\n"); 19 | return 0; 20 | } 21 | 22 | void timer_wait(int tmr, double s) { 23 | if (!s) 24 | return; 25 | switch (tmr) { 26 | case CLK_HPET: 27 | hpet_wait(s); 28 | break; 29 | case CLK_PIT: 30 | pit_wait(s); 31 | break; 32 | //case CLK_RTC: 33 | //case CLK_TSC: 34 | case CLK_ANY: 35 | __fallthrough; 36 | default: 37 | if (atomic_read(&hpet_avl)) 38 | hpet_wait(s); 39 | else 40 | pit_wait(s); 41 | } 42 | } 43 | 44 | void timer_intr(void) { 45 | if (atomic_read(&hpet_avl)) 46 | hpet_intr(); 47 | else 48 | pit_intr(); 49 | } 50 | 51 | 52 | MODULE_INIT(timer, NULL, timer_init, NULL); -------------------------------------------------------------------------------- /usr/include/stdnoreturn.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2011-2020 Free Software Foundation, Inc. 2 | 3 | This file is part of GCC. 4 | 5 | GCC is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 3, or (at your option) 8 | any later version. 9 | 10 | GCC is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | Under Section 7 of GPL version 3, you are granted additional 16 | permissions described in the GCC Runtime Library Exception, version 17 | 3.1, as published by the Free Software Foundation. 18 | 19 | You should have received a copy of the GNU General Public License and 20 | a copy of the GCC Runtime Library Exception along with this program; 21 | see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 22 | . */ 23 | 24 | /* ISO C1X: 7.23 _Noreturn . */ 25 | 26 | #ifndef _STDNORETURN_H 27 | #define _STDNORETURN_H 28 | 29 | #ifndef __cplusplus 30 | 31 | #define noreturn _Noreturn 32 | 33 | #endif 34 | 35 | #endif /* stdnoreturn.h */ 36 | -------------------------------------------------------------------------------- /usr/include/sys/time.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | struct timespec { 8 | time_t tv_sec; 9 | long tv_nsec; 10 | }; 11 | 12 | struct tm { 13 | int tm_sec; 14 | int tm_min; 15 | int tm_hour; 16 | int tm_mday; 17 | int tm_mon; 18 | int tm_year; 19 | int tm_wday; 20 | int tm_yday; 21 | int tm_isdst; 22 | }; 23 | 24 | typedef struct timeval { 25 | time_t tv_sec; // Seconds. 26 | susseconds_t tv_usec; // Microseconds. 27 | } timeval_t; 28 | int gettimeofday(struct timeval *restrict tp, void *restrict tzp); 29 | 30 | struct timezone 31 | { 32 | int tz_minuteswest; /* minutes west of Greenwich */ 33 | int tz_dsttime; /* type of DST correction */ 34 | }; 35 | 36 | extern int settimeofday(struct timeval *p, void *z); 37 | 38 | clock_t clock(void); 39 | 40 | 41 | struct tm *localtime(const time_t *timer); 42 | struct tm *localtime_r(const time_t *restrict timer, 43 | struct tm *restrict result); 44 | 45 | time_t mktime(struct tm *timeptr); 46 | 47 | int clock_getres(clockid_t clock_id, struct timespec *res); 48 | int clock_gettime(clockid_t clock_id, struct timespec *tp); 49 | int clock_settime(clockid_t clock_id, const struct timespec *tp); -------------------------------------------------------------------------------- /kernel/include/fs/cred.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | typedef struct cred_t { 7 | uid_t c_uid; 8 | uid_t c_euid; 9 | uid_t c_suid; 10 | gid_t c_gid; 11 | gid_t c_egid; 12 | gid_t c_sgid; 13 | mode_t c_umask; 14 | spinlock_t c_lock; 15 | } cred_t; 16 | 17 | #define CRED_DEFAULT() ((cred_t){\ 18 | .c_uid = 0, \ 19 | .c_euid = 0, \ 20 | .c_egid = 0, \ 21 | .c_gid = 0, \ 22 | .c_suid = 0, \ 23 | .c_sgid = 0, \ 24 | .c_lock = SPINLOCK_INIT() \ 25 | }) 26 | 27 | 28 | #define cred_assert(cr) ({ assert(cr, "No credentials!\n"); }) 29 | #define cred_islocked(cr) ({ cred_assert(cr); spin_islocked(&(cr)->c_lock); }) 30 | #define cred_assert_locked(cr) ({ cred_assert(cr); spin_assert_locked(&(cr)->c_lock); }) 31 | #define cred_lock(cr) ({ cred_assert(cr); spin_lock(&(cr)->c_lock); }) 32 | #define cred_unlock(cr) ({ cred_assert(cr); spin_unlock(&(cr)->c_lock); }) 33 | #define cred_trylock(cr) ({ cred_assert(cr); spin_trylock(&(cr)->c_lock); }) 34 | 35 | int cred_alloc(cred_t **ret); 36 | void cred_free(cred_t *cred); 37 | int cred_copy(cred_t *dst, cred_t *src); -------------------------------------------------------------------------------- /kernel/include/lib/stdnoreturn.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2011-2020 Free Software Foundation, Inc. 2 | 3 | This file is part of GCC. 4 | 5 | GCC is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 3, or (at your option) 8 | any later version. 9 | 10 | GCC is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | Under Section 7 of GPL version 3, you are granted additional 16 | permissions described in the GCC Runtime Library Exception, version 17 | 3.1, as published by the Free Software Foundation. 18 | 19 | You should have received a copy of the GNU General Public License and 20 | a copy of the GCC Runtime Library Exception along with this program; 21 | see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 22 | . */ 23 | 24 | /* ISO C1X: 7.23 _Noreturn . */ 25 | 26 | #ifndef _STDNORETURN_H 27 | #define _STDNORETURN_H 28 | 29 | #ifndef __cplusplus 30 | 31 | #define noreturn _Noreturn 32 | 33 | #endif 34 | 35 | #endif /* stdnoreturn.h */ 36 | -------------------------------------------------------------------------------- /kernel/include/dev/clocks.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #define CLK_PIT (0) 8 | #define CLK_HPET (1) 9 | #define CLK_RTC (2) 10 | #define CLK_TSC (3) 11 | #define CLK_ANY (-1) 12 | 13 | typedef struct __clk_t { 14 | struct timeval clk_tv; 15 | struct timeval clk_default_tv; 16 | int clk_flags; 17 | long clk_id; 18 | void *clk_arg; 19 | spinlock_t clk_spinlock; 20 | void (*clk_entry)(); 21 | } clk_t; 22 | 23 | #define CLK_ARMED BS(0) 24 | #define CLK_RESET BS(1) 25 | 26 | #define NCLK (4096) 27 | 28 | #define clk_assert(clk) ({ assert(clk, "No clock ptr"); }) 29 | #define clk_lock(clk) ({ clk_assert(clk); spin_lock(&(clk)->clk_spinlock); }) 30 | #define clk_unlock(clk) ({ clk_assert(clk); spin_unlock(&(clk)->clk_spinlock); }) 31 | #define clk_islocked(clk) ({ clk_assert(clk); spin_islocked(&(clk)->clk_spinlock); }) 32 | #define clk_assert_locked(clk) ({ clk_assert(clk); spin_assert_locked(&(clk)->clk_spinlock); }) 33 | 34 | int clock_set(timeval_t *ts, void (*entry)(), void *arg, int flags, clockid_t *ref); 35 | 36 | void timer_intr(void); 37 | void timer_wait(int tmr, double s); 38 | void clock_trigger(void); -------------------------------------------------------------------------------- /usr/include/wchar.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include <_cheader.h> 4 | #include 5 | 6 | _Begin_C_Header 7 | extern int wcwidth(wchar_t c); 8 | extern wchar_t * wcsncpy(wchar_t * dest, const wchar_t * src, size_t n); 9 | extern size_t wcslen(const wchar_t * s); 10 | extern int wcscmp(const wchar_t *s1, const wchar_t *s2); 11 | extern wchar_t * wcscat(wchar_t *dest, const wchar_t *src); 12 | extern wchar_t * wcstok(wchar_t * str, const wchar_t * delim, wchar_t ** saveptr); 13 | extern size_t wcsspn(const wchar_t * wcs, const wchar_t * accept); 14 | extern wchar_t *wcspbrk(const wchar_t *wcs, const wchar_t *accept); 15 | extern wchar_t * wcschr(const wchar_t *wcs, wchar_t wc); 16 | extern wchar_t * wcsrchr(const wchar_t *wcs, wchar_t wc); 17 | extern wchar_t * wcsncat(wchar_t *dest, const wchar_t * src, size_t n); 18 | extern int wcsncmp(const wchar_t *s1, const wchar_t *s2, size_t n); 19 | extern wchar_t * wcscpy(wchar_t * dest, const wchar_t * src); 20 | extern unsigned long int wcstoul(const wchar_t *nptr, wchar_t **endptr, int base); 21 | extern unsigned long long int wcstoull(const char *nptr, wchar_t **endptr, int base); 22 | extern long int wcstol(const wchar_t *nptr, wchar_t **endptr, int base); 23 | extern long long int wcstoll(const wchar_t *nptr, wchar_t **endptr, int base); 24 | 25 | typedef unsigned int wint_t; 26 | _End_C_Header 27 | -------------------------------------------------------------------------------- /kernel/include/fs/sysfs.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | int sysfs_init(void); 4 | 5 | int sysfs_iopen(inode_t *idev); 6 | int sysfs_isync(inode_t *ip); 7 | int sysfs_iclose(inode_t *ip); 8 | int sysfs_iunlink(inode_t *ip); 9 | int sysfs_itruncate(inode_t *ip); 10 | int sysfs_igetattr(inode_t *ip, void *attr); 11 | int sysfs_isetattr(inode_t *ip, void *attr); 12 | int sysfs_ifcntl(inode_t *ip, int cmd, void *argp); 13 | int sysfs_iioctl(inode_t *ip, int req, void *argp); 14 | ssize_t sysfs_iread_data(inode_t *ip, off_t off, void *buf, size_t nb); 15 | ssize_t sysfs_iwrite_data(inode_t *ip, off_t off, void *buf, size_t nb); 16 | int sysfs_imkdir(inode_t *dir, const char *fname, mode_t mode); 17 | int sysfs_icreate(inode_t *dir, const char *fname, mode_t mode); 18 | int sysfs_ibind(inode_t *dir, struct dentry *dentry, inode_t *ip); 19 | int sysfs_ilookup(inode_t *dir, const char *fname, inode_t **pipp); 20 | int sysfs_isymlink(inode_t *ip, inode_t *atdir, const char *symname); 21 | int sysfs_imknod(inode_t *dir, const char *name, mode_t mode, int devid); 22 | ssize_t sysfs_ireaddir(inode_t *dir, off_t off, struct dirent *buf, size_t count); 23 | int sysfs_ilink(const char *oldname, inode_t *dir, const char *newname); 24 | int sysfs_irename(inode_t *dir, const char *old, inode_t *newdir, const char *new); -------------------------------------------------------------------------------- /kernel/include/fs/procfs.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | 4 | int procfs_init(void); 5 | 6 | int procfs_iopen(inode_t *idev); 7 | int procfs_isync(inode_t *ip); 8 | int procfs_iclose(inode_t *ip); 9 | int procfs_iunlink(inode_t *ip); 10 | int procfs_itruncate(inode_t *ip); 11 | int procfs_igetattr(inode_t *ip, void *attr); 12 | int procfs_isetattr(inode_t *ip, void *attr); 13 | int procfs_ifcntl(inode_t *ip, int cmd, void *argp); 14 | int procfs_iioctl(inode_t *ip, int req, void *argp); 15 | ssize_t procfs_iread_data(inode_t *ip, off_t off, void *buf, size_t nb); 16 | ssize_t procfs_iwrite_data(inode_t *ip, off_t off, void *buf, size_t nb); 17 | int procfs_imkdir(inode_t *dir, const char *fname, mode_t mode); 18 | int procfs_icreate(inode_t *dir, const char *fname, mode_t mode); 19 | int procfs_ibind(inode_t *dir, struct dentry *dentry, inode_t *ip); 20 | int procfs_ilookup(inode_t *dir, const char *fname, inode_t **pipp); 21 | int procfs_isymlink(inode_t *ip, inode_t *atdir, const char *symname); 22 | int procfs_imknod(inode_t *dir, const char *name, mode_t mode, int devid); 23 | ssize_t procfs_ireaddir(inode_t *dir, off_t off, struct dirent *buf, size_t count); 24 | int procfs_ilink(const char *oldname, inode_t *dir, const char *newname); 25 | int procfs_irename(inode_t *dir, const char *old, inode_t *newdir, const char *new); -------------------------------------------------------------------------------- /usr/include/stdalign.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2011-2020 Free Software Foundation, Inc. 2 | 3 | This file is part of GCC. 4 | 5 | GCC is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 3, or (at your option) 8 | any later version. 9 | 10 | GCC is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | Under Section 7 of GPL version 3, you are granted additional 16 | permissions described in the GCC Runtime Library Exception, version 17 | 3.1, as published by the Free Software Foundation. 18 | 19 | You should have received a copy of the GNU General Public License and 20 | a copy of the GCC Runtime Library Exception along with this program; 21 | see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 22 | . */ 23 | 24 | /* ISO C1X: 7.15 Alignment . */ 25 | 26 | #ifndef _STDALIGN_H 27 | #define _STDALIGN_H 28 | 29 | #ifndef __cplusplus 30 | 31 | #define alignas _Alignas 32 | #define alignof _Alignof 33 | 34 | #define __alignas_is_defined 1 35 | #define __alignof_is_defined 1 36 | 37 | #endif 38 | 39 | #endif /* stdalign.h */ 40 | -------------------------------------------------------------------------------- /kernel/sys/sleep.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | static queue_t *global_sleep_queue = QUEUE_NEW(/*"Global sleep queue"*/); 10 | 11 | long sleep(long s) { 12 | jiffies_t jiffies = s_TO_jiffies(s); 13 | 14 | jiffies = jiffies_sleep(jiffies); 15 | if (jiffies <= 0) 16 | return 0; 17 | s = jiffies_TO_s(jiffies); 18 | return s; 19 | } 20 | 21 | int park(void) { 22 | int err = 0; 23 | 24 | current_lock(); 25 | current_setpark(); 26 | 27 | if (current_issetwake()) { 28 | current_mask_park_wake(); 29 | current_unlock(); 30 | return 0; 31 | } 32 | 33 | err = sched_sleep(global_sleep_queue, T_ISLEEP, NULL); 34 | 35 | current_mask_park_wake(); 36 | current_unlock(); 37 | return err; 38 | } 39 | 40 | int unpark(tid_t tid) { 41 | int err = 0; 42 | thread_t *thread = NULL; 43 | 44 | current_tgroup_lock(); 45 | if ((err = tgroup_get_thread(current_tgroup(), tid, T_ISLEEP, &thread))) { 46 | current_tgroup_lock(); 47 | return err; 48 | } 49 | current_tgroup_unlock(); 50 | 51 | thread_setwake(thread); 52 | err = thread_wake(thread); 53 | thread_unlock(thread); 54 | return err; 55 | } -------------------------------------------------------------------------------- /kernel/include/fs/tmpfs.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | int tmpfs_init(void); 4 | int tmpfs_new_inode(itype_t type, inode_t **pip); 5 | 6 | int tmpfs_iopen(inode_t *idev); 7 | int tmpfs_isync(inode_t *ip); 8 | int tmpfs_iclose(inode_t *ip); 9 | int tmpfs_iunlink(inode_t *ip); 10 | int tmpfs_itruncate(inode_t *ip); 11 | int tmpfs_igetattr(inode_t *ip, void *attr); 12 | int tmpfs_isetattr(inode_t *ip, void *attr); 13 | int tmpfs_ifcntl(inode_t *ip, int cmd, void *argp); 14 | int tmpfs_iioctl(inode_t *ip, int req, void *argp); 15 | ssize_t tmpfs_iread(inode_t *ip, off_t off, void *buf, size_t nb); 16 | ssize_t tmpfs_iwrite(inode_t *ip, off_t off, void *buf, size_t nb); 17 | int tmpfs_imkdir(inode_t *dir, const char *fname, mode_t mode); 18 | int tmpfs_icreate(inode_t *dir, const char *fname, mode_t mode); 19 | int tmpfs_ibind(inode_t *dir, struct dentry *dentry, inode_t *ip); 20 | int tmpfs_ilookup(inode_t *dir, const char *fname, inode_t **pipp); 21 | int tmpfs_isymlink(inode_t *ip, inode_t *atdir, const char *symname); 22 | int tmpfs_imknod(inode_t *dir, const char *name, mode_t mode, int devid); 23 | ssize_t tmpfs_ireaddir(inode_t *dir, off_t off, struct dirent *buf, size_t count); 24 | int tmpfs_ilink(const char *oldname, inode_t *dir, const char *newname); 25 | int tmpfs_irename(inode_t *dir, const char *old, inode_t *newdir, const char *new); -------------------------------------------------------------------------------- /kernel/include/lib/stdalign.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2011-2020 Free Software Foundation, Inc. 2 | 3 | This file is part of GCC. 4 | 5 | GCC is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 3, or (at your option) 8 | any later version. 9 | 10 | GCC is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | Under Section 7 of GPL version 3, you are granted additional 16 | permissions described in the GCC Runtime Library Exception, version 17 | 3.1, as published by the Free Software Foundation. 18 | 19 | You should have received a copy of the GNU General Public License and 20 | a copy of the GCC Runtime Library Exception along with this program; 21 | see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 22 | . */ 23 | 24 | /* ISO C1X: 7.15 Alignment . */ 25 | 26 | #ifndef _STDALIGN_H 27 | #define _STDALIGN_H 28 | 29 | #ifndef __cplusplus 30 | 31 | #define alignas _Alignas 32 | #define alignof _Alignof 33 | 34 | #define __alignas_is_defined 1 35 | #define __alignof_is_defined 1 36 | 37 | #endif 38 | 39 | #endif /* stdalign.h */ 40 | -------------------------------------------------------------------------------- /usr/include/sys/mman.h: -------------------------------------------------------------------------------- 1 | #ifndef MMAN_H 2 | #define MMAN_H 1 3 | 4 | #include 5 | 6 | #define PROT_NONE 0x0 // Deny any access, do not ack accesses to this region. 7 | #define PROT_READ 0x1 // The region is mapped for reading, must always be provided in "prot" argument. 8 | #define PROT_WRITE 0x2 // The region is mapped for writing. 9 | #define PROT_EXEC 0x4 // The paged in this region can be executed. 10 | 11 | #define MAP_PRIVATE 0x0001 12 | #define MAP_SHARED 0x0002 13 | #define MAP_DONTEXPAND 0x0004 14 | #define MAP_ANON 0x0008 15 | #define MAP_ZERO 0x0010 16 | #define MAP_MAPIN 0x0020 17 | #define MAP_GROWSDOWN 0x0100 18 | /*region is a stack*/ 19 | #define MAP_STACK (MAP_GROWSDOWN) 20 | 21 | /** 22 | * Map address range as given, 23 | * and unmap any overlaping regions previously mapped. 24 | */ 25 | #define MAP_FIXED 0x1000 26 | #define MAP_NORESERVE 27 | 28 | #ifdef __cplusplus 29 | extern "C" { 30 | #endif 31 | 32 | extern int getpagesize(void); 33 | extern void *mmap(void *__addr, size_t __len, int __prot, 34 | int __flags, int __fd, long __offset); 35 | 36 | extern int munmap(void *addr, size_t length); 37 | extern int mprotect(void *addr, size_t len, int prot); 38 | #ifdef __cplusplus 39 | } 40 | #endif 41 | 42 | #endif // MMAN_H -------------------------------------------------------------------------------- /roadmap.md: -------------------------------------------------------------------------------- 1 | # Features 2 | 3 | ## Firmware 4 | 5 | - [x] BIOS 6 | - [ ] UEFI 7 | - [x] ACPI 8 | 9 | ## Device Drivers 10 | 11 | ### Buses 12 | 13 | - [ ] IDE 14 | - [ ] Serial ATA 15 | - [ ] USB 16 | 17 | ### Physical Devices 18 | 19 | - [x] CGA 20 | - [x] Real Time Clock 21 | - [x] High Precision Event Timer 22 | - [ ] Console 23 | - [ ] PS2 Mouse 24 | - [ ] PS2 Keyboard 25 | - [ ] CD ROM 26 | - [ ] Central Processing unit 27 | 28 | ### Virtual Devices 29 | 30 | - [x] RamDisk 31 | - [x] Full 32 | - [x] Null 33 | - [x] Zero 34 | - [x] Random 35 | - [ ] Mem 36 | - [ ] Pseudo Teminals 37 | 38 | ## Memory Management 39 | 40 | - [x] Physical Memery Management 41 | - [x] Virtual Memory Management 42 | - [x] Page cache 43 | 44 | ### Memory allocator(s) 45 | 46 | - [x] Zones for physical memory (Similar, but not same, as in Linux). 47 | - [x] Liballoc (Credit to whom it is due) 48 | 49 | ## Multitasking 50 | 51 | - [x] Symmetric Multiprocessing up to 16 Cores 52 | - [x] Multi-Threading 53 | - [x] Thread groups 54 | - [x] User processes 55 | 56 | - [x] POSIX Signals 57 | 58 | ## Virtual Filesystem 59 | 60 | - [x] Generic inode operations. 61 | - [x] File address space to allow file sharing. 62 | - [ ] File locks 63 | - [ ] File times 64 | - [ ] Generic file operations. 65 | 66 | ## File System 67 | 68 | - [x] ginger ramfs 69 | - [x] tmpfs 70 | - [x] devfs 71 | - [x] pipefs 72 | - [ ] sysfs 73 | - [ ] ext2fs 74 | - [ ] FAT32 75 | -------------------------------------------------------------------------------- /kernel/include/dev/pty.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define NPTMX 256 // total number of allowed pseudoterminal masters. 9 | 10 | #define PTY_BUFFER_SIZE 4096 // buffer size for now. 11 | 12 | // pseudoterminal 13 | typedef struct pty_t { 14 | int pt_id; // psuedoterminal ID. 15 | inode_t *pt_imaster; // master inode. 16 | inode_t *pt_islave; // slave inode. 17 | 18 | ringbuf_t *master; 19 | ringbuf_t *slave; 20 | 21 | #define PTY_USED 0x01 // is pseudoterminal struct used? 22 | #define PTY_LOCKED 0x02 // is pseudoterminal locked? 23 | u32 pt_flags; // pseudoterminal flags. 24 | 25 | /** @brief TODO: define a struct termio 26 | * and define an instance here.*/ 27 | spinlock_t pt_lock; // lock 28 | } pty_t, *PTY; 29 | 30 | #define pty_assert(pt) ({ assert(pt, "No PTY."); }) 31 | 32 | #define pty_lock(pt) ({ pty_assert(pt); spin_lock(&(pt)->pt_lock); }) 33 | #define pty_unlock(pt) ({ pty_assert(pt); spin_unlock(&(pt)->pt_lock); }) 34 | #define pty_islocked(pt) ({ pty_assert(pt); spin_islocked(&(pt)->pt_lock); }) 35 | #define pty_assert_locked(pt) ({ pty_assert(pt); spin_assert_locked(&(pt)->pt_lock); }) 36 | 37 | 38 | extern int pseudo_init(void); 39 | extern int ptmx_alloc(PTY *ref); -------------------------------------------------------------------------------- /kernel/mm/liballoc/liballoc_hooks.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | 8 | #if !defined(MAP_ANONYMOUS) && defined(MAP_ANON) 9 | # define MAP_ANONYMOUS MAP_ANON 10 | #endif 11 | #if !defined(MAP_FAILED) 12 | # define MAP_FAILED ((char*)-1) 13 | #endif 14 | 15 | #ifndef MAP_NORESERVE 16 | # ifdef MAP_AUTORESRV 17 | # define MAP_NORESERVE MAP_AUTORESRV 18 | # else 19 | # define MAP_NORESERVE 0 20 | # endif 21 | #endif 22 | 23 | static int page_size = -1; 24 | static SPINLOCK(liballoc_lk); 25 | 26 | 27 | int liballoc_lock() { 28 | spin_lock(liballoc_lk); 29 | return 0; 30 | } 31 | 32 | int liballoc_unlock() { 33 | spin_unlock(liballoc_lk); 34 | return 0; 35 | } 36 | 37 | void* liballoc_alloc( int pages ) { 38 | void *p2 = NULL; 39 | 40 | if ( page_size < 0 ) 41 | page_size = getpagesize(); 42 | 43 | size_t size = pages * page_size; 44 | 45 | // printk("\nliballoc_alloc(): pointer: request pages: %d\n", pages); 46 | if (arch_pagealloc(size, (uintptr_t *)&p2)) 47 | return NULL; 48 | // printk("liballoc_alloc(): pointer: %p request pages: %d\n", p2, pages); 49 | 50 | assert((u64)p2 >= V2HI(0), "p2 below kernel virtual address space"); 51 | return p2; 52 | } 53 | 54 | int liballoc_free( void* ptr, int pages ) { 55 | // printk("liballoc_free(): release pointer: %p, pages: %d\n", ptr, pages); 56 | arch_pagefree((uintptr_t)ptr, pages * page_size); 57 | return 0; 58 | } -------------------------------------------------------------------------------- /kernel/dev/chr/ps2/kbd.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | DEV_DECL_OPS(static, ps2kbd); 5 | 6 | static DEV_INIT(ps2kbd, FS_CHR, DEV_KBD0, 0); 7 | 8 | static int ps2kbd_init(void) { 9 | printk("Initializing \e[025453;011m%s\e[0m chardev...\n", ps2kbddev.devname); 10 | return kdev_register(&ps2kbddev, DEV_KBD0, FS_CHR); 11 | } 12 | 13 | static int ps2kbd_probe(void) { 14 | return 0; 15 | } 16 | 17 | static int ps2kbd_close(struct devid *dd __unused) { 18 | return 0; 19 | } 20 | 21 | static int ps2kbd_getinfo(struct devid *dd __unused, void *info __unused) { 22 | return -ENOTSUP; 23 | } 24 | 25 | static int ps2kbd_open(struct devid *dd __unused) { 26 | return 0; 27 | } 28 | 29 | static int ps2kbd_ioctl(struct devid *dd __unused, int req __unused, void *argp __unused) { 30 | return -ENOTSUP; 31 | } 32 | 33 | static off_t ps2kbd_lseek(struct devid *dd __unused, off_t off __unused, int whence __unused) { 34 | return -ENOTSUP; 35 | } 36 | 37 | static ssize_t ps2kbd_read(struct devid *dd __unused, off_t off __unused, void *buf __unused, size_t sz __unused) { 38 | return 0; 39 | } 40 | 41 | static ssize_t ps2kbd_write(struct devid *dd __unused, off_t off __unused, void *buf __unused, size_t sz) { 42 | return sz; 43 | } 44 | 45 | static int ps2kbd_mmap(struct devid *dd, vmr_t *region) { 46 | if (dd == NULL || region == NULL) 47 | return -EINVAL; 48 | return -ENOSYS; 49 | } 50 | 51 | MODULE_INIT(ps2kbd, NULL, ps2kbd_init, 0ULL); -------------------------------------------------------------------------------- /kernel/test/test_threads.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | cond_t *condvar = COND_NEW(); 7 | 8 | void sa_sigaction(int signo, siginfo_t *info, void *ctx) { 9 | printk("thread[%d:%d]: signo: %d, info: %p, context: %p\n", getpid(), thread_self(), signo, info, ctx); 10 | thread_exit(0); 11 | } 12 | 13 | void test_signal(void) { 14 | int err = 0; 15 | sigaction_t act = {0}; 16 | 17 | act.sa_handler = NULL; 18 | act.sa_flags = SA_SIGINFO; 19 | act.sa_sigaction= sa_sigaction; 20 | 21 | err = sigaction(SIGINT, &act, NULL); 22 | assert(err == 0, "Failed to set signal action!!!"); 23 | 24 | cond_signal(condvar); 25 | loop() thread_yield(); 26 | } 27 | 28 | void test_main(void) { 29 | tid_t tid = 0; 30 | int err = 0; 31 | thread_t *thread = NULL; 32 | 33 | err = kthread_create( 34 | NULL, 35 | (void *)test_signal, 36 | condvar, 37 | THREAD_CREATE_GROUP | 38 | THREAD_CREATE_SCHED, 39 | &thread 40 | ); 41 | 42 | assert(err == 0, "Failed to create new thread!"); 43 | 44 | tid = thread_gettid(thread); 45 | thread_unlock(thread); 46 | 47 | cond_wait(condvar); 48 | err = pthread_kill(tid, SIGINT); 49 | 50 | assert_msg(err == 0, 51 | "Failed to send signal to thread[%d], errno: %d\n", tid, err); 52 | } // BUILTIN_THREAD(test_main, test_main, NULL); -------------------------------------------------------------------------------- /kernel/include/fs/devtmpfs.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | int devtmpfs_init(void); 11 | 12 | int dev_iopen(inode_t *idev); 13 | int dev_isync(inode_t *ip); 14 | int dev_iclose(inode_t *ip); 15 | int dev_iunlink(inode_t *ip); 16 | int dev_itruncate(inode_t *ip); 17 | int dev_igetattr(inode_t *ip, void *attr); 18 | int dev_isetattr(inode_t *ip, void *attr); 19 | int dev_ifcntl(inode_t *ip, int cmd, void *argp); 20 | int dev_iioctl(inode_t *ip, int req, void *argp); 21 | ssize_t dev_iread(inode_t *ip, off_t off, void *buf, size_t nb); 22 | ssize_t dev_iwrite(inode_t *ip, off_t off, void *buf, size_t nb); 23 | int dev_imkdir(inode_t *dir, const char *fname, mode_t mode); 24 | int dev_icreate(inode_t *dir, const char *fname, mode_t mode); 25 | int dev_ibind(inode_t *dir, struct dentry *dentry, inode_t *ip); 26 | int dev_ilookup(inode_t *dir, const char *fname, inode_t **pipp); 27 | int dev_isymlink(inode_t *ip, inode_t *atdir, const char *symname); 28 | int dev_imknod(inode_t *dir, const char *name, mode_t mode, int devid); 29 | ssize_t dev_ireaddir(inode_t *dir, off_t off, struct dirent *buf, size_t count); 30 | int dev_ilink(const char *oldname, inode_t *dir, const char *newname); 31 | int dev_irename(inode_t *dir, const char *old, inode_t *newdir, const char *new); 32 | 33 | extern iops_t dev_iops; -------------------------------------------------------------------------------- /ramfs/kernel.ld: -------------------------------------------------------------------------------- 1 | ENTRY(start32) 2 | OUTPUT_FORMAT(elf64-x86-64) 3 | OUTPUT_ARCH(i386:x86-64) 4 | 5 | TRAMPOLINE = 0x8000; 6 | KERNEL_LMA = 0x1000000; 7 | KERNEL_VMA = 0xFFFF800000000000; 8 | 9 | 10 | SECTIONS { 11 | . = TRAMPOLINE; 12 | .trampoline ALIGN (4K) : AT (ADDR (.trampoline)) { 13 | *(.trampoline) 14 | *(.multiboot) 15 | } 16 | 17 | . = KERNEL_LMA + KERNEL_VMA; 18 | _kernel_start = .; 19 | .text ALIGN (4K) : AT (ADDR (.text) - KERNEL_VMA) { 20 | *(.text) 21 | *(.rodata) 22 | } 23 | 24 | .ksym_table ALIGN (4K) : AT(ADDR(.ksym_table) - KERNEL_VMA) { 25 | ksym_table = .; 26 | *(.ksym_table*) 27 | ksym_table_end = .; 28 | } 29 | 30 | .__builtin_mods ALIGN (4K) : AT(ADDR(.__builtin_mods) - KERNEL_VMA) { 31 | __builtin_mods = .; 32 | *(.__builtin_mods*) 33 | __builtin_mods_end = .; 34 | } 35 | 36 | .__builtin_threads ALIGN (4K) : AT(ADDR(.__builtin_threads) - KERNEL_VMA) { 37 | __builtin_threads = .; 38 | *(.__builtin_threads*) 39 | __builtin_threads_end = .; 40 | } 41 | 42 | .data ALIGN (4K) : AT (ADDR (.data) - KERNEL_VMA) { 43 | *(.data) 44 | } 45 | 46 | .bss ALIGN (4K) : AT (ADDR (.bss) - KERNEL_VMA) { 47 | *(.bss) 48 | *(COMMON) 49 | } 50 | 51 | /DISCARD/ : 52 | { 53 | *(.comment) 54 | /* Exception handling section - we do not need it*/ 55 | *(.eh_frame) 56 | } 57 | 58 | _kernel_end = .; 59 | } -------------------------------------------------------------------------------- /usr/include/sys/types.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | typedef int pid_t; 4 | typedef int tid_t; 5 | 6 | typedef long ssize_t; 7 | typedef unsigned long off_t; 8 | typedef unsigned short devid_t; 9 | typedef unsigned short dev_t; 10 | 11 | typedef int uid_t; 12 | typedef int gid_t; 13 | typedef int ino_t; 14 | typedef int mode_t; 15 | typedef long time_t; 16 | typedef int susseconds_t; 17 | typedef long timer_t; 18 | typedef long clock_t; 19 | typedef long clockid_t; 20 | 21 | typedef unsigned long useconds_t; 22 | typedef long suseconds_t; 23 | typedef int pid_t; 24 | 25 | #define FD_SETSIZE 64 /* compatibility with newlib */ 26 | typedef unsigned int fd_mask; 27 | typedef struct _fd_set 28 | { 29 | fd_mask fds_bits[1]; /* should be 64 bits */ 30 | } fd_set; 31 | 32 | typedef void *(*thread_entry_t)(void *); 33 | 34 | typedef char i8; 35 | typedef short i16; 36 | typedef int i32; 37 | typedef long i64; 38 | typedef long isize; 39 | 40 | typedef unsigned char u8; 41 | typedef unsigned short u16; 42 | typedef unsigned int u32; 43 | typedef unsigned long u64; 44 | typedef unsigned long usize; 45 | typedef unsigned long off_t; -------------------------------------------------------------------------------- /kernel/arch/x86_64/swtch.asm: -------------------------------------------------------------------------------- 1 | global swtch 2 | swtch: 3 | push rbp 4 | push rbx 5 | push r11 6 | push r12 7 | push r13 8 | push r14 9 | push r15 10 | 11 | sub rsp, 8 ; For link. 12 | mov qword[rdi], rsp ; 13 | mov rsp, rsi ; 14 | add rsp, 8 ; For link. 15 | 16 | pop r15 17 | pop r14 18 | pop r13 19 | pop r12 20 | pop r11 21 | pop rbx 22 | pop rbp 23 | retq 24 | 25 | global context_switch 26 | ;context_switch(&arch.t_context); 27 | context_switch: 28 | push rbp 29 | push rbx 30 | push r11 31 | push r12 32 | push r13 33 | push r14 34 | push r15 35 | 36 | ; rdi = &arch->t_ctx 37 | mov rax, qword[rdi] ; rax = arch->t_ctx (i.e context we're swtching to) 38 | push qword[rax] ; push arch->t_ctx->link 39 | mov qword[rdi], rsp ; &arch->t_ctx = saved ctx 40 | mov rdi, rsp ; pass rsp as an argument 41 | ; to function pointed to 42 | ; by rip of new context. 43 | mov rsp, rax ; rsp = arch->t_ctx (i.e context we're swtching to) 44 | add rsp, 8 ; skip arch->t_ctx->link. 45 | 46 | pop r15 47 | pop r14 48 | pop r13 49 | pop r12 50 | pop r11 51 | pop rbx 52 | pop rbp 53 | 54 | mov rsi, rsp 55 | add rsi, 16 56 | retq -------------------------------------------------------------------------------- /kernel/arch/chipset/pit.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | volatile int intsrc_overide = 0; 12 | 13 | #define DATAPORT 0x40 14 | 15 | #define CMDPORT 0x43 16 | #define COUNTER(i) (DATAPORT + i) 17 | 18 | #define CH(i) SHL(i, 6) 19 | 20 | #define LOB 1 21 | #define HIB 2 22 | #define LOHI 3 23 | #define HZ SYS_HZ 24 | 25 | #define MODE(x) SHL(x, 1) 26 | #define RATEGEN MODE(2) 27 | #define ONESHOT MODE(1) 28 | 29 | void pit_init(void) { 30 | outb(CMDPORT, LOHI | RATEGEN); 31 | uint16_t counter = 1193182 / HZ; 32 | outb(COUNTER(0), (uint8_t)counter); 33 | inb(0x60); 34 | outb(COUNTER(0), (uint8_t)(counter >> 8)); 35 | ioapic_enable(LEG_PIT, lapic_id()); 36 | } 37 | 38 | void pit_intr(void) { 39 | jiffies_update(); 40 | } 41 | 42 | void pit_wait(double s) { 43 | uint8_t data = 0; 44 | uint16_t freq = (uint16_t) ((double) (1 / s)); 45 | uint16_t counter = 1193182 / freq; 46 | 47 | data = (inb(0x61) & 0xfd) | 1; 48 | outb(0x61, data); 49 | 50 | outb(CMDPORT, CH(2) | LOHI | ONESHOT); 51 | outb(COUNTER(2), (uint8_t)counter); 52 | inb(0x60); 53 | outb(COUNTER(2), (uint8_t)(counter >> 8)); 54 | 55 | data = inb(0x61) & 0xfe; 56 | outb(0x61, data); 57 | outb(0x61, data | 1); 58 | while (!(inb(0x61) & 0x20)); 59 | } -------------------------------------------------------------------------------- /usr/lib/stdlib/qsort.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | extern char * _argv_0; 9 | extern int __libc_debug; 10 | 11 | struct SortableArray { 12 | void * data; 13 | size_t size; 14 | int (*func)(const void *, const void *); 15 | }; 16 | 17 | static ssize_t partition(struct SortableArray * array, ssize_t lo, ssize_t hi) { 18 | char pivot[array->size]; 19 | memcpy(pivot, (char *)array->data + array->size * hi, array->size); 20 | ssize_t i = lo - 1; 21 | for (ssize_t j = lo; j <= hi; ++j) { 22 | uint8_t * obj_j = (uint8_t *)array->data + array->size * j; 23 | if (array->func(obj_j, pivot) <= 0) { 24 | i++; 25 | if (j != i) { 26 | uint8_t * obj_i = (uint8_t *)array->data + array->size * i; 27 | for (size_t x = 0; x < array->size; ++x) { 28 | uint8_t tmp = obj_i[x]; 29 | obj_i[x] = obj_j[x]; 30 | obj_j[x] = tmp; 31 | } 32 | } 33 | } 34 | } 35 | return i; 36 | } 37 | 38 | static void quicksort(struct SortableArray * array, ssize_t lo, ssize_t hi) { 39 | if (lo >= 0 && hi >= 0) { 40 | if (lo < hi) { 41 | ssize_t pivot = partition(array, lo, hi); 42 | quicksort(array, lo, pivot - 1); 43 | quicksort(array, pivot + 1, hi); 44 | } 45 | } 46 | } 47 | 48 | void qsort(void * base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)) { 49 | if (nmemb < 2) return; 50 | if (!size) return; 51 | struct SortableArray array = {base,size,compar}; 52 | quicksort(&array, 0, nmemb - 1); 53 | } 54 | -------------------------------------------------------------------------------- /usr/lib/wchar/wcstok.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | size_t wcsspn(const wchar_t * wcs, const wchar_t * accept) { 4 | size_t out = 0; 5 | 6 | while (*wcs) { 7 | int good = 0; 8 | for (const wchar_t * a = accept; *a; ++a) { 9 | if (*wcs == *a) { 10 | good = 1; 11 | break; 12 | } 13 | } 14 | if (!good) break; 15 | out++; 16 | wcs++; 17 | } 18 | 19 | return out; 20 | } 21 | 22 | wchar_t *wcspbrk(const wchar_t *wcs, const wchar_t *accept) { 23 | while (*wcs) { 24 | for (const wchar_t * a = accept; *a; ++a) { 25 | if (*wcs == *a) { 26 | return (wchar_t *)wcs; 27 | } 28 | } 29 | wcs++; 30 | } 31 | return NULL; 32 | } 33 | 34 | wchar_t * wcschr(const wchar_t *wcs, wchar_t wc) { 35 | while (*wcs != wc && *wcs != 0) { 36 | wcs++; 37 | } 38 | if (!*wcs) return NULL; 39 | return (wchar_t *)wcs; 40 | } 41 | 42 | wchar_t * wcsrchr(const wchar_t *wcs, wchar_t wc) { 43 | wchar_t * last = NULL; 44 | while (*wcs != 0) { 45 | if (*wcs == wc) { 46 | last = (wchar_t *)wcs; 47 | } 48 | wcs++; 49 | } 50 | return last; 51 | } 52 | 53 | wchar_t * wcstok(wchar_t * str, const wchar_t * delim, wchar_t ** saveptr) { 54 | wchar_t * token; 55 | if (str == NULL) { 56 | str = *saveptr; 57 | } 58 | str += wcsspn(str, delim); 59 | if (*str == '\0') { 60 | *saveptr = str; 61 | return NULL; 62 | } 63 | token = str; 64 | str = wcspbrk(token, delim); 65 | if (str == NULL) { 66 | *saveptr = (wchar_t *)wcschr(token, '\0'); 67 | } else { 68 | *str = '\0'; 69 | *saveptr = str + 1; 70 | } 71 | return token; 72 | } 73 | 74 | 75 | -------------------------------------------------------------------------------- /kernel/include/arch/ucontext.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | /*machine context*/ 10 | typedef struct __mcontext_t { 11 | // general purpose registers. 12 | #if defined (__x86_64__) 13 | u64 fs; 14 | u64 ds; 15 | 16 | u64 r15; 17 | u64 r14; 18 | u64 r13; 19 | u64 r12; 20 | u64 r11; 21 | u64 r10; 22 | u64 r9; 23 | u64 r8; 24 | 25 | u64 rbp; 26 | u64 rsi; 27 | u64 rdi; 28 | u64 rdx; 29 | u64 rcx; 30 | u64 rbx; 31 | u64 rax; 32 | 33 | // TODO: include cr2 and other necessary registers. 34 | 35 | u64 trapno; 36 | u64 errno; 37 | 38 | u64 rip; 39 | u64 cs; 40 | u64 rflags; 41 | u64 rsp; 42 | u64 ss; 43 | #endif // #if defined (__x86_64__) 44 | } mcontext_t/*Machine context*/; 45 | 46 | 47 | typedef struct __ucontext_t { 48 | ucontext_t *uc_link; /* pointer to context resumed when */ 49 | /* this context returns */ 50 | sigset_t uc_sigmask; /* signals blocked when this context */ 51 | /* is active */ 52 | uc_stack_t uc_stack; /* stack used by this context */ 53 | i32 uc_resvd; 54 | i64 uc_flags; /* flags*/ 55 | mcontext_t uc_mcontext;/* machine-specific representation of */ 56 | /* saved context */ 57 | } ucontext_t; 58 | 59 | #define uctx_isuser(ctx) ({ ((ctx)->uc_mcontext.cs == (((SEG_UCODE64 << 3) | DPL_USR))) ? 1 : 0; }) -------------------------------------------------------------------------------- /kernel/kernel.ld: -------------------------------------------------------------------------------- 1 | ENTRY(start32) 2 | OUTPUT_FORMAT(elf64-x86-64) 3 | OUTPUT_ARCH(i386:x86-64) 4 | 5 | TRAMPOLINE = 0x8000; 6 | KERNEL_LMA = 0x1000000; 7 | KERNEL_VMA = 0xFFFF800000000000; 8 | 9 | 10 | SECTIONS { 11 | . = TRAMPOLINE; 12 | .trampoline ALIGN (4K) : AT (ADDR (.trampoline)) { 13 | *(.trampoline) 14 | *(.multiboot) 15 | *(.init32) 16 | } 17 | 18 | . = KERNEL_LMA + KERNEL_VMA; 19 | kstart = .; 20 | .text ALIGN (4K) : AT (ADDR (.text) - KERNEL_VMA) { 21 | *(.text) 22 | } 23 | 24 | .ksym_table ALIGN (4K) : AT(ADDR(.ksym_table) - KERNEL_VMA) { 25 | ksym_table = .; 26 | *(.ksym_table*) 27 | ksym_table_end = .; 28 | } 29 | 30 | .__builtin_mods ALIGN (4K) : AT(ADDR(.__builtin_mods) - KERNEL_VMA) { 31 | __builtin_mods = .; 32 | *(.__builtin_mods*) 33 | __builtin_mods_end = .; 34 | } 35 | 36 | .__builtin_thrds ALIGN (4K) : AT(ADDR(.__builtin_thrds) - KERNEL_VMA) { 37 | __builtin_thrds = .; 38 | *(.__builtin_thrds*) 39 | __builtin_thrds_end = .; 40 | } 41 | 42 | .rodata ALIGN (4K) : AT (ADDR (.rodata) - KERNEL_VMA) { 43 | *(.rodata) 44 | } 45 | 46 | .data ALIGN (4K) : AT (ADDR (.data) - KERNEL_VMA) { 47 | *(.data) 48 | } 49 | 50 | .bss ALIGN (4K) : AT (ADDR (.bss) - KERNEL_VMA) { 51 | *(.bss) 52 | *(COMMON) 53 | } 54 | 55 | /DISCARD/ : 56 | { 57 | *(.comment) 58 | /* Exception handling section - we do not need it*/ 59 | *(.eh_frame) 60 | } 61 | 62 | kend = .; 63 | } -------------------------------------------------------------------------------- /kernel/include/bits/waitflags.h: -------------------------------------------------------------------------------- 1 | /* Definitions of flag bits for `waitpid' et al. 2 | Copyright (C) 1992-2022 Free Software Foundation, Inc. 3 | This file is part of the GNU C Library. 4 | 5 | The GNU C Library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | The GNU C Library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with the GNU C Library; if not, see 17 | . */ 18 | 19 | 20 | /* Bits in the third argument to `waitpid'. */ 21 | #define WNOHANG 1 /* Don't block waiting. */ 22 | #define WUNTRACED 2 /* Report status of stopped children. */ 23 | 24 | /* Bits in the fourth argument to `waitid'. */ 25 | #define WSTOPPED 2 /* Report stopped child (same as WUNTRACED). */ 26 | #define WEXITED 4 /* Report dead child. */ 27 | #define WCONTINUED 8 /* Report continued child. */ 28 | #define WNOWAIT 0x01000000 /* Don't reap, just poll status. */ 29 | 30 | 31 | #define __WNOTHREAD 0x20000000 /* Don't wait on children of other threads 32 | in this group */ 33 | #define __WALL 0x40000000 /* Wait for any child. */ 34 | #define __WCLONE 0x80000000 /* Wait for cloned process. */ 35 | -------------------------------------------------------------------------------- /usr/include/time.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include <_cheader.h> 4 | #include 5 | #include 6 | 7 | _Begin_C_Header 8 | 9 | struct tm { 10 | int tm_sec; /* Seconds (0-60) */ 11 | int tm_min; /* Minutes (0-59) */ 12 | int tm_hour; /* Hours (0-23) */ 13 | int tm_mday; /* Day of the month (1-31) */ 14 | int tm_mon; /* Month (0-11) */ 15 | int tm_year; /* Year - 1900 */ 16 | int tm_wday; /* Day of the week (0-6, Sunday = 0) */ 17 | int tm_yday; /* Day in the year (0-365, 1 Jan = 0) */ 18 | int tm_isdst; /* Daylight saving time */ 19 | 20 | const char * _tm_zone_name; 21 | int _tm_zone_offset; 22 | }; 23 | 24 | extern struct tm *localtime(const time_t *timep); 25 | extern struct tm *gmtime(const time_t *timep); 26 | 27 | extern struct tm *localtime_r(const time_t *timep, struct tm * buf); 28 | extern struct tm *gmtime_r(const time_t *timep, struct tm * buf); 29 | 30 | extern size_t strftime(char *s, size_t max, const char *format, const struct tm *tm); 31 | extern time_t time(time_t * out); 32 | extern double difftime(time_t a, time_t b); 33 | extern time_t mktime(struct tm *tm); 34 | 35 | extern char * asctime(const struct tm *tm); 36 | extern char * ctime(const time_t * timep); 37 | 38 | extern clock_t clock(void); 39 | #define CLOCKS_PER_SEC 1000000 40 | 41 | struct timespec { 42 | time_t tv_sec; 43 | long tv_nsec; 44 | }; 45 | 46 | typedef int clockid_t; 47 | 48 | #define CLOCK_REALTIME 0 49 | #define CLOCK_MONOTONIC 1 50 | 51 | extern int clock_gettime(clockid_t clk_id, struct timespec *tp); 52 | extern int clock_getres(clockid_t clk_id, struct timespec *res); 53 | 54 | _End_C_Header 55 | -------------------------------------------------------------------------------- /kernel/sys/signals/alarm.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | int raise(int signo) { 14 | return pthread_kill(thread_gettid(current), signo); 15 | } 16 | 17 | int pause(void) { 18 | static queue_t pause_queue = QUEUE_INIT(); 19 | 20 | queue_lock(current->t_tgroup); 21 | current_lock(); 22 | sched_sleep_r(&pause_queue, T_ISLEEP, NULL); 23 | current_unlock(); 24 | queue_unlock(current->t_tgroup); 25 | 26 | return -EINTR; 27 | } 28 | 29 | void trigger_alarm(pid_t pid) { 30 | kill(pid, SIGALRM); 31 | } 32 | 33 | unsigned long alarm(unsigned sec) { 34 | timeval_t tv = {0}; 35 | clockid_t clkid = 0; 36 | static btree_t alarms = {0}; 37 | 38 | tv.tv_sec = sec; 39 | tv.tv_usec = 0; 40 | 41 | proc_lock(curproc); 42 | if (sec == 0) { // disarm previous alarm. 43 | btree_lock(&alarms); 44 | btree_search(&alarms, curproc->pid, (void **)&clkid); 45 | btree_unlock(&alarms); 46 | proc_unlock(curproc); 47 | return 0; 48 | } 49 | 50 | assert( 51 | clock_set(&tv, 52 | (void *)trigger_alarm, 53 | (void *)(long)curproc->pid, 54 | CLK_ARMED, &clkid 55 | ) == 0, "Failed to set alarm\n"); 56 | 57 | btree_lock(&alarms); 58 | btree_insert(&alarms, curproc->pid, (void *)clkid); 59 | btree_unlock(&alarms); 60 | 61 | proc_unlock(curproc); 62 | 63 | return 0; 64 | } -------------------------------------------------------------------------------- /kernel/core/jiffies.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | static SPINLOCK(res_lock); 14 | static jiffies_t jiffies = 0; 15 | static struct timespec jiffies_res = {0}; 16 | static queue_t *sleep_queue= QUEUE_NEW(); 17 | 18 | void jiffies_update(void) { 19 | atomic_inc(&jiffies); 20 | clock_trigger(); 21 | sched_wakeall(sleep_queue); 22 | } 23 | 24 | jiffies_t jiffies_get(void) { 25 | return (jiffies_t)atomic_read(&jiffies); 26 | } 27 | 28 | void jiffies_timed_wait(double s) { 29 | jiffies_t jiffy = jiffies_get() + s_TO_jiffies(s); 30 | while (time_before(jiffies_get(), jiffy)); 31 | } 32 | 33 | jiffies_t jiffies_sleep(jiffies_t jiffy) { 34 | jiffies_t now = 0; 35 | jiffy += jiffies_get(); 36 | while (time_before((now = jiffies_get()), jiffy)) { 37 | current_lock(); 38 | if ((sched_sleep(sleep_queue, T_ISLEEP, NULL))) { 39 | current_unlock(); 40 | break; 41 | } 42 | current_unlock(); 43 | } 44 | return jiffy - now; 45 | } 46 | 47 | int jiffies_getres(struct timespec *res) { 48 | if (!res) 49 | return -EINVAL; 50 | spin_lock(res_lock); 51 | *res = jiffies_res; 52 | spin_unlock(res_lock); 53 | return 0; 54 | } 55 | 56 | int jiffies_gettime(struct timespec *tp __unused) { 57 | return -ENOSYS; 58 | } 59 | 60 | int jiffies_settime(const struct timespec *tp __unused) { 61 | return -ENOSYS; 62 | } -------------------------------------------------------------------------------- /usr/include/bits/waitflags.h: -------------------------------------------------------------------------------- 1 | /* Definitions of flag bits for `waitpid' et al. 2 | Copyright (C) 1992-2022 Free Software Foundation, Inc. 3 | This file is part of the GNU C Library. 4 | 5 | The GNU C Library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | The GNU C Library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with the GNU C Library; if not, see 17 | . */ 18 | 19 | 20 | /* Bits in the third argument to `waitpid'. */ 21 | #define WNOHANG 1 /* Don't block waiting. */ 22 | #define WUNTRACED 2 /* Report status of stopped children. */ 23 | 24 | /* Bits in the fourth argument to `waitid'. */ 25 | // #if defined __USE_XOPEN_EXTENDED || defined __USE_XOPEN2K8 26 | # define WSTOPPED 2 /* Report stopped child (same as WUNTRACED). */ 27 | # define WEXITED 4 /* Report dead child. */ 28 | # define WCONTINUED 8 /* Report continued child. */ 29 | # define WNOWAIT 0x01000000 /* Don't reap, just poll status. */ 30 | // #endif 31 | 32 | #define __WNOTHREAD 0x20000000 /* Don't wait on children of other threads 33 | in this group */ 34 | #define __WALL 0x40000000 /* Wait for any child. */ 35 | #define __WCLONE 0x80000000 /* Wait for cloned process. */ 36 | -------------------------------------------------------------------------------- /usr/include/stdbool.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 1998-2020 Free Software Foundation, Inc. 2 | 3 | This file is part of GCC. 4 | 5 | GCC is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 3, or (at your option) 8 | any later version. 9 | 10 | GCC is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | Under Section 7 of GPL version 3, you are granted additional 16 | permissions described in the GCC Runtime Library Exception, version 17 | 3.1, as published by the Free Software Foundation. 18 | 19 | You should have received a copy of the GNU General Public License and 20 | a copy of the GCC Runtime Library Exception along with this program; 21 | see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 22 | . */ 23 | 24 | /* 25 | * ISO C Standard: 7.16 Boolean type and values 26 | */ 27 | 28 | #ifndef _STDBOOL_H 29 | #define _STDBOOL_H 30 | 31 | #ifndef __cplusplus 32 | 33 | #define bool _Bool 34 | #define true 1 35 | #define false 0 36 | 37 | #else /* __cplusplus */ 38 | 39 | /* Supporting _Bool in C++ is a GCC extension. */ 40 | #define _Bool bool 41 | 42 | #if __cplusplus < 201103L 43 | /* Defining these macros in C++98 is a GCC extension. */ 44 | #define bool bool 45 | #define false false 46 | #define true true 47 | #endif 48 | 49 | #endif /* __cplusplus */ 50 | 51 | /* Signal that all the definitions are present. */ 52 | #define __bool_true_false_are_defined 1 53 | 54 | #endif /* stdbool.h */ 55 | -------------------------------------------------------------------------------- /kernel/include/lib/stdbool.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 1998-2020 Free Software Foundation, Inc. 2 | 3 | This file is part of GCC. 4 | 5 | GCC is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 3, or (at your option) 8 | any later version. 9 | 10 | GCC is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | Under Section 7 of GPL version 3, you are granted additional 16 | permissions described in the GCC Runtime Library Exception, version 17 | 3.1, as published by the Free Software Foundation. 18 | 19 | You should have received a copy of the GNU General Public License and 20 | a copy of the GCC Runtime Library Exception along with this program; 21 | see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 22 | . */ 23 | 24 | /* 25 | * ISO C Standard: 7.16 Boolean type and values 26 | */ 27 | 28 | #ifndef _STDBOOL_H 29 | #define _STDBOOL_H 30 | 31 | #ifndef __cplusplus 32 | 33 | #define bool _Bool 34 | #define true 1 35 | #define false 0 36 | 37 | #else /* __cplusplus */ 38 | 39 | /* Supporting _Bool in C++ is a GCC extension. */ 40 | #define _Bool bool 41 | 42 | #if __cplusplus < 201103L 43 | /* Defining these macros in C++98 is a GCC extension. */ 44 | #define bool bool 45 | #define false false 46 | #define true true 47 | #endif 48 | 49 | #endif /* __cplusplus */ 50 | 51 | /* Signal that all the definitions are present. */ 52 | #define __bool_true_false_are_defined 1 53 | 54 | #endif /* stdbool.h */ 55 | -------------------------------------------------------------------------------- /kernel/boot/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 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | extern __noreturn void kthread_main(void); 24 | 25 | #include 26 | 27 | int early_init(void) { 28 | int err = 0; 29 | 30 | if ((err = bsp_init())) 31 | panic("BSP initialization failed, error: %d\n", err); 32 | 33 | if ((err = vmman.init())) 34 | panic("Virtual memory initialization failed, error: %d\n", err); 35 | 36 | if ((err = pmman.init())) 37 | panic("Physical memory initialization failed, error: %d\n", err); 38 | 39 | earlycons_usefb(); 40 | 41 | if ((err = acpi_init())) 42 | panic("Failed to initialize ACPI, error: %d\n", err); 43 | 44 | bootothers(); 45 | 46 | pic_init(); 47 | ioapic_init(); 48 | 49 | if ((err = dev_init())) 50 | panic("Failed to start devices, error: %d\n", err); 51 | 52 | if ((err = vfs_init())) 53 | panic("Failed to initialize VFS!, error: %d\n", err); 54 | 55 | kthread_create( 56 | NULL, (thread_entry_t)kthread_main, 57 | NULL, THREAD_CREATE_GROUP | 58 | THREAD_CREATE_SCHED, NULL 59 | ); 60 | 61 | schedule(); 62 | assert(0, "scheduler returned :("); 63 | loop(); 64 | return 0; 65 | } -------------------------------------------------------------------------------- /kernel/include/fs/mount.h: -------------------------------------------------------------------------------- 1 | #ifndef FS_MOUNT_H 2 | #define FS_MOUNT_H 1 3 | 4 | #include 5 | 6 | #define MS_REMOUNT 0x00000001 7 | #define MS_BIND 0x00000002 8 | #define MS_MOVE 0x00000004 9 | #define MS_SHARED 0x00000008 10 | #define MS_PRIVATE 0x00000010 11 | #define MS_SLAVE 0x00000020 12 | #define MS_UNBINDABLE 0x00000040 13 | #define MS_CREAT 0x00000080 14 | #define MS_NONE(m_flags) (!(m_flags & (MS_REMOUNT | MS_BIND | MS_MOVE | MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE))) 15 | 16 | 17 | /*Additional flags*/ 18 | 19 | #define MS_DIRSYNC 0x00000080 20 | #define MS_NOEXEC 0x00000100 21 | #define MS_RDONLY 0x00000200 22 | #define MS_NODEV 0x00000400 23 | #define MS_NOSUID 0x00000800 24 | #define MS_RELATIME 0x00001000 25 | #define MS_NOATIME 0x00002000 26 | #define MS_SILENT 0x00004000 27 | 28 | typedef struct fs_mount 29 | { 30 | struct superblock *mnt_sb; 31 | int mnt_flags; 32 | char *mnt_path; 33 | void *mnt_priv; 34 | dentry_t *mnt_root; 35 | struct fs_mount *mnt_parent; 36 | spinlock_t mnt_lock; 37 | } fs_mount_t; 38 | 39 | #define mnt_assert(mnt) ({assert(mnt, "No mnt ptr"); }) 40 | #define mnt_lock(mnt) ({mnt_assert(mnt); spin_lock(&(mnt)->mnt_lock);}) 41 | #define mnt_unlock(mnt) ({mnt_assert(mnt); spin_unlock(&(mnt)->mnt_lock);}) 42 | #define mnt_islocked(mnt) ({mnt_assert(mnt); spin_islocked(&(mnt)->mnt_lock); }) 43 | #define mnt_assert_locked(mnt) ({mnt_assert(mnt); spin_assert_locked(&(mnt)->mnt_lock); }) 44 | 45 | 46 | int vfs_mount(const char *src, const char *dest, const char *type, unsigned long flags, const void *data); 47 | 48 | #endif // FS_MOUNT_H -------------------------------------------------------------------------------- /kernel/sys/syscall/fork.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | pid_t fork(void) { 12 | int err = 0; 13 | pid_t pid = 0; 14 | proc_t *child = NULL; 15 | thread_t *thread = NULL; 16 | 17 | if (curproc == NULL) 18 | return -EINVAL; 19 | 20 | proc_lock(curproc); 21 | 22 | if ((err = proc_alloc(curproc->name, &child))) 23 | return err; 24 | 25 | mmap_lock(proc_mmap(curproc)); 26 | mmap_lock(proc_mmap(child)); 27 | 28 | if ((err = proc_copy(child, curproc))) { 29 | mmap_unlock(proc_mmap(child)); 30 | mmap_unlock(proc_mmap(curproc)); 31 | goto error; 32 | } 33 | 34 | mmap_unlock(proc_mmap(curproc)); 35 | 36 | pid = child->pid; 37 | thread_lock(child->main_thread); 38 | thread = thread_getref(child->main_thread); 39 | 40 | current_lock(); 41 | if ((err = thread_fork(thread, current, child->mmap))) { 42 | current_unlock(); 43 | thread_release(thread); 44 | goto error; 45 | } 46 | current_unlock(); 47 | 48 | mmap_unlock(proc_mmap(child)); 49 | 50 | if ((err = proc_add_child(curproc, child))) { 51 | thread_unlock(thread); 52 | proc_unlock(child); 53 | proc_unlock(curproc); 54 | goto error; 55 | } 56 | 57 | proc_unlock(child); 58 | proc_unlock(curproc); 59 | 60 | if ((err = thread_schedule(thread))) { 61 | thread_unlock(thread); 62 | goto error; 63 | } 64 | 65 | thread_unlock(thread); 66 | return pid; 67 | error: 68 | if (child) 69 | proc_free(child); 70 | return err; 71 | } -------------------------------------------------------------------------------- /kernel/dev/chr/pty/ptmx.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | // pseudoterminal devices. 9 | static pty_t pseudo_terms[NPTMX] = {0}; 10 | static SPINLOCK(pseudo_termslk); 11 | 12 | #define pseudo_lock() spin_lock(pseudo_termslk) 13 | #define pseudo_unlock() spin_unlock(pseudo_termslk) 14 | #define pseudo_islocked() spin_islocked(pseudo_termslk) 15 | #define pseudo_assert_locked() spin_assert_locked(pseudo_termslk) 16 | 17 | 18 | int pseudo_init(void) { 19 | memset(pseudo_terms, 0, sizeof pseudo_terms); 20 | *pseudo_termslk = SPINLOCK_INIT(); 21 | return 0; 22 | } 23 | 24 | int ptmx_alloc(PTY *ref) { 25 | int err = 0; 26 | PTY pty = NULL; 27 | ringbuf_t *slave = NULL; 28 | ringbuf_t *master = NULL; 29 | 30 | if (ref == NULL) 31 | return -EINVAL; 32 | 33 | pseudo_lock(); 34 | 35 | for (pty = pseudo_terms; pty < &pseudo_terms[NPTMX]; ++pty) { 36 | if ((pty->pt_flags & PTY_USED) == 0) { 37 | if ((err = ringbuf_new(PTY_BUFFER_SIZE, &master))) 38 | return err; 39 | 40 | if ((err = ringbuf_new(PTY_BUFFER_SIZE, &slave))) { 41 | ringbuf_free(master); 42 | return err; 43 | } 44 | 45 | pty->slave = slave; 46 | pty->master = master; 47 | pty->pt_id = pty - pseudo_terms; 48 | pty->pt_flags |= PTY_USED | PTY_LOCKED; 49 | pty->pt_lock = SPINLOCK_INIT(); 50 | 51 | pty_lock(pty); 52 | 53 | *ref = pty; 54 | pseudo_unlock(); 55 | return 0; 56 | } 57 | } 58 | 59 | pseudo_unlock(); 60 | 61 | return -ENOMEM; 62 | } -------------------------------------------------------------------------------- /usr/lib/ctype.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int isalpha(int c) { 4 | return (islower(c) || isupper(c)); 5 | } 6 | 7 | int isdigit(int c) { 8 | return (c >= '0' && c <= '9'); 9 | } 10 | 11 | int isupper(int c) { 12 | return (c >= 'A' && c <= 'Z'); 13 | } 14 | 15 | int islower(int c) { 16 | return (c >= 'a' && c <= 'z'); 17 | } 18 | 19 | int tolower(int c) { 20 | if (!isalpha(c)) 21 | return c; 22 | return OR(c, BS(5)); 23 | } 24 | 25 | int toupper(int c) { 26 | if (!isalpha(c)) 27 | return c; 28 | return NAND(BS(5), c); 29 | } 30 | 31 | int isspace(int c) { 32 | return (c == ' ' || c == '\v' || c == '\b' || c == '\f' 33 | || c == '\t' || c == '\r' || c == '\n'); 34 | } 35 | 36 | int isxdigit(int c) { 37 | return (isdigit(c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')); 38 | } 39 | 40 | int isalphanum(int c) { 41 | return isalpha(c) || isdigit(c); 42 | } 43 | 44 | long atol(const char * s) { 45 | int n = 0; 46 | int neg = 0; 47 | while (isspace(*s)) { 48 | s++; 49 | } 50 | switch (*s) { 51 | case '-': 52 | neg = 1; /* fallthrough */ 53 | case '+': 54 | s++; 55 | } 56 | while (isdigit(*s)) { 57 | n = 10*n - (*s++ - '0'); 58 | } 59 | /* The sign order may look incorrect here but this is correct as n is calculated 60 | * as a negative number to avoid overflow on INT_MAX. 61 | */ 62 | return neg ? n : -n; 63 | } 64 | 65 | int atoi(const char * s) { 66 | int n = 0; 67 | int neg = 0; 68 | while (isspace(*s)) { 69 | s++; 70 | } 71 | switch (*s) { 72 | case '-': 73 | neg = 1; /* fallthrough */ 74 | case '+': 75 | s++; 76 | } 77 | while (isdigit(*s)) { 78 | n = 10*n - (*s++ - '0'); 79 | } 80 | /* The sign order may look incorrect here but this is correct as n is calculated 81 | * as a negative number to avoid overflow on INT_MAX. 82 | */ 83 | return neg ? n : -n; 84 | } -------------------------------------------------------------------------------- /kernel/fs/mkdir.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | int vfs_mkdirat(const char *pathname, dentry_t *dir, cred_t *cred, mode_t mode) { 10 | int err = 0; 11 | vfspath_t *path = NULL; 12 | 13 | if (!S_ISDIR(mode)) { 14 | if (S_IFMT & mode) 15 | return -EINVAL; 16 | } 17 | 18 | if ((err = vfs_resolve_path(pathname, dir, cred, O_EXCL, &path))) { 19 | if (err == -ENOENT) { 20 | // only goto create dir if the traversal reached the last token of the path. 21 | if (vfspath_islasttoken(path)) 22 | goto creat; 23 | printk("%s(%s)\n", __func__, path->lasttoken); 24 | debugloc(); 25 | } 26 | 27 | if (path) { 28 | assert(path->directory, "On error, path has no directory\n"); 29 | dclose(path->directory); 30 | } 31 | goto error; 32 | } 33 | 34 | assert(path->directory == NULL, "On success, path has directory\n"); 35 | assert(path->dentry, "On success, path has no dentry\n"); 36 | err = -EEXIST; 37 | dclose(path->directory); 38 | goto error; 39 | creat: 40 | ilock(path->directory->d_inode); 41 | if ((err = imkdir(path->directory->d_inode, path->token, mode & ~S_IFMT))) { 42 | iunlock(path->directory->d_inode); 43 | dclose(path->directory); 44 | goto error; 45 | } 46 | iunlock(path->directory->d_inode); 47 | 48 | dclose(path->directory); 49 | path_free(path); 50 | return 0; 51 | error: 52 | if (path) 53 | path_free(path); 54 | return err; 55 | } 56 | 57 | int vfs_mkdir(const char *path, cred_t *cred, mode_t mode) { 58 | return vfs_mkdirat(path, NULL, cred, mode); 59 | } -------------------------------------------------------------------------------- /kernel/dev/chr/pty/ptmxdev.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | DEV_DECL_OPS(static, ptmx); 8 | 9 | static DEV_INIT(ptmx, FS_CHR, DEV_PTMX, 2); 10 | 11 | static int ptmx_init(void) { 12 | int err = 0; 13 | 14 | printk("Initializing \e[025453;011m%s\e[0m chardev...\n", ptmxdev.devname); 15 | if ((err = pseudo_init())) 16 | return err; 17 | return kdev_register(&ptmxdev, DEV_PTMX, FS_CHR); 18 | } 19 | 20 | static int ptmx_probe(void) { 21 | return 0; 22 | } 23 | 24 | static int ptmx_close(struct devid *dd __unused) { 25 | return 0; 26 | } 27 | 28 | static int ptmx_getinfo(struct devid *dd __unused, void *info __unused) { 29 | return -ENOTSUP; 30 | } 31 | 32 | static int ptmx_open(struct devid *dd __unused) { 33 | int err = 0; 34 | PTY pty = NULL; 35 | char ptyname[64]; 36 | 37 | if ((err = pty_alloc(&pty))) 38 | return err; 39 | 40 | memset(ptyname, 0, sizeof ptyname); 41 | snprintf(ptyname, sizeof ptyname, "/dev/pts/%d", pty->pt_id); 42 | 43 | return 0; 44 | } 45 | 46 | static int ptmx_ioctl(struct devid *dd __unused, int req __unused, void *argp __unused) { 47 | return -ENOTSUP; 48 | } 49 | 50 | static off_t ptmx_lseek(struct devid *dd __unused, off_t off __unused, int whence __unused) { 51 | return -ENOTSUP; 52 | } 53 | 54 | static ssize_t ptmx_read(struct devid *dd __unused, off_t off __unused, void *buf __unused, size_t sz __unused) { 55 | return 0; 56 | } 57 | 58 | static ssize_t ptmx_write(struct devid *dd __unused, off_t off __unused, void *buf __unused, size_t sz) { 59 | return sz; 60 | } 61 | 62 | static int ptmx_mmap(struct devid *dd, vmr_t *region) { 63 | if (dd == NULL || region == NULL) 64 | return -EINVAL; 65 | return -ENOSYS; 66 | } 67 | 68 | MODULE_INIT(ptmx, NULL, ptmx_init, NULL); -------------------------------------------------------------------------------- /kernel/lib/ctype.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int isalpha(int c) { 5 | return (islower(c) || isupper(c)); 6 | } 7 | 8 | int isdigit(int c) { 9 | return (c >= '0' && c <= '9'); 10 | } 11 | 12 | int isupper(int c) { 13 | return (c >= 'A' && c <= 'Z'); 14 | } 15 | 16 | int islower(int c) { 17 | return (c >= 'a' && c <= 'z'); 18 | } 19 | 20 | int tolower(int c) { 21 | if (!isalpha(c)) 22 | return c; 23 | return OR(c, BS(5)); 24 | } 25 | 26 | int toupper(int c) { 27 | if (!isalpha(c)) 28 | return c; 29 | return NAND(BS(5), c); 30 | } 31 | 32 | int isspace(int c) { 33 | return (c == ' ' || c == '\v' || c == '\b' || c == '\f' 34 | || c == '\t' || c == '\r' || c == '\n'); 35 | } 36 | 37 | int isxdigit(int c) { 38 | return (isdigit(c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')); 39 | } 40 | 41 | int isalphanum(int c) { 42 | return isalpha(c) || isdigit(c); 43 | } 44 | 45 | long atol(const char * s) { 46 | int n = 0; 47 | int neg = 0; 48 | while (isspace(*s)) { 49 | s++; 50 | } 51 | switch (*s) { 52 | case '-': 53 | neg = 1; /* fallthrough */ 54 | case '+': 55 | s++; 56 | } 57 | while (isdigit(*s)) { 58 | n = 10*n - (*s++ - '0'); 59 | } 60 | /* The sign order may look incorrect here but this is correct as n is calculated 61 | * as a negative number to avoid overflow on INT_MAX. 62 | */ 63 | return neg ? n : -n; 64 | } 65 | 66 | int atoi(const char * s) { 67 | int n = 0; 68 | int neg = 0; 69 | while (isspace(*s)) { 70 | s++; 71 | } 72 | switch (*s) { 73 | case '-': 74 | neg = 1; /* fallthrough */ 75 | case '+': 76 | s++; 77 | } 78 | while (isdigit(*s)) { 79 | n = 10*n - (*s++ - '0'); 80 | } 81 | /* The sign order may look incorrect here but this is correct as n is calculated 82 | * as a negative number to avoid overflow on INT_MAX. 83 | */ 84 | return neg ? n : -n; 85 | } -------------------------------------------------------------------------------- /kernel/include/arch/x86_64/isr.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | extern void isr0(void); 4 | extern void isr1(void); 5 | extern void isr2(void); 6 | extern void isr3(void); 7 | extern void isr4(void); 8 | extern void isr5(void); 9 | extern void isr6(void); 10 | extern void isr7(void); 11 | extern void isr8(void); 12 | extern void isr9(void); 13 | extern void isr10(void); 14 | extern void isr11(void); 15 | extern void isr12(void); 16 | extern void isr13(void); 17 | extern void isr14(void); 18 | extern void isr15(void); 19 | extern void isr16(void); 20 | extern void isr17(void); 21 | extern void isr18(void); 22 | extern void isr19(void); 23 | extern void isr20(void); 24 | extern void isr21(void); 25 | extern void isr22(void); 26 | extern void isr23(void); 27 | extern void isr24(void); 28 | extern void isr25(void); 29 | extern void isr26(void); 30 | extern void isr27(void); 31 | extern void isr28(void); 32 | extern void isr29(void); 33 | extern void isr30(void); 34 | extern void isr31(void); 35 | extern void isr128(void); 36 | 37 | extern void irq0(void); 38 | extern void irq1(void); 39 | extern void irq2(void); 40 | extern void irq3(void); 41 | extern void irq4(void); 42 | extern void irq5(void); 43 | extern void irq6(void); 44 | extern void irq7(void); 45 | extern void irq8(void); 46 | extern void irq9(void); 47 | extern void irq10(void); 48 | extern void irq11(void); 49 | extern void irq12(void); 50 | extern void irq13(void); 51 | extern void irq14(void); 52 | extern void irq15(void); 53 | extern void irq16(void); 54 | extern void irq17(void); 55 | extern void irq18(void); 56 | extern void irq19(void); 57 | extern void irq20(void); 58 | extern void irq21(void); 59 | extern void irq22(void); 60 | extern void irq23(void); 61 | extern void irq24(void); 62 | extern void irq25(void); 63 | extern void irq26(void); 64 | extern void irq27(void); 65 | extern void irq28(void); 66 | extern void irq29(void); 67 | extern void irq30(void); 68 | extern void irq31(void); -------------------------------------------------------------------------------- /kernel/include/boot/boot.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #define NMODS 32 9 | #define NMMAP 32 10 | 11 | typedef struct { 12 | uintptr_t addr; // address at which module is loaded. 13 | usize size; // size of the module. 14 | char *cmd; // command line passed with the module 15 | } mod_t; 16 | 17 | typedef struct { 18 | uintptr_t addr; // address at which the memory map starts. 19 | usize size; // size of the memory map. 20 | int type; // type of memory this mmap describes. 21 | } boot_mmap_t; 22 | 23 | typedef struct { 24 | usize total; // total available memory. 25 | usize usable; // Size of usable physical memory. 26 | usize memlo; // Size of lower memory. 27 | usize memhi; // Size of Higher memory. 28 | 29 | struct { 30 | u8 type; 31 | uintptr_t addr; 32 | u32 pitch; 33 | u32 width; 34 | u32 height; 35 | usize size; 36 | u32 bpp; 37 | 38 | struct fb_bitfield red; 39 | struct fb_bitfield blue; 40 | struct fb_bitfield green; 41 | struct fb_bitfield resv; 42 | } fb /* framebuffer data returned by bootloader*/; 43 | 44 | uintptr_t phyaddr; // first free physical address. 45 | boot_mmap_t mmap[NMMAP];// array of memory maps. 46 | u32 mmapcnt; // # of memory maps 47 | 48 | mod_t mods[NMODS];// array of available modules. 49 | u32 modcnt; // # of modules 50 | 51 | uintptr_t kern_base; 52 | usize kern_size; 53 | } bootinfo_t; 54 | 55 | typedef multiboot_module_t mod_entry_t; 56 | typedef multiboot_memory_map_t mmap_entry_t; 57 | 58 | extern bootinfo_t bootinfo; 59 | 60 | extern void boot_mmap_dump(void); -------------------------------------------------------------------------------- /kernel/sys/syscall/exit.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | void exit(int exit_code) { 8 | int err = 0; 9 | proc_t *parent = NULL; 10 | 11 | if (curproc == initproc) 12 | panic("initproc not allowed to exit?!\n"); 13 | 14 | if ((err = thread_kill_all())) { 15 | panic( 16 | "%s:%d: proc(%d): Failed to kill all" 17 | " threads, error: %d", 18 | __FILE__, __LINE__, curproc->pid, 19 | thread_self(), err 20 | ); 21 | } 22 | 23 | // cancel all pending signals. 24 | 25 | // close all open file descriptors. 26 | file_close_all(); 27 | 28 | proc_lock(curproc); 29 | 30 | // abandon children to 'init'. 31 | proc_lock(initproc); 32 | if ((err = proc_abandon_children(initproc, curproc))) { 33 | panic( 34 | "%s:%d: [%d:%d]: " 35 | "Error abandoning children, error: %d", 36 | __FILE__, __LINE__, curproc->pid, 37 | thread_self(), err 38 | ); 39 | } 40 | proc_unlock(initproc); 41 | 42 | // clean mmap. 43 | mmap_lock(curproc->mmap); 44 | if ((err = mmap_clean(curproc->mmap))) { 45 | panic( 46 | "%s:%d: [%d:%d]: " 47 | "Error cleaning mmap, error: %d", 48 | __FILE__, __LINE__, curproc->pid, 49 | thread_self(), err 50 | ); 51 | } 52 | mmap_unlock(curproc->mmap); 53 | 54 | curproc->state = P_ZOMBIE; 55 | curproc->exit_code = exit_code; 56 | 57 | parent = curproc->parent; 58 | // broadcast event to parent process. 59 | proc_lock(parent); 60 | cond_broadcast(&parent->child_event); 61 | proc_unlock(parent); 62 | proc_unlock(curproc); 63 | 64 | printk("%s:%ld: %s(%d);\n", __FILE__, __LINE__, __func__, exit_code); 65 | thread_exit(exit_code); 66 | } -------------------------------------------------------------------------------- /kernel/include/dev/fb.h: -------------------------------------------------------------------------------- 1 | #ifndef _DEV_FB_H 2 | #define _DEV_FB_H 1 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #define NFBDEV 8 10 | 11 | #define FBIOGET_FIX_INFO 0x0000 12 | #define FBIOGET_VAR_INFO 0x0001 13 | 14 | struct fb_bitfield { 15 | uint8_t offset; // position in pixel 16 | uint8_t length; // length of bitfield 17 | uint8_t msb_right; // true if most significant byte is right 18 | }; 19 | 20 | typedef struct fb_fixinfo { 21 | char id[64]; // indentification 22 | int accel; // type of acceleration card in use 23 | uint32_t type; // type of framebuffer 24 | uint32_t caps; // capabilities 25 | size_t memsz; // total memory size of framebuffer 26 | uintptr_t addr; // physical address of framebuffer 27 | size_t line_length;// bytes per line 28 | } fb_fixinfo_t; 29 | 30 | typedef struct fb_varinfo { 31 | int bpp; // bits per pixel 32 | int width; // pixels per row 33 | int height; // pixels per column 34 | uint32_t vmode; // video mode 35 | uint32_t pitch; // pitch 36 | uint32_t grayscale; // greyscaling 37 | uint32_t colorspace; // colorspace (e.g, RBGA, e.t.c) 38 | 39 | /* bitfield if true color */ 40 | 41 | struct fb_bitfield red; 42 | struct fb_bitfield blue; 43 | struct fb_bitfield green; 44 | struct fb_bitfield transp; 45 | } fb_varinfo_t; 46 | 47 | typedef struct framebuffer { 48 | uint32_t id; 49 | void *priv; 50 | struct dev * dev; 51 | fb_fixinfo_t *fixinfo; 52 | fb_varinfo_t *varinfo; 53 | spinlock_t lock; 54 | void *module; 55 | } framebuffer_t; 56 | 57 | extern fb_fixinfo_t fix_info; 58 | extern fb_varinfo_t var_info; 59 | extern int earlycons_use_gfx; 60 | 61 | int framebuffer_process_info(); 62 | int framebuffer_gfx_init(void); 63 | 64 | #endif //_DEV_FB_H -------------------------------------------------------------------------------- /kernel/fs/mknod.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | int vfs_mknodat(const char *pathname, dentry_t *dir, cred_t *cred, mode_t mode, devid_t dev) { 10 | int err = 0; 11 | vfspath_t *path = NULL; 12 | 13 | // Validate the mode 14 | if ((mode & S_IFMT) == 0) { 15 | mode |= S_IFREG; // Default to regular file 16 | } 17 | 18 | if (!S_ISCHR(mode) && !S_ISBLK(mode) && !S_ISFIFO(mode) && !S_ISSOCK(mode) && !S_ISREG(mode)) { 19 | return -EINVAL; // Invalid argument 20 | } 21 | 22 | if ((err = vfs_resolve_path(pathname, dir, cred, O_EXCL, &path))) { 23 | if (err == -ENOENT) { 24 | // only goto create dir if the traversal reached the last token of the path. 25 | if (vfspath_islasttoken(path)) 26 | goto creat; 27 | } 28 | 29 | if (path) { 30 | assert(path->directory, "On error, path has no directory\n"); 31 | dclose(path->directory); 32 | } 33 | goto error; 34 | } 35 | 36 | assert(path->directory == NULL, "On success, path has directory\n"); 37 | assert(path->dentry, "On success, path has no dentry\n"); 38 | err = -EEXIST; 39 | dclose(path->directory); 40 | goto error; 41 | creat: 42 | ilock(path->directory->d_inode); 43 | if ((err = imknod(path->directory->d_inode, path->token, mode, dev))) { 44 | iunlock(path->directory->d_inode); 45 | dclose(path->directory); 46 | goto error; 47 | } 48 | iunlock(path->directory->d_inode); 49 | 50 | dclose(path->directory); 51 | path_free(path); 52 | return 0; 53 | error: 54 | if (path) 55 | path_free(path); 56 | return err; 57 | } 58 | 59 | int vfs_mknod(const char *pathname, cred_t *cred, mode_t mode, devid_t dev) { 60 | return vfs_mknodat(pathname, NULL, cred, mode, dev); 61 | } -------------------------------------------------------------------------------- /kernel/arch/x86_64/trampoline.asm: -------------------------------------------------------------------------------- 1 | [bits 16] 2 | 3 | section .trampoline 4 | 5 | SEG_ACC EQU (1 << 0) 6 | SEG_RW EQU (1 << 1) 7 | SEG_DC EQU (1 << 2) 8 | SEG_CODE EQU (1 << 3) 9 | 10 | SEG_TYPE EQU (1 << 4) 11 | SEG_DPL0 EQU (0 << 5) 12 | SEG_PRES EQU (1 << 7) 13 | 14 | SEG_LONG EQU (1 << 5) 15 | SEG_DB EQU (1 << 6) 16 | SEG_GRAN EQU (1 << 7) 17 | 18 | align 4 19 | global ap_trampoline 20 | ap_trampoline: 21 | cli 22 | cld 23 | 24 | mov eax, cr4 25 | or eax, (1 << 5) 26 | mov cr4, eax 27 | 28 | mov ecx, 0xC0000080 29 | rdmsr 30 | or eax, (1 << 8) 31 | wrmsr 32 | 33 | mov eax, dword [PML4] 34 | mov cr3, eax 35 | 36 | lgdt [gdt64.pointer] 37 | 38 | mov eax, cr0 39 | and eax, 0x0fffffff ; disable per-cpu caching 40 | or eax, 0x80000001 41 | mov cr0, eax 42 | 43 | jmp gdt64.code:long_mode 44 | 45 | gdt64: 46 | .null: equ $ - gdt64 47 | dq 0 48 | .code: equ $ - gdt64 49 | dw 0xFFFF ; limit_lo 50 | dw 0 ; base_lo 51 | db 0 ; base_mid 52 | db (SEG_PRES | SEG_DPL0 | SEG_TYPE | SEG_CODE | SEG_RW) 53 | db (SEG_GRAN | SEG_LONG | 0XF) 54 | db 0 55 | .data: equ $ - gdt64 56 | dw 0xFFFF 57 | dw 0 58 | db 0 59 | db (SEG_PRES | SEG_DPL0 | SEG_TYPE | SEG_RW) 60 | db (SEG_GRAN | SEG_DB | 0XF) 61 | db 0 62 | .pointer: 63 | dw $ - gdt64 - 1 64 | dq (gdt64) 65 | 66 | [bits 64] 67 | 68 | long_mode: 69 | mov ax, 0x10 70 | mov ds, ax 71 | mov es, ax 72 | mov fs, ax 73 | mov gs, ax 74 | mov ss, ax 75 | mov rsp, qword [stack] 76 | mov rbp, rsp 77 | mov rax, qword[entry] 78 | 79 | call rax ; AP entry 80 | 81 | cli 82 | hlt 83 | jmp $ 84 | 85 | times 4024 - ($ - $$) db 0 86 | PML4: dq 0 ; Level 4 Page Map 87 | stack: dq 0 ; AP bootstrap stack. 88 | entry: dq 0 ; AP entry point -------------------------------------------------------------------------------- /kernel/dev/chr/pseudodev/null.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | static int null_init(void); 8 | static int null_probe(void); 9 | static int null_close(struct devid *dd); 10 | static int null_getinfo(struct devid *dd, void *info); 11 | static int null_open(struct devid *dd); 12 | static int null_ioctl(struct devid *dd, int req, void *argp); 13 | static off_t null_lseek(struct devid *dd, off_t off, int whence); 14 | static ssize_t null_read(struct devid *dd, off_t off, void *buf, size_t sz); 15 | static ssize_t null_write(struct devid *dd, off_t off, void *buf, size_t sz); 16 | static int null_mmap(struct devid *dd, vmr_t *region); 17 | 18 | static DEV_INIT(null, FS_CHR, DEV_NULL, 3); 19 | 20 | static int null_init(void) { 21 | printk("Initializing \e[025453;011m%s\e[0m chardev...\n", nulldev.devname); 22 | return kdev_register(&nulldev, DEV_NULL, FS_CHR); 23 | } 24 | 25 | static int null_probe(void) { 26 | return 0; 27 | } 28 | 29 | static int null_close(struct devid *dd __unused) { 30 | return 0; 31 | } 32 | 33 | static int null_getinfo(struct devid *dd __unused, void *info __unused) { 34 | return -ENOTSUP; 35 | } 36 | 37 | static int null_open(struct devid *dd __unused) { 38 | return 0; 39 | } 40 | 41 | static int null_ioctl(struct devid *dd __unused, int req __unused, void *argp __unused) { 42 | return -ENOTSUP; 43 | } 44 | 45 | static off_t null_lseek(struct devid *dd __unused, off_t off __unused, int whence __unused) { 46 | return -ENOTSUP; 47 | } 48 | 49 | static ssize_t null_read(struct devid *dd __unused, off_t off __unused, void *buf __unused, size_t sz __unused) { 50 | return 0; 51 | } 52 | 53 | static ssize_t null_write(struct devid *dd __unused, off_t off __unused, void *buf __unused, size_t sz) { 54 | return sz; 55 | } 56 | 57 | static int null_mmap(struct devid *dd, vmr_t *region) { 58 | if (dd == NULL || region == NULL) 59 | return -EINVAL; 60 | 61 | return -ENOSYS; 62 | } 63 | 64 | MODULE_INIT(null, NULL, null_init, NULL); -------------------------------------------------------------------------------- /kernel/dev/chr/console/console.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | DEV_DECL_OPS(static, console); 13 | static DEV_INIT(console, FS_CHR, DEV_CONSOLE, 1); 14 | 15 | static int use_fb = 0; 16 | 17 | static int console_probe(void) { 18 | return 0; 19 | } 20 | 21 | static int console_init(void) { 22 | printk("Initializing \e[025453;011m%s\e[0m chardev...\n", consoledev.devname); 23 | if (bootinfo.fb.type == 1) 24 | use_fb = 1; 25 | 26 | if (use_fb) 27 | printk("console will use framebuffer\n"); 28 | 29 | return kdev_register(&consoledev, DEV_CONSOLE, FS_CHR); 30 | } 31 | 32 | int console_putc(int c) { 33 | uart_putc(c); 34 | if (use_earlycons) 35 | return earlycons_putc(c); 36 | return 0; 37 | } 38 | 39 | static int console_open(struct devid *dd __unused) { 40 | return 0; 41 | } 42 | 43 | static int console_close(struct devid *dd __unused) { 44 | return 0; 45 | } 46 | 47 | static int console_ioctl(struct devid *dd __unused, int req __unused, void *argp __unused) { 48 | return 0; 49 | } 50 | 51 | static isize console_write(struct devid *dd __unused, off_t off __unused, void *buf __unused, usize sz __unused) { 52 | for (char *c = buf; sz--; ++c) { 53 | console_putc(*c); 54 | } 55 | return 0; 56 | } 57 | 58 | static isize console_read(struct devid *dd __unused, off_t off __unused, void *buf __unused, usize sz __unused) { 59 | return 0; 60 | } 61 | 62 | static int console_mmap(struct devid *dd __unused, vmr_t *vmr __unused) { 63 | return -EOPNOTSUPP; 64 | } 65 | 66 | static int console_getinfo(struct devid *dd __unused, void *info __unused) { 67 | return -EOPNOTSUPP; 68 | } 69 | 70 | static off_t console_lseek(struct devid *dd __unused, off_t off __unused, int whence __unused) { 71 | return -EOPNOTSUPP; 72 | } 73 | 74 | MODULE_INIT(console, NULL, console_init, NULL); -------------------------------------------------------------------------------- /kernel/dev/chr/pseudodev/zero.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | static int zero_init(void); 8 | static int zero_probe(void); 9 | static int zero_close(struct devid *dd); 10 | static int zero_getinfo(struct devid *dd, void *info); 11 | static int zero_open(struct devid *dd); 12 | static int zero_ioctl(struct devid *dd, int req, void *argp); 13 | static off_t zero_lseek(struct devid *dd, off_t off, int whence); 14 | static ssize_t zero_read(struct devid *dd, off_t off, void *buf, size_t sz); 15 | static ssize_t zero_write(struct devid *dd, off_t off, void *buf, size_t sz); 16 | static int zero_mmap(struct devid *dd, vmr_t *region); 17 | 18 | static DEV_INIT(zero, FS_CHR, DEV_ZERO, 5); 19 | 20 | static int zero_init(void) { 21 | printk("Initializing \e[025453;011m%s\e[0m chardev...\n", zerodev.devname); 22 | return kdev_register(&zerodev, DEV_ZERO, FS_CHR); 23 | } 24 | 25 | static int zero_probe(void) { 26 | return 0; 27 | } 28 | 29 | static int zero_close(struct devid *dd __unused) { 30 | return 0; 31 | } 32 | 33 | static int zero_getinfo(struct devid *dd __unused, void *info __unused) { 34 | return -ENOTSUP; 35 | } 36 | 37 | static int zero_open(struct devid *dd __unused) { 38 | return 0; 39 | } 40 | 41 | static int zero_ioctl(struct devid *dd __unused, int req __unused, void *argp __unused) { 42 | return -ENOTSUP; 43 | } 44 | 45 | static off_t zero_lseek(struct devid *dd __unused, off_t off __unused, int whence __unused) { 46 | return -ENOTSUP; 47 | } 48 | 49 | static ssize_t zero_read(struct devid *dd __unused, off_t off __unused, void *buf, size_t sz) { 50 | memset(buf, '\0', sz); 51 | return sz; 52 | } 53 | 54 | static ssize_t zero_write(struct devid *dd __unused, off_t off __unused, void *buf __unused, size_t sz) { 55 | return sz; 56 | } 57 | 58 | static int zero_mmap(struct devid *dd, vmr_t *region) { 59 | if (dd == NULL || region == NULL) 60 | return -EINVAL; 61 | 62 | return -ENOSYS; 63 | } 64 | 65 | MODULE_INIT(zero, NULL, zero_init, NULL); -------------------------------------------------------------------------------- /kernel/dev/chr/ps2/mouse.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | static int ps2mouse_init(void); 5 | static int ps2mouse_probe(void); 6 | static int ps2mouse_close(struct devid *dd); 7 | static int ps2mouse_getinfo(struct devid *dd, void *info); 8 | static int ps2mouse_open(struct devid *dd); 9 | static int ps2mouse_ioctl(struct devid *dd, int req, void *argp); 10 | static off_t ps2mouse_lseek(struct devid *dd, off_t off, int whence); 11 | static ssize_t ps2mouse_read(struct devid *dd, off_t off, void *buf, size_t sz); 12 | static ssize_t ps2mouse_write(struct devid *dd, off_t off, void *buf, size_t sz); 13 | static int ps2mouse_mmap(struct devid *dd, vmr_t *region); 14 | 15 | static DEV_INIT(ps2mouse, FS_CHR, DEV_MOUSE0, 1); 16 | 17 | static int ps2mouse_init(void) { 18 | printk("Initializing \e[025453;011m%s\e[0m chardev...\n", ps2mousedev.devname); 19 | return kdev_register(&ps2mousedev, DEV_MOUSE0, FS_CHR); 20 | } 21 | 22 | static int ps2mouse_probe(void) { 23 | return 0; 24 | } 25 | 26 | static int ps2mouse_close(struct devid *dd __unused) { 27 | return 0; 28 | } 29 | 30 | static int ps2mouse_getinfo(struct devid *dd __unused, void *info __unused) { 31 | return -ENOTSUP; 32 | } 33 | 34 | static int ps2mouse_open(struct devid *dd __unused) { 35 | return 0; 36 | } 37 | 38 | static int ps2mouse_ioctl(struct devid *dd __unused, int req __unused, void *argp __unused) { 39 | return -ENOTSUP; 40 | } 41 | 42 | static off_t ps2mouse_lseek(struct devid *dd __unused, off_t off __unused, int whence __unused) { 43 | return -ENOTSUP; 44 | } 45 | 46 | static ssize_t ps2mouse_read(struct devid *dd __unused, off_t off __unused, void *buf __unused, size_t sz __unused) { 47 | return 0; 48 | } 49 | 50 | static ssize_t ps2mouse_write(struct devid *dd __unused, off_t off __unused, void *buf __unused, size_t sz) { 51 | return sz; 52 | } 53 | 54 | static int ps2mouse_mmap(struct devid *dd, vmr_t *region) { 55 | if (dd == NULL || region == NULL) 56 | return -EINVAL; 57 | return -ENOSYS; 58 | } 59 | 60 | MODULE_INIT(ps2mouse, NULL, ps2mouse_init, NULL); -------------------------------------------------------------------------------- /usr/include/sys/system.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #define __CAT(a, b) a##b 7 | 8 | #define __unused __attribute__((unused)) 9 | #define __packed __attribute__((packed)) 10 | #define __aligned(n) __attribute__((aligned(n))) 11 | #define __noreturn __attribute__((noreturn)) 12 | #define __section(s) __attribute__((section(#s))) 13 | #define __aligned_section(s, a) __attribute__((section(#s), aligned(a))) 14 | #define __fallthrough __attribute__((fallthrough)) 15 | #define __used_section(__section__) __attribute__((used, section(#__section__))) 16 | #define barrier() ({ asm volatile ("":::"memory"); }) 17 | 18 | #define loop() for (;;) 19 | 20 | #define forlinked(elem, list, iter) \ 21 | for (typeof(list) elem = list; elem; elem = iter) 22 | 23 | #define foreach(elem, list) \ 24 | for (typeof(*list) *tmp = list, elem = *tmp; elem; elem = *++tmp) 25 | 26 | #ifndef container_of 27 | #define container_of(ptr, type, member) ({ \ 28 | const typeof( ((type *)0)->member ) *__mptr = (ptr); \ 29 | (type *)( (char *)__mptr - offsetof(type,member) ); }) 30 | #endif 31 | 32 | #define BCD2binary(bcd) ((((bcd) & 0xF0) >> 1) + (((bcd) & 0xF0) >> 3) + ((bcd) & 0xf)) 33 | 34 | #define __retaddr(l) __builtin_return_address(l) 35 | 36 | #define NOT(a) (~(uintptr_t)(a)) 37 | #define BS(p) ((uintptr_t)(1) << (p)) 38 | #define AND(a, b) ((uintptr_t)(a) & (uintptr_t)(b)) 39 | #define OR(a, b) ((uintptr_t)(a) | (uintptr_t)(b)) 40 | #define XOR(a, b) ((uintptr_t)(a) ^ (uintptr_t)(b)) 41 | #define SHL(a, b) ((uintptr_t)(a) <<(uintptr_t)(b)) 42 | #define SHR(a, b) ((uintptr_t)(a) >>(uintptr_t)(b)) 43 | #define NAND(a, b) (AND(NOT((a)), (b))) 44 | #define BTEST(a, b) (AND((a), BS(b))) 45 | #define MAX(a, b) ((long)((a) > (b) ? (a) : (b))) 46 | #define MIN(a, b) ((long)((a) < (b) ? (a) : (b))) 47 | #define ABS(a) (((long)(a) < 0) ? -(long)(a) : (a)) 48 | 49 | // C('A') == Control-A 50 | #define CTRL(x) ((x) - '@') -------------------------------------------------------------------------------- /kernel/dev/chr/pseudodev/full.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | static int full_init(void); 8 | static int full_probe(void); 9 | static int full_close(struct devid *dd); 10 | static int full_getinfo(struct devid *dd, void *info); 11 | static int full_open(struct devid *dd); 12 | static int full_ioctl(struct devid *dd, int req, void *argp); 13 | static off_t full_lseek(struct devid *dd, off_t off, int whence); 14 | static ssize_t full_read(struct devid *dd, off_t off, void *buf, size_t sz); 15 | static ssize_t full_write(struct devid *dd, off_t off, void *buf, size_t sz); 16 | static int full_mmap(struct devid *dd, vmr_t *region); 17 | 18 | static DEV_INIT(full, FS_CHR, DEV_FULL, 7); 19 | 20 | static int full_init(void) { 21 | printk("Initializing \e[025453;011m%s\e[0m chardev...\n", fulldev.devname); 22 | return kdev_register(&fulldev, DEV_FULL, FS_CHR); 23 | } 24 | 25 | static int full_probe(void) { 26 | return 0; 27 | } 28 | 29 | static int full_close(struct devid *dd __unused) { 30 | return 0; 31 | } 32 | 33 | static int full_getinfo(struct devid *dd __unused, void *info __unused) { 34 | return -ENOTSUP; 35 | } 36 | 37 | static int full_open(struct devid *dd __unused) { 38 | return 0; 39 | } 40 | 41 | static int full_ioctl(struct devid *dd __unused, int req __unused, void *argp __unused) { 42 | return 0; 43 | } 44 | 45 | static off_t full_lseek(struct devid *dd __unused, off_t off __unused, int whence __unused) { 46 | return 0; 47 | } 48 | 49 | static ssize_t full_read(struct devid *dd __unused, off_t off __unused, void *buf, size_t sz) { 50 | if (buf == NULL) 51 | return -EINVAL; 52 | memset(buf, 0, sz); 53 | return sz; 54 | } 55 | 56 | static ssize_t full_write(struct devid *dd __unused, off_t off __unused, void *buf __unused, size_t sz __unused) { 57 | return -ENOSPC; 58 | } 59 | 60 | static int full_mmap(struct devid *dd, vmr_t *region) { 61 | if (dd == NULL || region == NULL) 62 | return -EINVAL; 63 | 64 | return -ENOSYS; 65 | } 66 | 67 | MODULE_INIT(full, NULL, full_init, NULL); -------------------------------------------------------------------------------- /kernel/dev/chr/pseudodev/random.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | static int random_init(void); 8 | static int random_probe(void); 9 | static int random_close(struct devid *dd); 10 | static int random_getinfo(struct devid *dd, void *info); 11 | static int random_open(struct devid *dd); 12 | static int random_ioctl(struct devid *dd, int req, void *argp); 13 | static off_t random_lseek(struct devid *dd, off_t off, int whence); 14 | static ssize_t random_read(struct devid *dd, off_t off, void *buf, size_t sz); 15 | static ssize_t random_write(struct devid *dd, off_t off, void *buf, size_t sz); 16 | static int random_mmap(struct devid *dd, vmr_t *region); 17 | 18 | static DEV_INIT(random, FS_CHR, DEV_RANDOM, 8); 19 | 20 | static int random_init(void) { 21 | printk("Initializing \e[025453;011m%s\e[0m chardev...\n", randomdev.devname); 22 | return kdev_register(&randomdev, DEV_RANDOM, FS_CHR); 23 | } 24 | 25 | static int random_probe(void) { 26 | return 0; 27 | } 28 | 29 | static int random_close(struct devid *dd __unused) { 30 | return 0; 31 | } 32 | 33 | static int random_getinfo(struct devid *dd __unused, void *info __unused) { 34 | return -ENOTSUP; 35 | } 36 | 37 | static int random_open(struct devid *dd __unused) { 38 | return 0; 39 | } 40 | 41 | static int random_ioctl(struct devid *dd __unused, int req __unused, void *argp __unused) 42 | { 43 | return -ENOTSUP; 44 | } 45 | 46 | static off_t random_lseek(struct devid *dd __unused, off_t off __unused, int whence __unused) { 47 | return -ENOTSUP; 48 | } 49 | 50 | static ssize_t random_read(struct devid *dd __unused, off_t off __unused, void *buf __unused, size_t sz __unused) { 51 | return -ENOTSUP; 52 | } 53 | 54 | static ssize_t random_write(struct devid *dd __unused, off_t off __unused, void *buf __unused, size_t sz __unused) { 55 | return -ENOTSUP; 56 | } 57 | 58 | static int random_mmap(struct devid *dd, vmr_t *region) { 59 | if (dd == NULL || region == NULL) 60 | return -EINVAL; 61 | 62 | return -ENOSYS; 63 | } 64 | 65 | MODULE_INIT(random, NULL, random_init, NULL); -------------------------------------------------------------------------------- /usr/include/string.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | void *memchr(const void *s, int c, size_t n); 6 | void *memrchr(const void *m, int c, size_t n); 7 | int memcmp(const void *s1, const void *s2, size_t n); 8 | void *memcpy(void *restrict s1, const void *restrict s2, size_t n); 9 | void *memmove(void *dest, const void *src, size_t n); 10 | void *memset(void *s, int c, size_t n); 11 | void *memsetw(void *s, int c, size_t n); 12 | 13 | char *safestrncpy(char *restrict dest, const char *restrict src, size_t n); 14 | 15 | long atol(const char *s); 16 | int atoi(const char *s); 17 | 18 | size_t lfind(const char *str, const char accept); 19 | size_t rfind(const char *str, const char accept); 20 | char *strtok_r(char *str, const char *delim, char **saveptr); 21 | char *strtok(char *str, const char *delim); 22 | 23 | char *stpcpy(char *restrict d, const char *restrict s); 24 | size_t strspn(const char *s, const char *c); 25 | char *strchrnul(const char *s, int c); 26 | char *strcat(char *restrict dest, const char *restrict src); 27 | char *strchr(const char *s, int c); 28 | char *strrchr(const char *s, int c); 29 | size_t strcspn(const char *s, const char *c); 30 | char *strpbrk(const char *s, const char *b); 31 | int strcmp(const char *s1, const char *s2); 32 | char *strcpy(char *restrict dest, const char *restrict src); 33 | char *strdup(const char *s); 34 | size_t strlen(const char *s); 35 | 36 | char *strncat(char *restrict dest, const char *restrict src, size_t n); 37 | int strncmp(const char *s1, const char *s2, size_t n); 38 | char *strncpy(char *restrict dest, const char *restrict src, size_t n); 39 | char *strndup(const char *s, size_t n); 40 | char *strrchr(const char *s, int c); 41 | 42 | int strcasecmp(const char *s1, const char *s2); 43 | int strncasecmp(const char *s1, const char *s2, size_t n); 44 | 45 | int compare_strings(const char *s0, const char *s1); 46 | char *combine_strings(const char *s0, const char *s1); 47 | void tokens_free(char **tokens); 48 | char **tokenize(char *s, int c, size_t *ptoks, char **plast_tok); 49 | char **canonicalize_path(const char *path, size_t *ptoks, char **plast); -------------------------------------------------------------------------------- /usr/lib/wchar/wcstol.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | static int is_valid(int base, wchar_t c) { 8 | if (c < '0') return 0; 9 | if (base <= 10) { 10 | return c < ('0' + (wchar_t)base); 11 | } 12 | 13 | if (c >= 'a' && c < 'a' + ((wchar_t)base - 10)) return 1; 14 | if (c >= 'A' && c < 'A' + ((wchar_t)base - 10)) return 1; 15 | if (c >= '0' && c <= '9') return 1; 16 | return 0; 17 | } 18 | 19 | static int convert_digit(wchar_t c) { 20 | if (c >= '0' && c <= '9') { 21 | return c - '0'; 22 | } 23 | if (c >= 'a' && c <= 'z') { 24 | return c - 'a' + 0xa; 25 | } 26 | if (c >= 'A' && c <= 'Z') { 27 | return c - 'A' + 0xa; 28 | } 29 | return 0; 30 | } 31 | 32 | #define strtox(max, type) \ 33 | if (base < 0 || base == 1 || base > 36) { \ 34 | errno = EINVAL; \ 35 | return max; \ 36 | } \ 37 | while (*nptr && isspace(*nptr)) nptr++; \ 38 | int sign = 1; \ 39 | if (*nptr == '-') { \ 40 | sign = -1; \ 41 | nptr++; \ 42 | } else if (*nptr == '+') { \ 43 | nptr++; \ 44 | } \ 45 | if (base == 16) { \ 46 | if (*nptr == '0') { \ 47 | nptr++; \ 48 | if (*nptr == 'x') { \ 49 | nptr++; \ 50 | } \ 51 | } \ 52 | } \ 53 | if (base == 0) { \ 54 | if (*nptr == '0') { \ 55 | base = 8; \ 56 | nptr++; \ 57 | if (*nptr == 'x') { \ 58 | base = 16; \ 59 | nptr++; \ 60 | } \ 61 | } else { \ 62 | base = 10; \ 63 | } \ 64 | } \ 65 | type val = 0; \ 66 | while (is_valid(base, *nptr)) { \ 67 | val *= base; \ 68 | val += convert_digit(*nptr); \ 69 | nptr++; \ 70 | } \ 71 | if (endptr) { \ 72 | *endptr = (wchar_t *)nptr; \ 73 | } \ 74 | if (sign == -1) { \ 75 | return -val; \ 76 | } else { \ 77 | return val; \ 78 | } 79 | 80 | unsigned long int wcstoul(const wchar_t *nptr, wchar_t **endptr, int base) { 81 | strtox(ULONG_MAX, unsigned long int); 82 | } 83 | 84 | unsigned long long int wcstoull(const char *nptr, wchar_t **endptr, int base) { 85 | strtox(ULLONG_MAX, unsigned long int); 86 | } 87 | 88 | long int wcstol(const wchar_t *nptr, wchar_t **endptr, int base) { 89 | strtox(LONG_MAX, unsigned long int); 90 | } 91 | 92 | long long int wcstoll(const wchar_t *nptr, wchar_t **endptr, int base) { 93 | strtox(LLONG_MAX, unsigned long long int); 94 | } 95 | 96 | -------------------------------------------------------------------------------- /kernel/include/fs/icache.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | typedef struct icache_t icache_t; 11 | typedef struct icache_t { 12 | long pc_refcnt; 13 | uint32_t pc_flags; 14 | inode_t *pc_inode; 15 | btree_t pc_btree; 16 | queue_t pc_queue; 17 | size_t pc_nrpages; 18 | spinlock_t pc_lock; 19 | } icache_t; 20 | 21 | #define BTREE_INIT() ((btree_t){0}) 22 | #define BTREE_NEW() (&BTREE_INIT()) 23 | 24 | #define icache_assert(icache) ({assert(icache, "No page cache"); }) 25 | #define icache_lock(icache) ({icache_assert(icache); spin_lock(&(icache)->pc_lock); }) 26 | #define icache_unlock(icache) ({icache_assert(icache); spin_unlock(&(icache)->pc_lock); }) 27 | #define icache_islocked(icache) ({icache_assert(icache); spin_islocked(&(icache)->pc_lock); }) 28 | #define icache_assert_locked(icache) ({icache_assert(icache); spin_assert_locked(&(icache)->pc_lock); }) 29 | 30 | #define icache_btree(icache) ({icache_assert_locked(icache); &(icache)->pc_btree; }) 31 | #define icache_queue(icache) ({icache_assert_locked(icache); &(icache)->pc_queue; }) 32 | 33 | #define icache_btree_lock(icache) ({btree_lock(icache_btree(icache)); }) 34 | #define icache_btree_unlock(icache) ({btree_unlock(icache_btree(icache)); }) 35 | #define icache_btree_islocked(icache) ({btree_islocked(icache_btree(icache)); }) 36 | #define icache_btree_assert_locked(icache) ({btree_assert_locked(icache_btree(icache)); }) 37 | 38 | #define icache_queue_lock(icache) ({ queue_lock(icache_queue(icache)); }) 39 | #define icache_queue_unlock(icache) ({ queue_unlock(icache_queue(icache)); }) 40 | #define icache_queue_islocked(icache) ({queue_islocked(icache_queue(icache)); }) 41 | #define icache_queue_assert_locked(icache) ({queue_assert_locked(icache_queue(icache)); }) 42 | 43 | int icache_alloc(icache_t **ppcp); 44 | void icache_free(icache_t *icache); 45 | int icache_getpage(icache_t *icache, off_t pgno, page_t **page); 46 | ssize_t icache_read(icache_t *icache, off_t off, void *buf, size_t size); 47 | ssize_t icache_write(icache_t *icache, off_t off, void *buf, size_t size); -------------------------------------------------------------------------------- /usr/include/bits/waitstatus.h: -------------------------------------------------------------------------------- 1 | /* Definitions of status bits for `wait' et al. 2 | Copyright (C) 1992-2022 Free Software Foundation, Inc. 3 | This file is part of the GNU C Library. 4 | 5 | The GNU C Library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | The GNU C Library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with the GNU C Library; if not, see 17 | . */ 18 | 19 | 20 | /* Everything extant so far uses these same bits. */ 21 | 22 | 23 | /* If WIFEXITED(STATUS), the low-order 8 bits of the status. */ 24 | #define __WEXITSTATUS(status) (((status) & 0xff00) >> 8) 25 | 26 | /* If WIFSIGNALED(STATUS), the terminating signal. */ 27 | #define __WTERMSIG(status) ((status) & 0x7f) 28 | 29 | /* If WIFSTOPPED(STATUS), the signal that stopped the child. */ 30 | #define __WSTOPSIG(status) __WEXITSTATUS(status) 31 | 32 | /* Nonzero if STATUS indicates normal termination. */ 33 | #define __WIFEXITED(status) (__WTERMSIG(status) == 0) 34 | 35 | /* Nonzero if STATUS indicates termination by a signal. */ 36 | #define __WIFSIGNALED(status) \ 37 | (((signed char) (((status) & 0x7f) + 1) >> 1) > 0) 38 | 39 | /* Nonzero if STATUS indicates the child is stopped. */ 40 | #define __WIFSTOPPED(status) (((status) & 0xff) == 0x7f) 41 | 42 | /* Nonzero if STATUS indicates the child continued after a stop. We only 43 | define this if provides the WCONTINUED flag bit. */ 44 | #ifdef WCONTINUED 45 | # define __WIFCONTINUED(status) ((status) == __W_CONTINUED) 46 | #endif 47 | 48 | /* Nonzero if STATUS indicates the child dumped core. */ 49 | #define __WCOREDUMP(status) ((status) & __WCOREFLAG) 50 | 51 | /* Macros for constructing status values. */ 52 | #define __W_EXITCODE(ret, sig) ((ret) << 8 | (sig)) 53 | #define __W_STOPCODE(sig) ((sig) << 8 | 0x7f) 54 | #define __W_CONTINUED 0xffff 55 | #define __WCOREFLAG 0x80 56 | -------------------------------------------------------------------------------- /kernel/arch/thread.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | void arch_thread_exit(uintptr_t exit_code) { 11 | #if defined (__x86_64__) 12 | x86_64_thread_exit(exit_code); 13 | #endif 14 | } 15 | 16 | int arch_uthread_init(arch_thread_t *arch, thread_entry_t entry, void *arg) { 17 | #if defined __x86_64__ 18 | return x86_64_uthread_init(arch, entry, arg); 19 | #endif 20 | } 21 | 22 | int arch_kthread_init(arch_thread_t *arch, thread_entry_t entry, void *arg) { 23 | #if defined __x86_64__ 24 | return x86_64_kthread_init(arch, entry, arg); 25 | #endif 26 | } 27 | 28 | char ***arch_execve_copy(char *_argp[], char *_envp[]) { 29 | int argc = 0; 30 | int envc = 0; 31 | char **argp = NULL; 32 | char **envp = NULL; 33 | char ***ptr = kcalloc(3, sizeof(char **)); 34 | 35 | if (_argp) foreach (token, _argp) argc++; 36 | 37 | if (_envp) foreach (token, _envp) envc++; 38 | 39 | argp = kcalloc(argc + 1, sizeof(char *)); 40 | argp[argc] = NULL; 41 | 42 | envp = kcalloc(envc + 1, sizeof(char *)); 43 | envp[envc] = NULL; 44 | 45 | if (_argp) { 46 | foreach (arg, _argp) { 47 | argc--; 48 | argp[argc] = strdup(_argp[argc]); 49 | } 50 | } 51 | 52 | if (_envp) { 53 | foreach (env, _envp) { 54 | envc--; 55 | envp[envc] = strdup(_envp[envc]); 56 | } 57 | } 58 | 59 | ptr[0] = argp; 60 | ptr[1] = envp; 61 | ptr[2] = NULL; 62 | 63 | return ptr; 64 | } 65 | 66 | void arch_exec_free_copy(char ***arg_env) { 67 | if (!arg_env) return; 68 | foreach (list, arg_env) foreach (arg, list) kfree(arg); 69 | kfree(arg_env); 70 | } 71 | 72 | int arch_thread_execve(arch_thread_t *arch, thread_entry_t entry, int argc, const char *argp[], const char *envp[]) { 73 | #if defined __x86_64__ 74 | return x86_64_thread_execve(arch, entry, argc, argp, envp); 75 | #endif 76 | } 77 | 78 | int arch_thread_setkstack(arch_thread_t *arch) { 79 | #if defined __x86_64__ 80 | return x86_64_thread_setkstack(arch); 81 | #endif 82 | } 83 | 84 | int arch_thread_fork(arch_thread_t *dst, arch_thread_t *src) { 85 | #if defined __x86_64__ 86 | return x86_64_thread_fork(dst, src); 87 | #endif 88 | } -------------------------------------------------------------------------------- /kernel/include/bits/waitstatus.h: -------------------------------------------------------------------------------- 1 | /* Definitions of status bits for `wait' et al. 2 | Copyright (C) 1992-2022 Free Software Foundation, Inc. 3 | This file is part of the GNU C Library. 4 | 5 | The GNU C Library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | The GNU C Library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with the GNU C Library; if not, see 17 | . */ 18 | 19 | 20 | /* Everything extant so far uses these same bits. */ 21 | 22 | 23 | /* If WIFEXITED(STATUS), the low-order 8 bits of the status. */ 24 | #define __WEXITSTATUS(status) (((status) & 0xff00) >> 8) 25 | 26 | /* If WIFSIGNALED(STATUS), the terminating signal. */ 27 | #define __WTERMSIG(status) ((status) & 0x7f) 28 | 29 | /* If WIFSTOPPED(STATUS), the signal that stopped the child. */ 30 | #define __WSTOPSIG(status) __WEXITSTATUS(status) 31 | 32 | /* Nonzero if STATUS indicates normal termination. */ 33 | #define __WIFEXITED(status) (__WTERMSIG(status) == 0) 34 | 35 | /* Nonzero if STATUS indicates termination by a signal. */ 36 | #define __WIFSIGNALED(status) \ 37 | (((signed char) (((status) & 0x7f) + 1) >> 1) > 0) 38 | 39 | /* Nonzero if STATUS indicates the child is stopped. */ 40 | #define __WIFSTOPPED(status) (((status) & 0xff) == 0x7f) 41 | 42 | /* Nonzero if STATUS indicates the child continued after a stop. We only 43 | define this if provides the WCONTINUED flag bit. */ 44 | #ifdef WCONTINUED 45 | # define __WIFCONTINUED(status) ((status) == __W_CONTINUED) 46 | #endif 47 | 48 | /* Nonzero if STATUS indicates the child dumped core. */ 49 | #define __WCOREDUMP(status) ((status) & __WCOREFLAG) 50 | 51 | /* Macros for constructing status values. */ 52 | #define __W_EXITCODE(ret, sig) ((ret) << 8 | (sig)) 53 | #define __W_STOPCODE(sig) ((sig) << 8 | 0x7f) 54 | #define __W_CONTINUED 0xffff 55 | #define __WCOREFLAG 0x80 56 | -------------------------------------------------------------------------------- /usr/include/stdlib.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include <_cheader.h> 4 | #include 5 | 6 | _Begin_C_Header 7 | 8 | extern void exit(int status); 9 | extern char * getenv(const char *name); 10 | 11 | extern void *malloc(size_t size); 12 | extern void free(void *ptr); 13 | extern void *calloc(size_t nmemb, size_t size); 14 | extern void *realloc(void *ptr, size_t size); 15 | 16 | extern void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void*,const void*)); 17 | 18 | extern int system(const char * command); 19 | 20 | extern int abs(int j); 21 | 22 | extern int putenv(char * name); 23 | extern int setenv(const char *name, const char *value, int overwrite); 24 | extern int unsetenv(const char * str); 25 | 26 | extern double strtod(const char *nptr, char **endptr); 27 | extern float strtof(const char *nptr, char **endptr); 28 | extern double atof(const char * nptr); 29 | extern int atoi(const char * nptr); 30 | extern long atol(const char * nptr); 31 | extern long int labs(long int j); 32 | extern long int strtol(const char * s, char **endptr, int base); 33 | extern long long int strtoll(const char *nptr, char **endptr, int base); 34 | extern unsigned long int strtoul(const char *nptr, char **endptr, int base); 35 | extern unsigned long long int strtoull(const char *nptr, char **endptr, int base); 36 | 37 | extern void srand(unsigned int); 38 | extern int rand(void); 39 | 40 | #define ATEXIT_MAX 32 41 | extern int atexit(void (*h)(void)); 42 | extern void _handle_atexit(void); 43 | 44 | #define RAND_MAX 0x7FFFFFFF 45 | 46 | extern void abort(void); 47 | 48 | #define EXIT_SUCCESS 0 49 | #define EXIT_FAILURE 1 50 | 51 | extern void *bsearch(const void *key, const void *base, size_t nmemb, size_t size, 52 | int (*compar)(const void *, const void *)); 53 | 54 | extern char * mktemp(char *); 55 | extern int mkstemp(char *); 56 | 57 | extern size_t mbstowcs(wchar_t *dest, const char *src, size_t n); 58 | extern size_t wcstombs(char * dest, const wchar_t *src, size_t n); 59 | 60 | typedef struct { int quot; int rem; } div_t; 61 | typedef struct { long int quot; long int rem; } ldiv_t; 62 | 63 | extern div_t div(int numerator, int denominator); 64 | extern ldiv_t ldiv(long numerator, long denominator); 65 | 66 | /* These are supposed to be in limits, but gcc screwed us */ 67 | #define PATH_MAX 4096 68 | #define NAME_MAX 255 69 | extern char *realpath(const char *path, char *resolved_path); 70 | 71 | _End_C_Header 72 | -------------------------------------------------------------------------------- /kernel/include/lib/string.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | void *memchr(const void *s, int c, size_t n); 7 | void *memrchr(const void *m, int c, size_t n); 8 | int memcmp(const void *s1, const void *s2, size_t n); 9 | void *memcpy(void *restrict s1, const void *restrict s2, size_t n); 10 | void *memmove(void *dest, const void *src, size_t n); 11 | void *memset(void *s, int c, size_t n); 12 | void *memsetw(void *s, int c, size_t n); 13 | 14 | char *safestrncpy(char *restrict dest, const char *restrict src, size_t n); 15 | 16 | long atol(const char *s); 17 | int atoi(const char *s); 18 | 19 | size_t lfind(const char *str, const char accept); 20 | size_t rfind(const char *str, const char accept); 21 | char *strtok_r(char *str, const char *delim, char **saveptr); 22 | char *strtok(char *str, const char *delim); 23 | 24 | char *stpcpy(char *restrict d, const char *restrict s); 25 | size_t strspn(const char *s, const char *c); 26 | char *strchrnul(const char *s, int c); 27 | char *strcat(char *restrict dest, const char *restrict src); 28 | char *strchr(const char *s, int c); 29 | char *strrchr(const char *s, int c); 30 | size_t strcspn(const char *s, const char *c); 31 | char *strpbrk(const char *s, const char *b); 32 | int strcmp(const char *s1, const char *s2); 33 | char *strcpy(char *restrict dest, const char *restrict src); 34 | char *strdup(const char *s); 35 | size_t strlen(const char *s); 36 | 37 | char *strncat(char *restrict dest, const char *restrict src, size_t n); 38 | int strncmp(const char *s1, const char *s2, size_t n); 39 | char *strncpy(char *restrict dest, const char *restrict src, size_t n); 40 | char *strndup(const char *s, size_t n); 41 | char *strrchr(const char *s, int c); 42 | 43 | int strcasecmp(const char *s1, const char *s2); 44 | int strncasecmp(const char *s1, const char *s2, size_t n); 45 | 46 | /// test strings for equality, based of contents. 47 | /// @returns 1 on success and 0 no failure. 48 | int string_eq(const char *str0, const char *str1); 49 | int compare_strings(const char *s0, const char *s1); 50 | char *combine_strings(const char *s0, const char *s1); 51 | void tokens_free(char **tokens); 52 | int tokenize(char *s, int c, size_t *ntoks, char ***tokenized, char **plast_tok); 53 | int canonicalize_path(const char *path, size_t *ntoks, char ***ptokenized, char **plast); -------------------------------------------------------------------------------- /usr/include/ginger/liballoc_1_1.h: -------------------------------------------------------------------------------- 1 | #ifndef _LIBALLOC_H 2 | #define _LIBALLOC_H 3 | 4 | /** \defgroup ALLOCHOOKS liballoc hooks 5 | * 6 | * These are the OS specific functions which need to 7 | * be implemented on any platform that the library 8 | * is expected to work on. 9 | */ 10 | 11 | /** @{ */ 12 | 13 | #include 14 | 15 | // If we are told to not define our own size_t, then we skip the define. 16 | //#define _HAVE_UINTPTR_T 17 | //typedef unsigned long uintptr_t; 18 | 19 | //This lets you prefix malloc and friends 20 | #define PREFIX(func) func 21 | 22 | #ifdef __cplusplus 23 | extern "C" { 24 | #endif 25 | 26 | 27 | 28 | /** This function is supposed to lock the memory data structures. It 29 | * could be as simple as disabling interrupts or acquiring a spinlock. 30 | * It's up to you to decide. 31 | * 32 | * \return 0 if the lock was acquired successfully. Anything else is 33 | * failure. 34 | */ 35 | extern int liballoc_lock(); 36 | 37 | /** This function unlocks what was previously locked by the liballoc_lock 38 | * function. If it disabled interrupts, it enables interrupts. If it 39 | * had acquiried a spinlock, it releases the spinlock. etc. 40 | * 41 | * \return 0 if the lock was successfully released. 42 | */ 43 | extern int liballoc_unlock(); 44 | 45 | /** This is the hook into the local system which allocates pages. It 46 | * accepts an integer parameter which is the number of pages 47 | * required. The page size was set up in the liballoc_init function. 48 | * 49 | * \return NULL if the pages were not allocated. 50 | * \return A pointer to the allocated memory. 51 | */ 52 | extern void* liballoc_alloc(size_t); 53 | 54 | /** This frees previously allocated memory. The void* parameter passed 55 | * to the function is the exact same value returned from a previous 56 | * liballoc_alloc call. 57 | * 58 | * The integer value is the number of pages to free. 59 | * 60 | * \return 0 if the memory was successfully freed. 61 | */ 62 | extern int liballoc_free(void*,size_t); 63 | 64 | 65 | 66 | 67 | extern void *PREFIX(malloc)(size_t); ///< The standard function. 68 | extern void *PREFIX(realloc)(void *, size_t); ///< The standard function. 69 | extern void *PREFIX(calloc)(size_t, size_t); ///< The standard function. 70 | extern void PREFIX(free)(void *); ///< The standard function. 71 | 72 | 73 | #ifdef __cplusplus 74 | } 75 | #endif 76 | 77 | 78 | /** @} */ 79 | 80 | #endif 81 | 82 | 83 | -------------------------------------------------------------------------------- /kernel/include/ds/hash.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | typedef unsigned long hash_key_t; 13 | 14 | typedef struct hash_ctx_t { 15 | int (*hash_verify_obj)(); 16 | hash_key_t (*hash_func)(); 17 | } hash_ctx_t; 18 | 19 | typedef struct hash_table_t { 20 | hash_ctx_t *h_ctx; 21 | btree_t h_btree; 22 | spinlock_t h_spinlock; 23 | } hash_table_t; 24 | 25 | typedef struct hash_node_t { 26 | struct hash_node_t *hn_prev; 27 | void *hn_data; 28 | struct hash_node_t *hn_next; 29 | } hash_node_t; 30 | 31 | #define hash_assert(h) ({assert((h), "No Hash Table."); }) 32 | #define hash_lock(h) ({hash_assert(h); spin_lock(&(h)->h_spinlock); }) 33 | #define hash_unlock(h) ({hash_assert(h); spin_unlock(&(h)->h_spinlock); }) 34 | #define hash_islocked(h) ({hash_assert(h); spin_islocked(&(h)->h_spinlock); }) 35 | #define hash_assert_locked(h) ({hash_assert(h); spin_assert_locked(&(h)->h_spinlock); }) 36 | 37 | 38 | #define hash_ctx(h) ({hash_assert_locked(h); ((h)->h_ctx); }) 39 | #define hash_btree(h) ({hash_assert_locked(h); (&(h)->h_btree); }) 40 | #define hash_btree_lock(h) ({btree_lock(hash_btree(h)); }) 41 | #define hash_btree_unlock(h) ({btree_unlock(hash_btree(h)); }) 42 | #define hash_btree_islocked(h) ({btree_islocked(hash_btree(h)); }) 43 | #define hash_btree_assert_locked(h) ({btree_assert_locked(hash_btree(h)); }) 44 | 45 | #define HASH_INIT(ctx) ((hash_table_t){ \ 46 | .h_ctx = (ctx), \ 47 | .h_btree = {0}, \ 48 | .h_spinlock = SPINLOCK_INIT(), \ 49 | }) 50 | 51 | #define HASH_NEW(ctx) (HASH_INIT(ctx)) 52 | 53 | extern int hash_free(hash_table_t *ht); 54 | extern void hash_destroy(hash_table_t *ht); 55 | extern void hash_init(hash_table_t *ht, hash_ctx_t *ctx); 56 | extern int hash_traverse(hash_table_t *ht, queue_t *queue); 57 | extern int hash_alloc(hash_ctx_t *ctx, hash_table_t **phtp); 58 | extern int hash_insert(hash_table_t *ht, void *key, void *data); 59 | extern int hash_delete(hash_table_t *ht, void *key, int isstring); 60 | extern int hash_traverse_btree_node(btree_node_t *tree, queue_t *queue); 61 | extern int hash_search(hash_table_t *ht, void *key, int isstring, void **pdp); -------------------------------------------------------------------------------- /kernel/sys/signals/sigaction.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | int sigaction(int signo, const sigaction_t *restrict act, sigaction_t *restrict oact) { 11 | int err = -EINVAL; 12 | sig_desc_t *sigdesc = NULL; 13 | 14 | if (SIGBAD(signo)) 15 | return -EINVAL; 16 | 17 | current_lock(); 18 | sigdesc = current->t_sigdesc; 19 | current_unlock(); 20 | 21 | sigdesc_lock(sigdesc); 22 | 23 | if (oact) 24 | *oact = sigdesc->sig_action[signo - 1]; 25 | 26 | if (act == NULL) { 27 | sigdesc_unlock(sigdesc); 28 | return 0; 29 | } 30 | 31 | if ((signo == SIGSTOP) || (signo == SIGKILL)) 32 | goto error; 33 | 34 | if (!act->sa_handler && !act->sa_sigaction) 35 | goto error; 36 | 37 | switch ((uintptr_t)act->sa_handler) { 38 | case SIG_IGNORE: 39 | break; 40 | case SIG_ABRT: 41 | __fallthrough; 42 | case SIG_TERM: 43 | __fallthrough; 44 | case SIG_TERM_CORE: 45 | __fallthrough; 46 | case SIG_STOP: 47 | __fallthrough; 48 | case SIG_CONT: 49 | err = -EINVAL; 50 | goto error; 51 | } 52 | 53 | switch ((uintptr_t)act->sa_sigaction) { 54 | case SIG_IGNORE: 55 | break; 56 | case SIG_ABRT: 57 | __fallthrough; 58 | case SIG_TERM: 59 | __fallthrough; 60 | case SIG_TERM_CORE: 61 | __fallthrough; 62 | case SIG_STOP: 63 | __fallthrough; 64 | case SIG_CONT: 65 | err = -EINVAL; 66 | goto error; 67 | } 68 | 69 | if ((act->sa_flags & SA_SIGINFO) && (act->sa_sigaction == NULL)) 70 | goto error; 71 | 72 | sigdesc->sig_action[signo - 1] = *act; 73 | sigdesc_unlock(sigdesc); 74 | return 0; 75 | error: 76 | sigdesc_unlock(sigdesc); 77 | return err; 78 | } 79 | 80 | sigfunc_t signal(int signo, sigfunc_t func) { 81 | sigaction_t act, oact; 82 | act.sa_handler = func; 83 | sigemptyset(&act.sa_mask); 84 | act.sa_flags = 0; 85 | if (signo == SIGALRM) { 86 | #ifdef SA_INTERRUPT 87 | act.sa_flags |= SA_INTERRUPT; 88 | #endif 89 | } 90 | else 91 | { 92 | act.sa_flags |= SA_RESTART; 93 | } 94 | if (sigaction(signo, &act, &oact) < 0) 95 | return (SIG_ERR); 96 | return (oact.sa_handler); 97 | } -------------------------------------------------------------------------------- /kernel/core/swap.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | int copy_to_user(void *udst, void *ksrc, size_t size) { 9 | if (udst == NULL || ksrc == NULL) 10 | return -EFAULT; 11 | if (size == 0) 12 | return -ERANGE; 13 | 14 | if (memcpy(udst, ksrc, size) != udst) 15 | return -EINVAL; 16 | return 0; 17 | } 18 | 19 | int copy_from_user(void *kdst, void * usrc, size_t size) { 20 | if (kdst == NULL || usrc == NULL) 21 | return -EFAULT; 22 | 23 | if (size == 0) 24 | return -ERANGE; 25 | 26 | if (memcpy(kdst, usrc, size) != kdst) 27 | return -EINVAL; 28 | 29 | return 0; 30 | } 31 | 32 | void swapi64(i64 *a0, i64 *a1) { 33 | i64 tmp = 0; 34 | assert(a0 && a1, "Invalid arguments"); 35 | 36 | tmp = *a1; 37 | *a1 = *a0; 38 | *a0 = tmp; 39 | } 40 | 41 | void swapi32(i32 *a0, i32 *a1) { 42 | i32 tmp = 0; 43 | assert(a0 && a1, "Invalid arguments"); 44 | 45 | tmp = *a1; 46 | *a1 = *a0; 47 | *a0 = tmp; 48 | } 49 | 50 | void swapi16(i16 *a0, i16 *a1) { 51 | i16 tmp = 0; 52 | assert(a0 && a1, "Invalid arguments"); 53 | 54 | tmp = *a1; 55 | *a1 = *a0; 56 | *a0 = tmp; 57 | } 58 | 59 | void swapi8(i8 *a0, i8 *a1) { 60 | i8 tmp = 0; 61 | assert(a0 && a1, "Invalid arguments"); 62 | 63 | tmp = *a1; 64 | *a1 = *a0; 65 | *a0 = tmp; 66 | } 67 | 68 | void swapu64(u64 *a0, u64 *a1) { 69 | u64 tmp = 0; 70 | assert(a0 && a1, "Invalid arguments"); 71 | 72 | tmp = *a1; 73 | *a1 = *a0; 74 | *a0 = tmp; 75 | } 76 | 77 | void swapu32(u32 *a0, u32 *a1) { 78 | u32 tmp = 0; 79 | assert(a0 && a1, "Invalid arguments"); 80 | 81 | tmp = *a1; 82 | *a1 = *a0; 83 | *a0 = tmp; 84 | } 85 | 86 | void swapu16(u16 *a0, u16 *a1) { 87 | u16 tmp = 0; 88 | assert(a0 && a1, "Invalid arguments"); 89 | 90 | tmp = *a1; 91 | *a1 = *a0; 92 | *a0 = tmp; 93 | } 94 | 95 | void swapu8(u8 *a0, u8 *a1) { 96 | u8 tmp = 0; 97 | assert(a0 && a1, "Invalid arguments"); 98 | 99 | tmp = *a1; 100 | *a1 = *a0; 101 | *a0 = tmp; 102 | } 103 | 104 | void swapptr(void **p0, void **p1) { 105 | void *tmp = NULL; 106 | assert(p0 && p1, "Invalid arguments"); 107 | 108 | tmp = *p1; 109 | *p1 = *p0; 110 | *p0 = tmp; 111 | } -------------------------------------------------------------------------------- /kernel/include/mm/kalloc.h: -------------------------------------------------------------------------------- 1 | #ifndef _LIBALLOC_H 2 | #define _LIBALLOC_H 3 | 4 | #define KALLOC_H 5 | 6 | #include 7 | #include 8 | 9 | /** \defgroup ALLOCHOOKS liballoc hooks 10 | * 11 | * These are the OS specific functions which need to 12 | * be implemented on any platform that the library 13 | * is expected to work on. 14 | */ 15 | 16 | /** @{ */ 17 | 18 | 19 | 20 | // If we are told to not define our own size_t, then we skip the define. 21 | //#define _HAVE_UINTPTR_T 22 | //typedef unsigned long uintptr_t; 23 | 24 | //This lets you prefix malloc and friends 25 | #define PREFIX(func) k ## func 26 | 27 | #ifdef __cplusplus 28 | extern "C" { 29 | #endif 30 | 31 | 32 | 33 | /** This function is supposed to lock the memory data structures. It 34 | * could be as simple as disabling interrupts or acquiring a spinlock. 35 | * It's up to you to decide. 36 | * 37 | * \return 0 if the lock was acquired successfully. Anything else is 38 | * failure. 39 | */ 40 | extern int liballoc_lock(); 41 | 42 | /** This function unlocks what was previously locked by the liballoc_lock 43 | * function. If it disabled interrupts, it enables interrupts. If it 44 | * had acquiried a spinlock, it releases the spinlock. etc. 45 | * 46 | * \return 0 if the lock was successfully released. 47 | */ 48 | extern int liballoc_unlock(); 49 | 50 | /** This is the hook into the local system which allocates pages. It 51 | * accepts an integer parameter which is the number of pages 52 | * required. The page size was set up in the liballoc_init function. 53 | * 54 | * \return NULL if the pages were not allocated. 55 | * \return A pointer to the allocated memory. 56 | */ 57 | extern void* liballoc_alloc(size_t); 58 | 59 | /** This frees previously allocated memory. The void* parameter passed 60 | * to the function is the exact same value returned from a previous 61 | * liballoc_alloc call. 62 | * 63 | * The integer value is the number of pages to free. 64 | * 65 | * \return 0 if the memory was successfully freed. 66 | */ 67 | extern int liballoc_free(void*,size_t); 68 | 69 | 70 | 71 | 72 | extern void *PREFIX(malloc)(size_t); ///< The standard function. 73 | extern void *PREFIX(realloc)(void *, size_t); ///< The standard function. 74 | extern void *PREFIX(calloc)(size_t n, size_t sz); ///< The standard function. 75 | extern void PREFIX(free)(void *); ///< The standard function. 76 | 77 | 78 | #ifdef __cplusplus 79 | } 80 | #endif 81 | 82 | 83 | /** @} */ 84 | 85 | #endif 86 | 87 | 88 | -------------------------------------------------------------------------------- /usr/lib/stdio/scanf.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | extern char * _argv_0; 7 | 8 | int vsscanf(const char *str, const char *format, va_list ap) { 9 | int count = 0; 10 | while (*format) { 11 | if (*format == ' ') { 12 | /* handle white space */ 13 | while (*str && isspace(*str)) { 14 | str++; 15 | } 16 | } else if (*format == '%') { 17 | /* Parse */ 18 | format++; 19 | __unused int _long = 0; 20 | 21 | if (*format == 'l') { 22 | format++; 23 | if (*format == 'l') { 24 | _long = 1; 25 | format++; 26 | } 27 | } 28 | 29 | if (*format == 'd') { 30 | int i = 0; 31 | int sign = 1; 32 | while (isspace(*str)) str++; 33 | if (*str == '-') { 34 | sign = -1; 35 | str++; 36 | } 37 | while (*str && *str >= '0' && *str <= '9') { 38 | i = i * 10 + *str - '0'; 39 | str++; 40 | } 41 | int * out = (int *)va_arg(ap, int*); 42 | count++; 43 | *out = i * sign; 44 | } else if (*format == 'u') { 45 | unsigned int i = 0; 46 | while (isspace(*str)) str++; 47 | while (*str && *str >= '0' && *str <= '9') { 48 | i = i * 10 + *str - '0'; 49 | str++; 50 | } 51 | unsigned int * out = (unsigned int *)va_arg(ap, unsigned int*); 52 | count++; 53 | *out = i; 54 | } 55 | } else { 56 | /* Expect exact character? */ 57 | if (*str == *format) { 58 | str++; 59 | } else { 60 | break; 61 | } 62 | } 63 | format++; 64 | } 65 | return count; 66 | } 67 | 68 | int vfscanf(FILE * stream __unused, const char *format, va_list ap __unused) { 69 | while (*format) { 70 | if (*format == ' ') { 71 | /* Handle whitespace */ 72 | } else if (*format == '%') { 73 | /* Parse */ 74 | } else { 75 | /* Expect exact character? */ 76 | } 77 | format++; 78 | } 79 | return 0; 80 | } 81 | 82 | int sscanf(const char *str, const char *format, ...) { 83 | va_list args; 84 | va_start(args, format); 85 | int out = vsscanf(str, format, args); 86 | va_end(args); 87 | return out; 88 | } 89 | 90 | int fscanf(FILE *stream, const char *format, ...) { 91 | va_list args; 92 | va_start(args, format); 93 | int out = vfscanf(stream, format, args); 94 | va_end(args); 95 | return out; 96 | } 97 | 98 | int scanf(const char *format, ...) { 99 | va_list args; 100 | va_start(args, format); 101 | int out = vfscanf(stdin, format, args); 102 | va_end(args); 103 | return out; 104 | } 105 | -------------------------------------------------------------------------------- /kernel/sync/cond.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | int cond_new(cond_t **ref) { 10 | return cond_init(NULL, ref); 11 | } 12 | 13 | void cond_free(cond_t *c) { 14 | queue_lock(&c->waiters); 15 | queue_flush(&c->waiters); 16 | kfree(c); 17 | } 18 | 19 | int cond_init(cond_t *c, cond_t **ref) { 20 | int err = 0; 21 | int alloc = !c; 22 | 23 | if ((!c && !ref)) 24 | return -EINVAL; 25 | 26 | if (alloc) { 27 | if (!(c = (cond_t *)kmalloc(sizeof *c))) { 28 | err = -ENOMEM; 29 | goto error; 30 | } 31 | } 32 | 33 | *c = (cond_t){0}; 34 | 35 | c->waiters = QUEUE_INIT(); 36 | c->guard = SPINLOCK_INIT(); 37 | 38 | if (ref) 39 | *ref = c; 40 | return 0; 41 | error: 42 | if (c && alloc) 43 | kfree(c); 44 | printk("cond_init(): called @ 0x%p, error=%d\n", __retaddr(0), err); 45 | return err; 46 | } 47 | 48 | int cond_wait(cond_t *cond) { 49 | int retval = 0; 50 | 51 | assert(cond, "no condition-variable"); 52 | current_assert(); 53 | 54 | spin_lock(&cond->guard); 55 | if ((int)atomic_inc(&cond->count) >= 0) { 56 | current_lock(); 57 | retval = sched_sleep(&cond->waiters, T_ISLEEP, &cond->guard); 58 | current_unlock(); 59 | } 60 | spin_unlock(&cond->guard); 61 | return retval; 62 | } 63 | 64 | int cond_wait_releasing(cond_t *cond, spinlock_t *lk) { 65 | int retval = 0; 66 | 67 | if (lk) 68 | spin_unlock(lk); 69 | retval = cond_wait(cond); 70 | if (lk) 71 | spin_lock(lk); 72 | return retval; 73 | } 74 | 75 | static void cond_wake1(cond_t *cond) { 76 | sched_wake1(&cond->waiters); 77 | } 78 | 79 | void cond_signal(cond_t *cond) { 80 | assert(cond, "no condition-variable"); 81 | spin_lock(&cond->guard); 82 | cond_wake1(cond); 83 | atomic_dec(&cond->count); 84 | spin_unlock(&cond->guard); 85 | } 86 | 87 | static void cond_wakeall(cond_t *cond) { 88 | int waiters = sched_wakeall(&cond->waiters); 89 | if (waiters == 0) 90 | atomic_write(&cond->count, -1); 91 | else 92 | atomic_write(&cond->count, 0); 93 | } 94 | 95 | void cond_broadcast(cond_t *cond) { 96 | assert(cond, "no condition-variable"); 97 | spin_lock(&cond->guard); 98 | cond_wakeall(cond); 99 | spin_unlock(&cond->guard); 100 | } -------------------------------------------------------------------------------- /kernel/include/arch/thread.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #define ARCH_EXEC_ONSTACK BS(0) 10 | 11 | /** 12 | * Arch-specific thread structure. 13 | * This is what the architecture understands a thread to be. 14 | * i.e, thread_t is understood by the multitasking concept in ginger 15 | * but arch_thread_t is what it really is underneath. 16 | * 17 | * NOTE: t_contextand t_ucontext; 18 | * t_context: is what is used by the system to switch contexts 19 | * by calling swtch() implicitly through sched() or in schedule(). 20 | * see sys/sched/sched.c 21 | * t_ucontext: is the execution context at the time of 22 | * interrupts, exceptions, and system calls. 23 | */ 24 | typedef struct __arch_thread_t { 25 | thread_t *t_thread; // pointer to thread control block. 26 | context_t *t_ctx; // caller-callee context. 27 | ucontext_t *t_uctx; // execution context status. 28 | void *t_rsvd; // reserved space on kstack, incase of interrupt chaining. 29 | flags64_t t_flags; // flags. 30 | uc_stack_t t_sstack; // scratch stack for when executing for the first time. 31 | uc_stack_t t_kstack; // kernel stack description. 32 | uc_stack_t t_ustack; // user stack description. 33 | uc_stack_t t_altstack; // if SA_ONSTACK is set for a signal handler, use this stack. 34 | } arch_thread_t; 35 | 36 | /** 37 | * \brief exit execution of thread. 38 | * \param exit_code exit code from thread. 39 | */ 40 | void arch_thread_exit(uintptr_t exit_code); 41 | 42 | /** 43 | * \brief Initialize architecture-specific thread data. 44 | * \param thread arch-specific thread struct. \todo change to (void *) 45 | * \param entry thread entry point. 46 | * \param arg argument to be passed to the thread. 47 | * \return 0 if successful and errno on failure. 48 | */ 49 | int arch_kthread_init(arch_thread_t *thread, thread_entry_t entry, void *arg); 50 | int arch_uthread_init(arch_thread_t *thread, thread_entry_t entry, void *arg); 51 | int x86_64_signal_dispatch( arch_thread_t *thread, thread_entry_t entry, 52 | siginfo_t *info, sigaction_t *sigact); 53 | 54 | void arch_exec_free_copy(char ***arg_env); 55 | char ***arch_execve_copy(char *_argp[], char *_envp[]); 56 | int arch_thread_execve(arch_thread_t *thread, thread_entry_t entry, 57 | int argc, const char *argp[], const char *envp[]); 58 | 59 | int arch_thread_setkstack(arch_thread_t *arch); 60 | int arch_thread_fork(arch_thread_t *dst, arch_thread_t *src); -------------------------------------------------------------------------------- /usr/include/ginger/spinlock.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | typedef struct { 8 | uint8_t guard; 9 | uint8_t locked; 10 | tid_t thread; 11 | } spinlock_t; 12 | 13 | #define SPINLOCK_INIT() ((spinlock_t){ \ 14 | .guard = 0, \ 15 | .locked = 0, \ 16 | .thread = 0, \ 17 | }) 18 | 19 | #define SPINLOCK_NEW() ((spinlock_t *){&SPINLOCK_INIT()}) 20 | 21 | #define spin_islocked(lk) ({ \ 22 | while (atomic_test_and_set(&(lk)->guard)) \ 23 | asm __volatile__("pause"); \ 24 | int locked = ((lk)->locked && \ 25 | ((lk)->thread == sys_thread_self())) \ 26 | ? 1 \ 27 | : 0; \ 28 | atomic_clear(&(lk)->guard); \ 29 | locked; \ 30 | }) 31 | 32 | #define spin_assert_locked(lk) ({ \ 33 | assert(spin_islocked(lk), "lock is not held"); \ 34 | }) 35 | 36 | #define spin_lock(lk) ({ \ 37 | for (;;) { \ 38 | while (atomic_test_and_set(&(lk)->guard)) \ 39 | asm __volatile__("pause"); \ 40 | assert(!(((lk)->locked) && \ 41 | ((lk)->thread == sys_thread_self())), \ 42 | "lock already acquired"); \ 43 | if ((lk)->locked) \ 44 | atomic_clear(&(lk)->guard); \ 45 | else \ 46 | break; \ 47 | } \ 48 | (lk)->locked = 1; \ 49 | (lk)->thread = sys_thread_self(); \ 50 | atomic_clear(&(lk)->guard); \ 51 | }) 52 | 53 | #define spin_unlock(lk) ({ \ 54 | while (atomic_test_and_set(&(lk)->guard)) \ 55 | asm __volatile__("pause"); \ 56 | assert((((lk)->locked) && \ 57 | ((lk)->thread == sys_thread_self())), \ 58 | "lock not acquired"); \ 59 | (lk)->locked = 0; \ 60 | (lk)->thread = 0; \ 61 | atomic_clear(&(lk)->guard); \ 62 | }) 63 | -------------------------------------------------------------------------------- /kernel/arch/firmware/acpi.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | static xsdt_t *XSDT = NULL; 9 | static rsdt_t *RSDT = NULL; 10 | static rsdp20_t *RSDP = NULL; 11 | 12 | int acpi_validate_table(char *addr, size_t size) { 13 | uint8_t sum = 0; 14 | while (size--) 15 | sum += *addr++; 16 | return sum == 0; 17 | } 18 | 19 | void *acpi_findrsdp(void) { 20 | char *bios = (char *)VMA2HI(EBDA); 21 | for (; bios < (char *)(VMA2HI(EBDA) + KiB(1)); bios +=4) 22 | if (!strncmp("RSD PTR ", bios, 8)) 23 | return bios; 24 | 25 | bios = (char *)(VMA2HI(BIOSROM)); 26 | for (; bios < (char *)(VMA2HI(BIOSROM) + 0xfffff); bios +=4) 27 | if (!strncmp("RSD PTR ", bios, 8)) 28 | return bios; 29 | return NULL; 30 | } 31 | 32 | acpiSDT_t *acpi_parse_rsdt(rsdt_t *rsdt, const char *sign) { 33 | int count = 0; 34 | acpiSDT_t *sdt = NULL; 35 | 36 | if (!rsdt || !sign) 37 | return NULL; 38 | 39 | count = (rsdt->hdr.length - sizeof(acpiSDT_t)) / 4; 40 | 41 | for (int i = 0; i < count; ++i) { 42 | sdt = (void *)VMA2HI(rsdt->sdt[i]); 43 | if (!strncmp(sign, sdt->signature, 4)) 44 | return sdt; 45 | } 46 | 47 | return NULL; 48 | } 49 | 50 | acpiSDT_t *acpi_parse_xsdt(xsdt_t *xsdt, const char *sign) { 51 | int count = 0; 52 | acpiSDT_t *sdt = NULL; 53 | 54 | if (!xsdt || !sign) 55 | return NULL; 56 | 57 | count = (xsdt->hdr.length - sizeof (acpiSDT_t)) / 8; 58 | 59 | for (int i = 0; i < count; ++i) { 60 | sdt = (void *)VMA2HI(xsdt->sdt[i]); 61 | if (!strncmp(sign, sdt->signature, 4)) 62 | return sdt; 63 | } 64 | 65 | return NULL; 66 | } 67 | 68 | acpiSDT_t *acpi_enumerate(const char *sign) { 69 | acpiSDT_t *sdt = NULL; 70 | sdt = XSDT ? acpi_parse_xsdt(XSDT, sign) : 71 | RSDT ? acpi_parse_rsdt(RSDT, sign) : NULL; 72 | if (sdt && acpi_validate_table((void *)sdt, sdt->length)) 73 | return sdt; 74 | return NULL; 75 | } 76 | 77 | int acpi_init(void) { 78 | size_t size = 0; 79 | 80 | if (!(RSDP = acpi_findrsdp())) 81 | return -ENOENT; 82 | 83 | size = RSDP->rsdp.revno < 2 ? sizeof(rsdp_t) : RSDP->length; 84 | 85 | if (!(acpi_validate_table((void *)RSDP, size))) 86 | return -EINVAL; 87 | 88 | if (RSDP->rsdp.revno < 2) 89 | RSDT = (rsdt_t *)VMA2HI(RSDP->rsdp.rsdtaddr); 90 | else 91 | XSDT = (xsdt_t *)VMA2HI(RSDP->xsdtaddr); 92 | return 0; 93 | } -------------------------------------------------------------------------------- /kernel/arch/chipset/pic.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | // I/O Addresses of the two programmable interrupt controllers 7 | #define IO_PIC1 0x20 // Master (IRQs 0-7) 8 | #define IO_PIC2 0xA0 // Slave (IRQs 8-15) 9 | 10 | #define IRQ_SLAVE 2 // IRQ at which slave connects to master 11 | 12 | // Current IRQ mask. 13 | // Initial IRQ mask has interrupt 2 enabled (for slave 8259A). 14 | static uint16_t irqmask = 0xFFFF & ~(1 << IRQ_SLAVE); 15 | 16 | static void 17 | pic_setmask(uint16_t mask) { 18 | irqmask = mask; 19 | outb(IO_PIC1 + 1, mask); 20 | outb(IO_PIC2 + 1, mask >> 8); 21 | } 22 | 23 | void pic_enable(int irq) { 24 | pic_setmask(irqmask & ~(1 << irq)); 25 | } 26 | 27 | // Initialize the 8259A interrupt controllers. 28 | void pic_init(void) { 29 | // mask all interrupts 30 | outb(IO_PIC1 + 1, 0xFF); 31 | outb(IO_PIC2 + 1, 0xFF); 32 | 33 | // Set up master (8259A-1) 34 | 35 | // ICW1: 0001g0hi 36 | // g: 0 = edge triggering, 1 = level triggering 37 | // h: 0 = cascaded PICs, 1 = master only 38 | // i: 0 = no ICW4, 1 = ICW4 required 39 | outb(IO_PIC1, 0x11); 40 | 41 | // ICW2: Vector offset 42 | outb(IO_PIC1 + 1, IRQ_OFFSET); 43 | 44 | // ICW3: (master PIC) bit mask of IR lines connected to slaves 45 | // (slave PIC) 3-bit # of slave's connection to master 46 | outb(IO_PIC1 + 1, 1 << IRQ_SLAVE); 47 | 48 | // ICW4: 000nbmap 49 | // n: 1 = special fully nested mode 50 | // b: 1 = buffered mode 51 | // m: 0 = slave PIC, 1 = master PIC 52 | // (ignored when b is 0, as the master/slave role 53 | // can be hardwired). 54 | // a: 1 = Automatic EOI mode 55 | // p: 0 = MCS-80/85 mode, 1 = intel x86 mode 56 | outb(IO_PIC1 + 1, 0x3); 57 | 58 | // Set up slave (8259A-2) 59 | outb(IO_PIC2, 0x11); // ICW1 60 | outb(IO_PIC2 + 1, IRQ_OFFSET + 8); // ICW2 61 | outb(IO_PIC2 + 1, IRQ_SLAVE); // ICW3 62 | // NB Automatic EOI mode doesn't tend to work on the slave. 63 | // Linux source code says it's "to be investigated". 64 | outb(IO_PIC2 + 1, 0x3); // ICW4 65 | 66 | // OCW3: 0ef01prs 67 | // ef: 0x = NOP, 10 = clear specific mask, 11 = set specific mask 68 | // p: 0 = no polling, 1 = polling mode 69 | // rs: 0x = NOP, 10 = read IRR, 11 = read ISR 70 | outb(IO_PIC1, 0x68); // clear specific mask 71 | outb(IO_PIC1, 0x0a); // read IRR by default 72 | 73 | outb(IO_PIC2, 0x68); // OCW3 74 | outb(IO_PIC2, 0x0a); // OCW3 75 | 76 | if (irqmask != 0xFFFF) 77 | pic_setmask(irqmask); 78 | } 79 | -------------------------------------------------------------------------------- /usr/include/bits/stat.h: -------------------------------------------------------------------------------- 1 | #ifndef _STAT_H 2 | #define _STAT_H 3 | #include 4 | #include 5 | #include 6 | 7 | 8 | struct stat { 9 | devid_t st_dev; 10 | ino_t st_ino; 11 | mode_t st_mode; 12 | unsigned long st_nlink; 13 | uid_t st_uid; 14 | gid_t st_gid; 15 | devid_t st_rdev; 16 | size_t st_size; 17 | time_t st_atime; 18 | time_t st_mtime; 19 | time_t st_ctime; 20 | }; 21 | 22 | #define _IFMT 0170000 /* type of file */ 23 | #define _IFDIR 0040000 /* directory */ 24 | #define _IFCHR 0020000 /* character special */ 25 | #define _IFBLK 0060000 /* block special */ 26 | #define _IFREG 0100000 /* regular */ 27 | #define _IFLNK 0120000 /* symbolic link */ 28 | #define _IFSOCK 0140000 /* socket */ 29 | #define _IFIFO 0010000 /* fifo */ 30 | 31 | #define S_BLKSIZE 1024 /* size of a block */ 32 | 33 | #define S_ISUID 0004000 /* set user id on execution */ 34 | #define S_ISGID 0002000 /* set group id on execution */ 35 | #define S_ISVTX 0001000 /* save swapped text even after use */ 36 | #define S_IREAD 0000400 /* read permission, owner */ 37 | #define S_IWRITE 0000200 /* write permission, owner */ 38 | #define S_IEXEC 0000100 /* execute/search permission, owner */ 39 | #define S_ENFMT 0002000 /* enforcement-mode locking */ 40 | 41 | #define S_IFMT _IFMT 42 | #define S_IFDIR _IFDIR 43 | #define S_IFCHR _IFCHR 44 | #define S_IFBLK _IFBLK 45 | #define S_IFREG _IFREG 46 | #define S_IFLNK _IFLNK 47 | #define S_IFSOCK _IFSOCK 48 | #define S_IFIFO _IFIFO 49 | 50 | #define S_IRWXU (S_IRUSR | S_IWUSR | S_IXUSR) 51 | #define S_IRUSR 0000400 /* read permission, owner */ 52 | #define S_IWUSR 0000200 /* write permission, owner */ 53 | #define S_IXUSR 0000100/* execute/search permission, owner */ 54 | #define S_IRWXG (S_IRGRP | S_IWGRP | S_IXGRP) 55 | #define S_IRGRP 0000040 /* read permission, group */ 56 | #define S_IWGRP 0000020 /* write permission, grougroup */ 57 | #define S_IXGRP 0000010/* execute/search permission, group */ 58 | #define S_IRWXO (S_IROTH | S_IWOTH | S_IXOTH) 59 | #define S_IROTH 0000004 /* read permission, other */ 60 | #define S_IWOTH 0000002 /* write permission, other */ 61 | #define S_IXOTH 0000001/* execute/search permission, other */ 62 | 63 | int fstat(int fd, struct stat *buf); 64 | int stat(const char *restrict path, struct stat *restrict buf); 65 | int lstat(const char *restrict path, struct stat *restrict buf); 66 | int fstatat(int fd, const char *restrict path, struct stat *restrict buf, int flag); 67 | 68 | #endif /* _STAT_H */ -------------------------------------------------------------------------------- /kernel/include/arch/x86_64/system.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | // halt the current processor core. 8 | static inline void hlt(void) { 9 | #if defined __i386__ || __x86_64__ 10 | asm __volatile__ ("hlt"); 11 | #endif 12 | } 13 | 14 | // clear interrupts on the current processor core. 15 | static inline void cli(void) { 16 | #if defined __i386__ || __x86_64__ 17 | asm __volatile__ ("cli"); 18 | #endif 19 | } 20 | 21 | // start interrupts on the current processor core. 22 | static inline void sti(void) { 23 | #if defined __i386__ || __x86_64__ 24 | asm __volatile__ ("sti"); 25 | #endif 26 | } 27 | 28 | // momentarily pause the current processor core. 29 | static inline void cpu_pause(void) { 30 | #if defined __i386__ || __x86_64__ 31 | asm __volatile__("pause"); 32 | #endif 33 | } 34 | 35 | extern void disable_caching(void); 36 | 37 | static inline uintptr_t rdrax(void) { 38 | uintptr_t ret; 39 | asm volatile("":"=a"(ret)); 40 | return ret; 41 | } 42 | 43 | //uintptr_t rdrax(void); 44 | extern void wrcr0(u64); 45 | extern u64 rdcr0(void); 46 | extern u64 rdcr4(void); 47 | extern void wrcr4(u64); 48 | extern uintptr_t rdcr2(void); 49 | extern uintptr_t rdcr3(void); 50 | extern uintptr_t rdrsp(void); 51 | extern uintptr_t rdrbp(void); 52 | extern void cr0set(u64); 53 | extern void cr4set(u64); 54 | extern void wrcr2(uintptr_t); 55 | extern void wrcr3(uintptr_t); 56 | extern void cr0mask(u64); 57 | extern void cr4mask(u64); 58 | extern uintptr_t rdrflags(void); 59 | extern void wrrflags(uintptr_t); 60 | extern u64 cr0test(u64 bits); 61 | extern u64 cr4test(u64 bits); 62 | 63 | static inline void cpuid(u64 leaf, u64 subleaf, u32 *eax, 64 | u32 *ebx, u32 *ecx, u32 *edx) { 65 | __get_cpuid_count(leaf, subleaf, eax, ebx, ecx, edx); 66 | } 67 | 68 | extern u64 rdxcr(u32 i); 69 | extern void wrxcr(u32 i, u64 value); 70 | extern void xsave(void *region); 71 | extern void xrstor(void *region); 72 | extern void fxsave(void *region); 73 | extern void fxrstor(void *region); 74 | 75 | extern void fninit(void); 76 | extern void invlpg(uintptr_t); 77 | 78 | #define is_intena() ({ (rdrflags() & 0x200); }) 79 | 80 | static inline u8 inb(u16 port) { 81 | u8 data; 82 | #if defined __i386__ || __x86_64__ 83 | __asm__ __volatile__("inb %1, %0" 84 | : "=a"(data) 85 | : "dN"(port)); 86 | #endif 87 | return data; 88 | } 89 | 90 | static inline void outb(u16 port, u8 data) { 91 | #if defined __i386__ || __x86_64__ 92 | __asm__ __volatile__("outb %1, %0" 93 | : 94 | : "dN"(port), "a"(data)); 95 | #endif 96 | } -------------------------------------------------------------------------------- /kernel/core/clock.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | static QUEUE(clk_queue); 11 | static atomic_t nclks = 0; 12 | static atomic_t clkid = 0; 13 | 14 | void clock_trigger(void) { 15 | timeval_t tv; 16 | JIFFIES_TO_TIMEVAL(1, &tv); 17 | 18 | queue_lock(clk_queue); 19 | queue_foreach(clk_t *, clk, clk_queue) { 20 | clk_lock(clk); 21 | if (clk->clk_flags & CLK_ARMED) { 22 | clk->clk_tv = TIMEVAL_SUB(clk->clk_tv, tv); 23 | if (clk->clk_tv.tv_sec < 0) { 24 | if (clk->clk_flags & CLK_RESET) 25 | clk->clk_tv = clk->clk_default_tv; 26 | else{ 27 | clk->clk_flags &= ~CLK_ARMED; 28 | clk->clk_tv = (timeval_t) {0}; 29 | } 30 | clk->clk_entry(clk->clk_arg); 31 | } else if (TIMEVAL_EQ(&clk->clk_tv, &((timeval_t){0}))) { 32 | if (clk->clk_flags & CLK_RESET) 33 | clk->clk_tv = clk->clk_default_tv; 34 | else{ 35 | clk->clk_flags &= ~CLK_ARMED; 36 | clk->clk_tv = (timeval_t) {0}; 37 | } 38 | clk->clk_entry(clk->clk_arg); 39 | } 40 | } 41 | clk_unlock(clk); 42 | } 43 | queue_unlock(clk_queue); 44 | } 45 | 46 | int clock_set(timeval_t *ts, void (*entry)(), void *arg, int flags, clockid_t *ref) { 47 | int err = 0; 48 | clockid_t id = 0; 49 | clk_t *clk= NULL; 50 | 51 | if (atomic_read(&nclks) >= NCLK) 52 | return -EAGAIN; 53 | 54 | if ((ts == NULL) || ((ts->tv_usec == 0) && (ts->tv_sec == 0))) 55 | return -EINVAL; 56 | 57 | if (entry == NULL) 58 | return -EFAULT; 59 | 60 | if (ref == NULL) 61 | return -EINVAL; 62 | 63 | if (NULL == (clk = kcalloc(1, sizeof *clk))) 64 | return -ENOMEM; 65 | 66 | clk->clk_tv = *ts; 67 | clk->clk_default_tv = *ts; 68 | clk->clk_arg = arg; 69 | clk->clk_entry = entry; 70 | clk->clk_flags = flags | CLK_ARMED; 71 | clk->clk_spinlock = SPINLOCK_INIT(); 72 | clk->clk_id = id = (clockid_t) atomic_inc(&clkid); 73 | 74 | queue_lock(clk_queue); 75 | err = enqueue(clk_queue, (void *)clk, 1, NULL); 76 | queue_unlock(clk_queue); 77 | 78 | if (err) goto error; 79 | 80 | *ref = id; 81 | return 0; 82 | error: 83 | kfree(clk); 84 | printk("%s:%d: failed to set clock, error: %d\n", __FILE__, __LINE__, err); 85 | return err; 86 | } -------------------------------------------------------------------------------- /kernel/kernel.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | int load_init(const char *conf_fn); 11 | 12 | static char *init_path = "/ramfs/init"; 13 | 14 | __noreturn void kthread_main(void) { 15 | int err = 0; 16 | 17 | printk("\n\t\t\tWelcome to \'" 18 | "\e[025453;011mGinger OS\e[0m\'.\n\n" 19 | ); 20 | 21 | builtin_threads_begin(NULL); 22 | 23 | if ((err = load_init("/ramfs/startup.conf"))) { 24 | printk("Failed to read or parse startup.conf" 25 | "\nexit_code: %d\n", err 26 | ); 27 | } 28 | 29 | loop() { 30 | thread_join(0, NULL, NULL); 31 | thread_yield(); 32 | } 33 | } 34 | 35 | static int conf_find(const char *buf, const char *str, char **ret) { 36 | char *at = NULL; 37 | char *cpybuf = NULL; 38 | 39 | if (buf == NULL || str == NULL || ret == NULL) 40 | return -EINVAL; 41 | 42 | if (NULL == (cpybuf = strdup(buf))) 43 | return -ENOMEM; 44 | 45 | for (at = strtok(cpybuf, "\n\t"); (at = strtok(NULL, "\n\t")); ) { 46 | printk("value: %s\n", at); 47 | } 48 | 49 | return 0; 50 | } 51 | 52 | int load_init(const char *conf_fn) { 53 | int err = 0; 54 | int conf_fd = 0; 55 | size_t conf_size = 0; 56 | char *conf_buf = NULL; 57 | char *init_desc= NULL; 58 | 59 | if (conf_fn == NULL) 60 | return -EINVAL; 61 | 62 | if ((err = open(conf_fn, O_RDONLY, 0)) < 0) { 63 | printk("Failed to open startup configuration file," 64 | "failed with err_code: %d\n", err); 65 | goto error; 66 | } 67 | 68 | conf_size = lseek(conf_fd, 0, SEEK_END) + 1; 69 | lseek(conf_fd, 0, SEEK_SET); 70 | 71 | if (NULL == (conf_buf = kcalloc(1, conf_size))) { 72 | printk("failed to allocate buf for configuration file\n" 73 | "Not enough memory to satisfy request!\n"); 74 | goto error; 75 | } 76 | 77 | if ((ssize_t)(err = read(conf_fd, conf_buf, conf_size)) != (ssize_t)conf_size) { 78 | printk("Failed to read startup configuration file\n" 79 | "read() returned: %d\n", err); 80 | } 81 | 82 | printk("Parsing startup configuration file...\n"); 83 | conf_find(conf_buf, "![init]", &init_desc); 84 | 85 | printk("[exec] %s...\n", init_path); 86 | err = proc_init(init_path); 87 | printk( 88 | "[%s] %s \"%s\", error: %d.\n", 89 | err ? "\e[025453;03mFAIL\e[0m" : "\e[025453;03mOK\e[0m", 90 | err ? "couldn't load" : "started", 91 | init_path, err 92 | ); 93 | 94 | return 0; 95 | error: 96 | return err; 97 | } -------------------------------------------------------------------------------- /kernel/fs/devtmpfs/devtmpfs.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | static filesystem_t *devtmpfs = NULL; 7 | 8 | static iops_t devtmpfs_iops = { 9 | .iopen = tmpfs_iopen, 10 | .ibind = tmpfs_ibind, 11 | .isync = tmpfs_isync, 12 | .ilink = tmpfs_ilink, 13 | .iread = tmpfs_iread, 14 | .iwrite = tmpfs_iwrite, 15 | .iclose = tmpfs_iclose, 16 | .ifcntl = tmpfs_ifcntl, 17 | .iioctl = tmpfs_iioctl, 18 | .imkdir = tmpfs_imkdir, 19 | .imknod = tmpfs_imknod, 20 | .icreate = tmpfs_icreate, 21 | .ilookup = tmpfs_ilookup, 22 | .iunlink = tmpfs_iunlink, 23 | .irename = tmpfs_irename, 24 | .igetattr = tmpfs_igetattr, 25 | .isetattr = tmpfs_isetattr, 26 | .isymlink = tmpfs_isymlink, 27 | .ireaddir = tmpfs_ireaddir, 28 | .itruncate = tmpfs_itruncate, 29 | }; 30 | 31 | static int devtmpfs_fill_sb(filesystem_t *fs __unused, const char *target, 32 | struct devid *devid __unused, superblock_t *sb) { 33 | int err = 0; 34 | inode_t *iroot = NULL; 35 | dentry_t *droot = NULL; 36 | 37 | if ((err = tmpfs_new_inode(FS_DIR, &iroot))) 38 | return err; 39 | 40 | if ((err = dalloc(target, &droot))) { 41 | irelease(iroot); 42 | return err; 43 | } 44 | 45 | if ((err = iadd_alias(iroot, droot))) { 46 | dclose(droot); 47 | irelease(iroot); 48 | return err; 49 | } 50 | 51 | strncpy(sb->sb_magic0, "devtmpfs", 10); 52 | sb->sb_blocksize = -1; 53 | sb->sb_size = -1; 54 | sb->sb_root = droot; 55 | sb->sb_uio = (cred_t){ 56 | .c_gid = 0, 57 | .c_uid = 0, 58 | .c_umask = 0555, 59 | .c_lock = SPINLOCK_INIT(), 60 | }; 61 | 62 | iroot->i_sb = sb; 63 | iroot->i_type = FS_DIR; 64 | iroot->i_ops = sb->sb_iops; 65 | 66 | dunlock(droot); 67 | iunlock(iroot); 68 | return 0; 69 | } 70 | 71 | static int devtmpfs_getsb(filesystem_t *fs, const char *src __unused, const char *target, 72 | unsigned long flags, void *data, superblock_t **psbp) { 73 | return getsb_nodev(fs, target, flags, data, psbp, devtmpfs_fill_sb); 74 | } 75 | 76 | int devtmpfs_init(void) { 77 | int err = 0; 78 | 79 | if ((err = fs_create("devtmpfs", &devtmpfs_iops, &devtmpfs))) 80 | return err; 81 | 82 | devtmpfs->get_sb = devtmpfs_getsb; 83 | devtmpfs->mount = NULL; 84 | 85 | if ((err = vfs_register_fs(devtmpfs))) { 86 | fsunlock(devtmpfs); 87 | goto error; 88 | } 89 | 90 | fsunlock(devtmpfs); 91 | return 0; 92 | error: 93 | if (devtmpfs) 94 | fs_free(devtmpfs); 95 | return err; 96 | } --------------------------------------------------------------------------------