aboutsummaryrefslogtreecommitdiff
path: root/kernel/include
diff options
context:
space:
mode:
authornthnluu <nate1299@me.com>2024-01-28 21:20:27 -0500
committernthnluu <nate1299@me.com>2024-01-28 21:20:27 -0500
commitc63f340d90800895f007de64b7d2d14624263331 (patch)
tree2c0849fa597dd6da831c8707b6f2603403778d7b /kernel/include
Created student weenix repository
Diffstat (limited to 'kernel/include')
-rw-r--r--kernel/include/api/access.h19
-rw-r--r--kernel/include/api/binfmt.h12
-rw-r--r--kernel/include/api/elf.h2595
-rw-r--r--kernel/include/api/exec.h12
-rw-r--r--kernel/include/api/syscall.h196
-rw-r--r--kernel/include/api/utsname.h14
-rw-r--r--kernel/include/boot/config.h12
-rw-r--r--kernel/include/boot/multiboot_macros.h6
-rw-r--r--kernel/include/config.h50
-rw-r--r--kernel/include/ctype.h124
-rw-r--r--kernel/include/drivers/blockdev.h99
-rw-r--r--kernel/include/drivers/chardev.h51
-rw-r--r--kernel/include/drivers/cmos.h40
-rw-r--r--kernel/include/drivers/dev.h49
-rw-r--r--kernel/include/drivers/disk/ahci.h325
-rw-r--r--kernel/include/drivers/disk/sata.h14
-rw-r--r--kernel/include/drivers/keyboard.h43
-rw-r--r--kernel/include/drivers/memdevs.h6
-rw-r--r--kernel/include/drivers/pcie.h112
-rw-r--r--kernel/include/drivers/screen.h72
-rw-r--r--kernel/include/drivers/tty/ldisc.h68
-rw-r--r--kernel/include/drivers/tty/tty.h21
-rw-r--r--kernel/include/drivers/tty/vterminal.h249
-rw-r--r--kernel/include/errno.h151
-rw-r--r--kernel/include/fs/dirent.h25
-rw-r--r--kernel/include/fs/fcntl.h18
-rw-r--r--kernel/include/fs/file.h62
-rw-r--r--kernel/include/fs/lseek.h5
-rw-r--r--kernel/include/fs/open.h5
-rw-r--r--kernel/include/fs/pipe.h10
-rw-r--r--kernel/include/fs/ramfs/ramfs.h5
-rw-r--r--kernel/include/fs/s5fs/s5fs.h145
-rw-r--r--kernel/include/fs/s5fs/s5fs_privtest.h6
-rw-r--r--kernel/include/fs/s5fs/s5fs_subr.h53
-rw-r--r--kernel/include/fs/stat.h44
-rw-r--r--kernel/include/fs/vfs.h162
-rw-r--r--kernel/include/fs/vfs_privtest.h3
-rw-r--r--kernel/include/fs/vfs_syscall.h39
-rw-r--r--kernel/include/fs/vnode.h358
-rw-r--r--kernel/include/fs/vnode_specials.h0
-rw-r--r--kernel/include/globals.h11
-rw-r--r--kernel/include/kernel.h79
-rw-r--r--kernel/include/limits.h18
-rw-r--r--kernel/include/main/acpi.h20
-rw-r--r--kernel/include/main/apic.h73
-rw-r--r--kernel/include/main/cpuid.h118
-rw-r--r--kernel/include/main/entry.h3
-rw-r--r--kernel/include/main/gdt.h21
-rw-r--r--kernel/include/main/inits.h15
-rw-r--r--kernel/include/main/interrupt.h117
-rw-r--r--kernel/include/main/io.h46
-rw-r--r--kernel/include/main/smp.h22
-rw-r--r--kernel/include/mm/kmalloc.h7
-rw-r--r--kernel/include/mm/mm.h8
-rw-r--r--kernel/include/mm/mman.h25
-rw-r--r--kernel/include/mm/mobj.h75
-rw-r--r--kernel/include/mm/page.h124
-rw-r--r--kernel/include/mm/pagecache.h9
-rw-r--r--kernel/include/mm/pagetable.h94
-rw-r--r--kernel/include/mm/pframe.h23
-rw-r--r--kernel/include/mm/slab.h96
-rw-r--r--kernel/include/mm/tlb.h35
-rw-r--r--kernel/include/multiboot.h417
-rw-r--r--kernel/include/proc/context.h62
-rw-r--r--kernel/include/proc/core.h15
-rw-r--r--kernel/include/proc/kmutex.h60
-rw-r--r--kernel/include/proc/kthread.h106
-rw-r--r--kernel/include/proc/proc.h200
-rw-r--r--kernel/include/proc/sched.h126
-rw-r--r--kernel/include/proc/spinlock.h37
-rw-r--r--kernel/include/stdarg.h7
-rw-r--r--kernel/include/test/driverstest.h3
-rw-r--r--kernel/include/test/kshell/io.h61
-rw-r--r--kernel/include/test/kshell/kshell.h52
-rw-r--r--kernel/include/test/proctest.h3
-rw-r--r--kernel/include/test/s5fstest.h3
-rw-r--r--kernel/include/test/usertest.h51
-rw-r--r--kernel/include/test/vfstest/vfstest.h156
-rw-r--r--kernel/include/types.h31
-rw-r--r--kernel/include/util/atomic.h31
-rw-r--r--kernel/include/util/bits.h27
-rw-r--r--kernel/include/util/debug.h305
-rw-r--r--kernel/include/util/delay.h73
-rw-r--r--kernel/include/util/gdb.h5
-rw-r--r--kernel/include/util/init.h21
-rw-r--r--kernel/include/util/list.h224
-rw-r--r--kernel/include/util/printf.h87
-rw-r--r--kernel/include/util/string.h93
-rw-r--r--kernel/include/util/time.h25
-rw-r--r--kernel/include/util/timer.h28
-rw-r--r--kernel/include/vm/anon.h9
-rw-r--r--kernel/include/vm/brk.h3
-rw-r--r--kernel/include/vm/mmap.h8
-rw-r--r--kernel/include/vm/pagefault.h11
-rw-r--r--kernel/include/vm/shadow.h11
-rw-r--r--kernel/include/vm/vmmap.h71
96 files changed, 8741 insertions, 0 deletions
diff --git a/kernel/include/api/access.h b/kernel/include/api/access.h
new file mode 100644
index 0000000..77f5e63
--- /dev/null
+++ b/kernel/include/api/access.h
@@ -0,0 +1,19 @@
+#pragma once
+
+#include "types.h"
+
+struct proc;
+struct argstr;
+struct argvec;
+
+long copy_from_user(void *kaddr, const void *uaddr, size_t nbytes);
+
+long copy_to_user(void *uaddr, const void *kaddr, size_t nbytes);
+
+long user_strdup(struct argstr *ustr, char **kstrp);
+
+long user_vecdup(struct argvec *uvec, char ***kvecp);
+
+long range_perm(struct proc *p, const void *vaddr, size_t len, int perm);
+
+long addr_perm(struct proc *p, const void *vaddr, int perm);
diff --git a/kernel/include/api/binfmt.h b/kernel/include/api/binfmt.h
new file mode 100644
index 0000000..5063276
--- /dev/null
+++ b/kernel/include/api/binfmt.h
@@ -0,0 +1,12 @@
+#pragma once
+
+#include "fs/vnode.h"
+
+typedef long (*binfmt_load_func_t)(const char *filename, int fd,
+ char *const *argv, char *const *envp,
+ uint64_t *rip, uint64_t *rsp);
+
+long binfmt_add(const char *id, binfmt_load_func_t loadfunc);
+
+long binfmt_load(const char *filename, char *const *argv, char *const *envp,
+ uint64_t *rip, uint64_t *rsp);
diff --git a/kernel/include/api/elf.h b/kernel/include/api/elf.h
new file mode 100644
index 0000000..5ccc109
--- /dev/null
+++ b/kernel/include/api/elf.h
@@ -0,0 +1,2595 @@
+/* This file defines standard ELF types, structures, and macros.
+ Copyright (C) 1995-2003, 2004 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#pragma once
+
+/* __BEGIN_DECLS */
+
+/* Standard ELF types. */
+
+#ifdef __KERNEL__
+#include "types.h"
+#else
+
+#include <sys/types.h>
+
+#endif
+
+/* Type for a 16-bit quantity. */
+typedef uint16_t Elf32_Half;
+typedef uint16_t Elf64_Half;
+
+/* Types for signed and unsigned 32-bit quantities. */
+typedef uint32_t Elf32_Word;
+typedef int32_t Elf32_Sword;
+typedef uint32_t Elf64_Word;
+typedef int32_t Elf64_Sword;
+
+/* Types for signed and unsigned 64-bit quantities. */
+typedef uint64_t Elf32_Xword;
+typedef int64_t Elf32_Sxword;
+typedef uint64_t Elf64_Xword;
+typedef int64_t Elf64_Sxword;
+
+/* Type of addresses. */
+typedef uint32_t Elf32_Addr;
+typedef uint64_t Elf64_Addr;
+
+/* Type of file offsets. */
+typedef uint32_t Elf32_Off;
+typedef uint64_t Elf64_Off;
+
+/* Type for section indices, which are 16-bit quantities. */
+typedef uint16_t Elf32_Section;
+typedef uint16_t Elf64_Section;
+
+/* Type for version symbol information. */
+typedef Elf32_Half Elf32_Versym;
+typedef Elf64_Half Elf64_Versym;
+
+/* The ELF file header. This appears at the start of every ELF file. */
+
+#define EI_NIDENT (16)
+
+typedef struct
+{
+ unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
+ Elf32_Half e_type; /* Object file type */
+ Elf32_Half e_machine; /* Architecture */
+ Elf32_Word e_version; /* Object file version */
+ Elf32_Addr e_entry; /* Entry point virtual address */
+ Elf32_Off e_phoff; /* Program header table file offset */
+ Elf32_Off e_shoff; /* Section header table file offset */
+ Elf32_Word e_flags; /* Processor-specific flags */
+ Elf32_Half e_ehsize; /* ELF header size in bytes */
+ Elf32_Half e_phentsize; /* Program header table entry size */
+ Elf32_Half e_phnum; /* Program header table entry count */
+ Elf32_Half e_shentsize; /* Section header table entry size */
+ Elf32_Half e_shnum; /* Section header table entry count */
+ Elf32_Half e_shstrndx; /* Section header string table index */
+} Elf32_Ehdr;
+
+typedef struct
+{
+ unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
+ Elf64_Half e_type; /* Object file type */
+ Elf64_Half e_machine; /* Architecture */
+ Elf64_Word e_version; /* Object file version */
+ Elf64_Addr e_entry; /* Entry point virtual address */
+ Elf64_Off e_phoff; /* Program header table file offset */
+ Elf64_Off e_shoff; /* Section header table file offset */
+ Elf64_Word e_flags; /* Processor-specific flags */
+ Elf64_Half e_ehsize; /* ELF header size in bytes */
+ Elf64_Half e_phentsize; /* Program header table entry size */
+ Elf64_Half e_phnum; /* Program header table entry count */
+ Elf64_Half e_shentsize; /* Section header table entry size */
+ Elf64_Half e_shnum; /* Section header table entry count */
+ Elf64_Half e_shstrndx; /* Section header string table index */
+} Elf64_Ehdr;
+
+/* Fields in the e_ident array. The EI_* macros are indices into the
+ array. The macros under each EI_* macro are the values the byte
+ may have. */
+
+#define EI_MAG0 0 /* File identification byte 0 index */
+#define ELFMAG0 0x7f /* Magic number byte 0 */
+
+#define EI_MAG1 1 /* File identification byte 1 index */
+#define ELFMAG1 'E' /* Magic number byte 1 */
+
+#define EI_MAG2 2 /* File identification byte 2 index */
+#define ELFMAG2 'L' /* Magic number byte 2 */
+
+#define EI_MAG3 3 /* File identification byte 3 index */
+#define ELFMAG3 'F' /* Magic number byte 3 */
+
+/* Conglomeration of the identification bytes, for easy testing as a word. */
+#define ELFMAG "\177ELF"
+#define SELFMAG 4
+
+#define EI_CLASS 4 /* File class byte index */
+#define ELFCLASSNONE 0 /* Invalid class */
+#define ELFCLASS32 1 /* 32-bit objects */
+#define ELFCLASS64 2 /* 64-bit objects */
+#define ELFCLASSNUM 3
+
+#define EI_DATA 5 /* Data encoding byte index */
+#define ELFDATANONE 0 /* Invalid data encoding */
+#define ELFDATA2LSB 1 /* 2's complement, little endian */
+#define ELFDATA2MSB 2 /* 2's complement, big endian */
+#define ELFDATANUM 3
+
+#define EI_VERSION 6 /* File version byte index */
+/* Value must be EV_CURRENT */
+
+#define EI_OSABI 7 /* OS ABI identification */
+#define ELFOSABI_NONE 0 /* UNIX System V ABI */
+#define ELFOSABI_SYSV 0 /* Alias. */
+#define ELFOSABI_HPUX 1 /* HP-UX */
+#define ELFOSABI_NETBSD 2 /* NetBSD. */
+#define ELFOSABI_LINUX 3 /* Linux. */
+#define ELFOSABI_SOLARIS 6 /* Sun Solaris. */
+#define ELFOSABI_AIX 7 /* IBM AIX. */
+#define ELFOSABI_IRIX 8 /* SGI Irix. */
+#define ELFOSABI_FREEBSD 9 /* FreeBSD. */
+#define ELFOSABI_TRU64 10 /* Compaq TRU64 UNIX. */
+#define ELFOSABI_MODESTO 11 /* Novell Modesto. */
+#define ELFOSABI_OPENBSD 12 /* OpenBSD. */
+#define ELFOSABI_ARM 97 /* ARM */
+#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */
+
+#define EI_ABIVERSION 8 /* ABI version */
+
+#define EI_PAD 9 /* Byte index of padding bytes */
+
+/* Legal values for e_type (object file type). */
+
+#define ET_NONE 0 /* No file type */
+#define ET_REL 1 /* Relocatable file */
+#define ET_EXEC 2 /* Executable file */
+#define ET_DYN 3 /* Shared object file */
+#define ET_CORE 4 /* Core file */
+#define ET_NUM 5 /* Number of defined types */
+#define ET_LOOS 0xfe00 /* OS-specific range start */
+#define ET_HIOS 0xfeff /* OS-specific range end */
+#define ET_LOPROC 0xff00 /* Processor-specific range start */
+#define ET_HIPROC 0xffff /* Processor-specific range end */
+
+/* Legal values for e_machine (architecture). */
+
+#define EM_NONE 0 /* No machine */
+#define EM_M32 1 /* AT&T WE 32100 */
+#define EM_SPARC 2 /* SUN SPARC */
+#define EM_386 3 /* Intel 80386 */
+#define EM_68K 4 /* Motorola m68k family */
+#define EM_88K 5 /* Motorola m88k family */
+#define EM_860 7 /* Intel 80860 */
+#define EM_MIPS 8 /* MIPS R3000 big-endian */
+#define EM_S370 9 /* IBM System/370 */
+#define EM_MIPS_RS3_LE 10 /* MIPS R3000 little-endian */
+
+#define EM_PARISC 15 /* HPPA */
+#define EM_VPP500 17 /* Fujitsu VPP500 */
+#define EM_SPARC32PLUS 18 /* Sun's "v8plus" */
+#define EM_960 19 /* Intel 80960 */
+#define EM_PPC 20 /* PowerPC */
+#define EM_PPC64 21 /* PowerPC 64-bit */
+#define EM_S390 22 /* IBM S390 */
+
+#define EM_V800 36 /* NEC V800 series */
+#define EM_FR20 37 /* Fujitsu FR20 */
+#define EM_RH32 38 /* TRW RH-32 */
+#define EM_RCE 39 /* Motorola RCE */
+#define EM_ARM 40 /* ARM */
+#define EM_FAKE_ALPHA 41 /* Digital Alpha */
+#define EM_SH 42 /* Hitachi SH */
+#define EM_SPARCV9 43 /* SPARC v9 64-bit */
+#define EM_TRICORE 44 /* Siemens Tricore */
+#define EM_ARC 45 /* Argonaut RISC Core */
+#define EM_H8_300 46 /* Hitachi H8/300 */
+#define EM_H8_300H 47 /* Hitachi H8/300H */
+#define EM_H8S 48 /* Hitachi H8S */
+#define EM_H8_500 49 /* Hitachi H8/500 */
+#define EM_IA_64 50 /* Intel Merced */
+#define EM_MIPS_X 51 /* Stanford MIPS-X */
+#define EM_COLDFIRE 52 /* Motorola Coldfire */
+#define EM_68HC12 53 /* Motorola M68HC12 */
+#define EM_MMA 54 /* Fujitsu MMA Multimedia Accelerator*/
+#define EM_PCP 55 /* Siemens PCP */
+#define EM_NCPU 56 /* Sony nCPU embeeded RISC */
+#define EM_NDR1 57 /* Denso NDR1 microprocessor */
+#define EM_STARCORE 58 /* Motorola Start*Core processor */
+#define EM_ME16 59 /* Toyota ME16 processor */
+#define EM_ST100 60 /* STMicroelectronic ST100 processor */
+#define EM_TINYJ 61 /* Advanced Logic Corp. Tinyj emb.fam*/
+#define EM_X86_64 62 /* AMD x86-64 architecture */
+#define EM_PDSP 63 /* Sony DSP Processor */
+
+#define EM_FX66 66 /* Siemens FX66 microcontroller */
+#define EM_ST9PLUS 67 /* STMicroelectronics ST9+ 8/16 mc */
+#define EM_ST7 68 /* STmicroelectronics ST7 8 bit mc */
+#define EM_68HC16 69 /* Motorola MC68HC16 microcontroller */
+#define EM_68HC11 70 /* Motorola MC68HC11 microcontroller */
+#define EM_68HC08 71 /* Motorola MC68HC08 microcontroller */
+#define EM_68HC05 72 /* Motorola MC68HC05 microcontroller */
+#define EM_SVX 73 /* Silicon Graphics SVx */
+#define EM_ST19 74 /* STMicroelectronics ST19 8 bit mc */
+#define EM_VAX 75 /* Digital VAX */
+#define EM_CRIS 76 /* Axis Communications 32-bit embedded processor */
+#define EM_JAVELIN 77 /* Infineon Technologies 32-bit embedded processor */
+#define EM_FIREPATH 78 /* Element 14 64-bit DSP Processor */
+#define EM_ZSP 79 /* LSI Logic 16-bit DSP Processor */
+#define EM_MMIX 80 /* Donald Knuth's educational 64-bit processor */
+#define EM_HUANY 81 /* Harvard University machine-independent object files */
+#define EM_PRISM 82 /* SiTera Prism */
+#define EM_AVR 83 /* Atmel AVR 8-bit microcontroller */
+#define EM_FR30 84 /* Fujitsu FR30 */
+#define EM_D10V 85 /* Mitsubishi D10V */
+#define EM_D30V 86 /* Mitsubishi D30V */
+#define EM_V850 87 /* NEC v850 */
+#define EM_M32R 88 /* Mitsubishi M32R */
+#define EM_MN10300 89 /* Matsushita MN10300 */
+#define EM_MN10200 90 /* Matsushita MN10200 */
+#define EM_PJ 91 /* picoJava */
+#define EM_OPENRISC 92 /* OpenRISC 32-bit embedded processor */
+#define EM_ARC_A5 93 /* ARC Cores Tangent-A5 */
+#define EM_XTENSA 94 /* Tensilica Xtensa Architecture */
+#define EM_NUM 95
+
+/* If it is necessary to assign new unofficial EM_* values, please
+ pick large random numbers (0x8523, 0xa7f2, etc.) to minimize the
+ chances of collision with official or non-GNU unofficial values. */
+
+#define EM_ALPHA 0x9026
+
+/* Legal values for e_version (version). */
+
+#define EV_NONE 0 /* Invalid ELF version */
+#define EV_CURRENT 1 /* Current version */
+#define EV_NUM 2
+
+/* Section header. */
+
+typedef struct
+{
+ Elf32_Word sh_name; /* Section name (string tbl index) */
+ Elf32_Word sh_type; /* Section type */
+ Elf32_Word sh_flags; /* Section flags */
+ Elf32_Addr sh_addr; /* Section virtual addr at execution */
+ Elf32_Off sh_offset; /* Section file offset */
+ Elf32_Word sh_size; /* Section size in bytes */
+ Elf32_Word sh_link; /* Link to another section */
+ Elf32_Word sh_info; /* Additional section information */
+ Elf32_Word sh_addralign; /* Section alignment */
+ Elf32_Word sh_entsize; /* Entry size if section holds table */
+} Elf32_Shdr;
+
+typedef struct
+{
+ Elf64_Word sh_name; /* Section name (string tbl index) */
+ Elf64_Word sh_type; /* Section type */
+ Elf64_Xword sh_flags; /* Section flags */
+ Elf64_Addr sh_addr; /* Section virtual addr at execution */
+ Elf64_Off sh_offset; /* Section file offset */
+ Elf64_Xword sh_size; /* Section size in bytes */
+ Elf64_Word sh_link; /* Link to another section */
+ Elf64_Word sh_info; /* Additional section information */
+ Elf64_Xword sh_addralign; /* Section alignment */
+ Elf64_Xword sh_entsize; /* Entry size if section holds table */
+} Elf64_Shdr;
+
+/* Special section indices. */
+
+#define SHN_UNDEF 0 /* Undefined section */
+#define SHN_LORESERVE 0xff00 /* Start of reserved indices */
+#define SHN_LOPROC 0xff00 /* Start of processor-specific */
+#define SHN_BEFORE \
+ 0xff00 /* Order section before all others \
+(Solaris). */
+#define SHN_AFTER \
+ 0xff01 /* Order section after all others \
+(Solaris). */
+#define SHN_HIPROC 0xff1f /* End of processor-specific */
+#define SHN_LOOS 0xff20 /* Start of OS-specific */
+#define SHN_HIOS 0xff3f /* End of OS-specific */
+#define SHN_ABS 0xfff1 /* Associated symbol is absolute */
+#define SHN_COMMON 0xfff2 /* Associated symbol is common */
+#define SHN_XINDEX 0xffff /* Index is in extra table. */
+#define SHN_HIRESERVE 0xffff /* End of reserved indices */
+
+/* Legal values for sh_type (section type). */
+
+#define SHT_NULL 0 /* Section header table entry unused */
+#define SHT_PROGBITS 1 /* Program data */
+#define SHT_SYMTAB 2 /* Symbol table */
+#define SHT_STRTAB 3 /* String table */
+#define SHT_RELA 4 /* Relocation entries with addends */
+#define SHT_HASH 5 /* Symbol hash table */
+#define SHT_DYNAMIC 6 /* Dynamic linking information */
+#define SHT_NOTE 7 /* Notes */
+#define SHT_NOBITS 8 /* Program space with no data (bss) */
+#define SHT_REL 9 /* Relocation entries, no addends */
+#define SHT_SHLIB 10 /* Reserved */
+#define SHT_DYNSYM 11 /* Dynamic linker symbol table */
+#define SHT_INIT_ARRAY 14 /* Array of constructors */
+#define SHT_FINI_ARRAY 15 /* Array of destructors */
+#define SHT_PREINIT_ARRAY 16 /* Array of pre-constructors */
+#define SHT_GROUP 17 /* Section group */
+#define SHT_SYMTAB_SHNDX 18 /* Extended section indeces */
+#define SHT_NUM 19 /* Number of defined types. */
+#define SHT_LOOS 0x60000000 /* Start OS-specific */
+#define SHT_GNU_LIBLIST 0x6ffffff7 /* Prelink library list */
+#define SHT_CHECKSUM 0x6ffffff8 /* Checksum for DSO content. */
+#define SHT_LOSUNW 0x6ffffffa /* Sun-specific low bound. */
+#define SHT_SUNW_move 0x6ffffffa
+#define SHT_SUNW_COMDAT 0x6ffffffb
+#define SHT_SUNW_syminfo 0x6ffffffc
+#define SHT_GNU_verdef 0x6ffffffd /* Version definition section. */
+#define SHT_GNU_verneed 0x6ffffffe /* Version needs section. */
+#define SHT_GNU_versym 0x6fffffff /* Version symbol table. */
+#define SHT_HISUNW 0x6fffffff /* Sun-specific high bound. */
+#define SHT_HIOS 0x6fffffff /* End OS-specific type */
+#define SHT_LOPROC 0x70000000 /* Start of processor-specific */
+#define SHT_HIPROC 0x7fffffff /* End of processor-specific */
+#define SHT_LOUSER 0x80000000 /* Start of application-specific */
+#define SHT_HIUSER 0x8fffffff /* End of application-specific */
+
+/* Legal values for sh_flags (section flags). */
+
+#define SHF_WRITE (1 << 0) /* Writable */
+#define SHF_ALLOC (1 << 1) /* Occupies memory during execution */
+#define SHF_EXECINSTR (1 << 2) /* Executable */
+#define SHF_MERGE (1 << 4) /* Might be merged */
+#define SHF_STRINGS (1 << 5) /* Contains nul-terminated strings */
+#define SHF_INFO_LINK (1 << 6) /* `sh_info' contains SHT index */
+#define SHF_LINK_ORDER (1 << 7) /* Preserve order after combining */
+#define SHF_OS_NONCONFORMING \
+ (1 << 8) /* Non-standard OS specific handling \
+required */
+#define SHF_GROUP (1 << 9) /* Section is member of a group. */
+#define SHF_TLS (1 << 10) /* Section hold thread-local data. */
+#define SHF_MASKOS 0x0ff00000 /* OS-specific. */
+#define SHF_MASKPROC 0xf0000000 /* Processor-specific */
+#define SHF_ORDERED \
+ (1 << 30) /* Special ordering requirement \
+(Solaris). */
+#define SHF_EXCLUDE \
+ (1 << 31) /* Section is excluded unless \
+referenced or allocated (Solaris).*/
+
+/* Section group handling. */
+#define GRP_COMDAT 0x1 /* Mark group as COMDAT. */
+
+/* Symbol table entry. */
+
+typedef struct
+{
+ Elf32_Word st_name; /* Symbol name (string tbl index) */
+ Elf32_Addr st_value; /* Symbol value */
+ Elf32_Word st_size; /* Symbol size */
+ unsigned char st_info; /* Symbol type and binding */
+ unsigned char st_other; /* Symbol visibility */
+ Elf32_Section st_shndx; /* Section index */
+} Elf32_Sym;
+
+typedef struct
+{
+ Elf64_Word st_name; /* Symbol name (string tbl index) */
+ unsigned char st_info; /* Symbol type and binding */
+ unsigned char st_other; /* Symbol visibility */
+ Elf64_Section st_shndx; /* Section index */
+ Elf64_Addr st_value; /* Symbol value */
+ Elf64_Xword st_size; /* Symbol size */
+} Elf64_Sym;
+
+/* The syminfo section if available contains additional information about
+ every dynamic symbol. */
+
+typedef struct
+{
+ Elf32_Half si_boundto; /* Direct bindings, symbol bound to */
+ Elf32_Half si_flags; /* Per symbol flags */
+} Elf32_Syminfo;
+
+typedef struct
+{
+ Elf64_Half si_boundto; /* Direct bindings, symbol bound to */
+ Elf64_Half si_flags; /* Per symbol flags */
+} Elf64_Syminfo;
+
+/* Possible values for si_boundto. */
+#define SYMINFO_BT_SELF 0xffff /* Symbol bound to self */
+#define SYMINFO_BT_PARENT 0xfffe /* Symbol bound to parent */
+#define SYMINFO_BT_LOWRESERVE 0xff00 /* Beginning of reserved entries */
+
+/* Possible bitmasks for si_flags. */
+#define SYMINFO_FLG_DIRECT 0x0001 /* Direct bound symbol */
+#define SYMINFO_FLG_PASSTHRU 0x0002 /* Pass-thru symbol for translator */
+#define SYMINFO_FLG_COPY 0x0004 /* Symbol is a copy-reloc */
+#define SYMINFO_FLG_LAZYLOAD \
+ 0x0008 /* Symbol bound to object to be lazy loaded */
+/* Syminfo version values. */
+#define SYMINFO_NONE 0
+#define SYMINFO_CURRENT 1
+#define SYMINFO_NUM 2
+
+/* How to extract and insert information held in the st_info field. */
+
+#define ELF32_ST_BIND(val) (((unsigned char)(val)) >> 4)
+#define ELF32_ST_TYPE(val) ((val)&0xf)
+#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type)&0xf))
+
+/* Both Elf32_Sym and Elf64_Sym use the same one-byte st_info field. */
+#define ELF64_ST_BIND(val) ELF32_ST_BIND(val)
+#define ELF64_ST_TYPE(val) ELF32_ST_TYPE(val)
+#define ELF64_ST_INFO(bind, type) ELF32_ST_INFO((bind), (type))
+
+/* Legal values for ST_BIND subfield of st_info (symbol binding). */
+
+#define STB_LOCAL 0 /* Local symbol */
+#define STB_GLOBAL 1 /* Global symbol */
+#define STB_WEAK 2 /* Weak symbol */
+#define STB_NUM 3 /* Number of defined types. */
+#define STB_LOOS 10 /* Start of OS-specific */
+#define STB_HIOS 12 /* End of OS-specific */
+#define STB_LOPROC 13 /* Start of processor-specific */
+#define STB_HIPROC 15 /* End of processor-specific */
+
+/* Legal values for ST_TYPE subfield of st_info (symbol type). */
+
+#define STT_NOTYPE 0 /* Symbol type is unspecified */
+#define STT_OBJECT 1 /* Symbol is a data object */
+#define STT_FUNC 2 /* Symbol is a code object */
+#define STT_SECTION 3 /* Symbol associated with a section */
+#define STT_FILE 4 /* Symbol's name is file name */
+#define STT_COMMON 5 /* Symbol is a common data object */
+#define STT_TLS 6 /* Symbol is thread-local data object*/
+#define STT_NUM 7 /* Number of defined types. */
+#define STT_LOOS 10 /* Start of OS-specific */
+#define STT_HIOS 12 /* End of OS-specific */
+#define STT_LOPROC 13 /* Start of processor-specific */
+#define STT_HIPROC 15 /* End of processor-specific */
+
+/* Symbol table indices are found in the hash buckets and chain table
+ of a symbol hash table section. This special index value indicates
+ the end of a chain, meaning no further symbols are found in that bucket. */
+
+#define STN_UNDEF 0 /* End of a chain. */
+
+/* How to extract and insert information held in the st_other field. */
+
+#define ELF32_ST_VISIBILITY(o) ((o)&0x03)
+
+/* For ELF64 the definitions are the same. */
+#define ELF64_ST_VISIBILITY(o) ELF32_ST_VISIBILITY(o)
+
+/* Symbol visibility specification encoded in the st_other field. */
+#define STV_DEFAULT 0 /* Default symbol visibility rules */
+#define STV_INTERNAL 1 /* Processor specific hidden class */
+#define STV_HIDDEN 2 /* Sym unavailable in other modules */
+#define STV_PROTECTED 3 /* Not preemptible, not exported */
+
+/* Relocation table entry without addend (in section of type SHT_REL). */
+
+typedef struct
+{
+ Elf32_Addr r_offset; /* Address */
+ Elf32_Word r_info; /* Relocation type and symbol index */
+} Elf32_Rel;
+
+/* I have seen two different definitions of the Elf64_Rel and
+ Elf64_Rela structures, so we'll leave them out until Novell (or
+ whoever) gets their act together. */
+/* The following, at least, is used on Sparc v9, MIPS, and Alpha. */
+
+typedef struct
+{
+ Elf64_Addr r_offset; /* Address */
+ Elf64_Xword r_info; /* Relocation type and symbol index */
+} Elf64_Rel;
+
+/* Relocation table entry with addend (in section of type SHT_RELA). */
+
+typedef struct
+{
+ Elf32_Addr r_offset; /* Address */
+ Elf32_Word r_info; /* Relocation type and symbol index */
+ Elf32_Sword r_addend; /* Addend */
+} Elf32_Rela;
+
+typedef struct
+{
+ Elf64_Addr r_offset; /* Address */
+ Elf64_Xword r_info; /* Relocation type and symbol index */
+ Elf64_Sxword r_addend; /* Addend */
+} Elf64_Rela;
+
+/* How to extract and insert information held in the r_info field. */
+
+#define ELF32_R_SYM(val) ((val) >> 8)
+#define ELF32_R_TYPE(val) ((val)&0xff)
+#define ELF32_R_INFO(sym, type) (((sym) << 8) + ((type)&0xff))
+
+#define ELF64_R_SYM(i) ((i) >> 32)
+#define ELF64_R_TYPE(i) ((i)&0xffffffff)
+#define ELF64_R_INFO(sym, type) ((((Elf64_Xword)(sym)) << 32) + (type))
+
+/* Program segment header. */
+
+typedef struct
+{
+ Elf32_Word p_type; /* Segment type */
+ Elf32_Off p_offset; /* Segment file offset */
+ Elf32_Addr p_vaddr; /* Segment virtual address */
+ Elf32_Addr p_paddr; /* Segment physical address */
+ Elf32_Word p_filesz; /* Segment size in file */
+ Elf32_Word p_memsz; /* Segment size in memory */
+ Elf32_Word p_flags; /* Segment flags */
+ Elf32_Word p_align; /* Segment alignment */
+} Elf32_Phdr;
+
+typedef struct
+{
+ Elf64_Word p_type; /* Segment type */
+ Elf64_Word p_flags; /* Segment flags */
+ Elf64_Off p_offset; /* Segment file offset */
+ Elf64_Addr p_vaddr; /* Segment virtual address */
+ Elf64_Addr p_paddr; /* Segment physical address */
+ Elf64_Xword p_filesz; /* Segment size in file */
+ Elf64_Xword p_memsz; /* Segment size in memory */
+ Elf64_Xword p_align; /* Segment alignment */
+} Elf64_Phdr;
+
+/* Legal values for p_type (segment type). */
+
+#define PT_NULL 0 /* Program header table entry unused */
+#define PT_LOAD 1 /* Loadable program segment */
+#define PT_DYNAMIC 2 /* Dynamic linking information */
+#define PT_INTERP 3 /* Program interpreter */
+#define PT_NOTE 4 /* Auxiliary information */
+#define PT_SHLIB 5 /* Reserved */
+#define PT_PHDR 6 /* Entry for header table itself */
+#define PT_TLS 7 /* Thread-local storage segment */
+#define PT_NUM 8 /* Number of defined types */
+#define PT_LOOS 0x60000000 /* Start of OS-specific */
+#define PT_GNU_EH_FRAME 0x6474e550 /* GCC .eh_frame_hdr segment */
+#define PT_GNU_STACK 0x6474e551 /* Indicates stack executability */
+#define PT_GNU_RELRO 0x6474e552 /* Read-only after relocation */
+#define PT_LOSUNW 0x6ffffffa
+#define PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */
+#define PT_SUNWSTACK 0x6ffffffb /* Stack segment */
+#define PT_HISUNW 0x6fffffff
+#define PT_HIOS 0x6fffffff /* End of OS-specific */
+#define PT_LOPROC 0x70000000 /* Start of processor-specific */
+#define PT_HIPROC 0x7fffffff /* End of processor-specific */
+
+/* Legal values for p_flags (segment flags). */
+
+#define PF_X (1 << 0) /* Segment is executable */
+#define PF_W (1 << 1) /* Segment is writable */
+#define PF_R (1 << 2) /* Segment is readable */
+#define PF_MASKOS 0x0ff00000 /* OS-specific */
+#define PF_MASKPROC 0xf0000000 /* Processor-specific */
+
+/* Legal values for note segment descriptor types for core files. */
+
+#define NT_PRSTATUS 1 /* Contains copy of prstatus struct */
+#define NT_FPREGSET 2 /* Contains copy of fpregset struct */
+#define NT_PRPSINFO 3 /* Contains copy of prpsinfo struct */
+#define NT_PRXREG 4 /* Contains copy of prxregset struct */
+#define NT_TASKSTRUCT 4 /* Contains copy of task structure */
+#define NT_PLATFORM 5 /* String from sysinfo(SI_PLATFORM) */
+#define NT_AUXV 6 /* Contains copy of auxv array */
+#define NT_GWINDOWS 7 /* Contains copy of gwindows struct */
+#define NT_ASRS 8 /* Contains copy of asrset struct */
+#define NT_PSTATUS 10 /* Contains copy of pstatus struct */
+#define NT_PSINFO 13 /* Contains copy of psinfo struct */
+#define NT_PRCRED 14 /* Contains copy of prcred struct */
+#define NT_UTSNAME 15 /* Contains copy of utsname struct */
+#define NT_LWPSTATUS 16 /* Contains copy of lwpstatus struct */
+#define NT_LWPSINFO 17 /* Contains copy of lwpinfo struct */
+#define NT_PRFPXREG 20 /* Contains copy of fprxregset struct*/
+
+/* Legal values for the note segment descriptor types for object files. */
+
+#define NT_VERSION 1 /* Contains a version string. */
+
+/* Dynamic section entry. */
+
+typedef struct
+{
+ Elf32_Sword d_tag; /* Dynamic entry type */
+ union {
+ Elf32_Word d_val; /* Integer value */
+ Elf32_Addr d_ptr; /* Address value */
+ } d_un;
+} Elf32_Dyn;
+
+typedef struct
+{
+ Elf64_Sxword d_tag; /* Dynamic entry type */
+ union {
+ Elf64_Xword d_val; /* Integer value */
+ Elf64_Addr d_ptr; /* Address value */
+ } d_un;
+} Elf64_Dyn;
+
+/* Legal values for d_tag (dynamic entry type). */
+
+#define DT_NULL 0 /* Marks end of dynamic section */
+#define DT_NEEDED 1 /* Name of needed library */
+#define DT_PLTRELSZ 2 /* Size in bytes of PLT relocs */
+#define DT_PLTGOT 3 /* Processor defined value */
+#define DT_HASH 4 /* Address of symbol hash table */
+#define DT_STRTAB 5 /* Address of string table */
+#define DT_SYMTAB 6 /* Address of symbol table */
+#define DT_RELA 7 /* Address of Rela relocs */
+#define DT_RELASZ 8 /* Total size of Rela relocs */
+#define DT_RELAENT 9 /* Size of one Rela reloc */
+#define DT_STRSZ 10 /* Size of string table */
+#define DT_SYMENT 11 /* Size of one symbol table entry */
+#define DT_INIT 12 /* Address of init function */
+#define DT_FINI 13 /* Address of termination function */
+#define DT_SONAME 14 /* Name of shared object */
+#define DT_RPATH 15 /* Library search path (deprecated) */
+#define DT_SYMBOLIC 16 /* Start symbol search here */
+#define DT_REL 17 /* Address of Rel relocs */
+#define DT_RELSZ 18 /* Total size of Rel relocs */
+#define DT_RELENT 19 /* Size of one Rel reloc */
+#define DT_PLTREL 20 /* Type of reloc in PLT */
+#define DT_DEBUG 21 /* For debugging; unspecified */
+#define DT_TEXTREL 22 /* Reloc might modify .text */
+#define DT_JMPREL 23 /* Address of PLT relocs */
+#define DT_BIND_NOW 24 /* Process relocations of object */
+#define DT_INIT_ARRAY 25 /* Array with addresses of init fct */
+#define DT_FINI_ARRAY 26 /* Array with addresses of fini fct */
+#define DT_INIT_ARRAYSZ 27 /* Size in bytes of DT_INIT_ARRAY */
+#define DT_FINI_ARRAYSZ 28 /* Size in bytes of DT_FINI_ARRAY */
+#define DT_RUNPATH 29 /* Library search path */
+#define DT_FLAGS 30 /* Flags for the object being loaded */
+#define DT_ENCODING 32 /* Start of encoded range */
+#define DT_PREINIT_ARRAY 32 /* Array with addresses of preinit fct*/
+#define DT_PREINIT_ARRAYSZ 33 /* size in bytes of DT_PREINIT_ARRAY */
+#define DT_NUM 34 /* Number used */
+#define DT_LOOS 0x6000000d /* Start of OS-specific */
+#define DT_HIOS 0x6ffff000 /* End of OS-specific */
+#define DT_LOPROC 0x70000000 /* Start of processor-specific */
+#define DT_HIPROC 0x7fffffff /* End of processor-specific */
+#define DT_PROCNUM DT_MIPS_NUM /* Most used by any processor */
+
+/* DT_* entries which fall between DT_VALRNGHI & DT_VALRNGLO use the
+ Dyn.d_un.d_val field of the Elf*_Dyn structure. This follows Sun's
+ approach. */
+#define DT_VALRNGLO 0x6ffffd00
+#define DT_GNU_PRELINKED 0x6ffffdf5 /* Prelinking timestamp */
+#define DT_GNU_CONFLICTSZ 0x6ffffdf6 /* Size of conflict section */
+#define DT_GNU_LIBLISTSZ 0x6ffffdf7 /* Size of library list */
+#define DT_CHECKSUM 0x6ffffdf8
+#define DT_PLTPADSZ 0x6ffffdf9
+#define DT_MOVEENT 0x6ffffdfa
+#define DT_MOVESZ 0x6ffffdfb
+#define DT_FEATURE_1 0x6ffffdfc /* Feature selection (DTF_*). */
+#define DT_POSFLAG_1 \
+ 0x6ffffdfd /* Flags for DT_* entries, effecting \
+the following DT_* entry. */
+#define DT_SYMINSZ 0x6ffffdfe /* Size of syminfo table (in bytes) */
+#define DT_SYMINENT 0x6ffffdff /* Entry size of syminfo */
+#define DT_VALRNGHI 0x6ffffdff
+#define DT_VALTAGIDX(tag) (DT_VALRNGHI - (tag)) /* Reverse order! */
+#define DT_VALNUM 12
+
+/* DT_* entries which fall between DT_ADDRRNGHI & DT_ADDRRNGLO use the
+ Dyn.d_un.d_ptr field of the Elf*_Dyn structure.
+
+ If any adjustment is made to the ELF object after it has been
+ built these entries will need to be adjusted. */
+#define DT_ADDRRNGLO 0x6ffffe00
+#define DT_GNU_CONFLICT 0x6ffffef8 /* Start of conflict section */
+#define DT_GNU_LIBLIST 0x6ffffef9 /* Library list */
+#define DT_CONFIG 0x6ffffefa /* Configuration information. */
+#define DT_DEPAUDIT 0x6ffffefb /* Dependency auditing. */
+#define DT_AUDIT 0x6ffffefc /* Object auditing. */
+#define DT_PLTPAD 0x6ffffefd /* PLT padding. */
+#define DT_MOVETAB 0x6ffffefe /* Move table. */
+#define DT_SYMINFO 0x6ffffeff /* Syminfo table. */
+#define DT_ADDRRNGHI 0x6ffffeff
+#define DT_ADDRTAGIDX(tag) (DT_ADDRRNGHI - (tag)) /* Reverse order! */
+#define DT_ADDRNUM 10
+
+/* The versioning entry types. The next are defined as part of the
+ GNU extension. */
+#define DT_VERSYM 0x6ffffff0
+
+#define DT_RELACOUNT 0x6ffffff9
+#define DT_RELCOUNT 0x6ffffffa
+
+/* These were chosen by Sun. */
+#define DT_FLAGS_1 0x6ffffffb /* State flags, see DF_1_* below. */
+#define DT_VERDEF \
+ 0x6ffffffc /* Address of version definition \
+table */
+#define DT_VERDEFNUM 0x6ffffffd /* Number of version definitions */
+#define DT_VERNEED \
+ 0x6ffffffe /* Address of table with needed \
+ versions */
+#define DT_VERNEEDNUM 0x6fffffff /* Number of needed versions */
+#define DT_VERSIONTAGIDX(tag) (DT_VERNEEDNUM - (tag)) /* Reverse order! */
+#define DT_VERSIONTAGNUM 16
+
+/* Sun added these machine-independent extensions in the "processor-specific"
+ range. Be compatible. */
+#define DT_AUXILIARY 0x7ffffffd /* Shared object to load before self */
+#define DT_FILTER 0x7fffffff /* Shared object to get values from */
+#define DT_EXTRATAGIDX(tag) ((Elf32_Word) - ((Elf32_Sword)(tag) << 1 >> 1) - 1)
+#define DT_EXTRANUM 3
+
+/* Values of `d_un.d_val' in the DT_FLAGS entry. */
+#define DF_ORIGIN 0x00000001 /* Object may use DF_ORIGIN */
+#define DF_SYMBOLIC 0x00000002 /* Symbol resolutions starts here */
+#define DF_TEXTREL 0x00000004 /* Object contains text relocations */
+#define DF_BIND_NOW 0x00000008 /* No lazy binding for this object */
+#define DF_STATIC_TLS 0x00000010 /* Module uses the static TLS model */
+
+/* State flags selectable in the `d_un.d_val' element of the DT_FLAGS_1
+ entry in the dynamic section. */
+#define DF_1_NOW 0x00000001 /* Set RTLD_NOW for this object. */
+#define DF_1_GLOBAL 0x00000002 /* Set RTLD_GLOBAL for this object. */
+#define DF_1_GROUP 0x00000004 /* Set RTLD_GROUP for this object. */
+#define DF_1_NODELETE 0x00000008 /* Set RTLD_NODELETE for this object.*/
+#define DF_1_LOADFLTR 0x00000010 /* Trigger filtee loading at runtime.*/
+#define DF_1_INITFIRST 0x00000020 /* Set RTLD_INITFIRST for this object*/
+#define DF_1_NOOPEN 0x00000040 /* Set RTLD_NOOPEN for this object. */
+#define DF_1_ORIGIN 0x00000080 /* $ORIGIN must be handled. */
+#define DF_1_DIRECT 0x00000100 /* Direct binding enabled. */
+#define DF_1_TRANS 0x00000200
+#define DF_1_INTERPOSE 0x00000400 /* Object is used to interpose. */
+#define DF_1_NODEFLIB 0x00000800 /* Ignore default lib search path. */
+#define DF_1_NODUMP 0x00001000 /* Object can't be dldump'ed. */
+#define DF_1_CONFALT 0x00002000 /* Configuration alternative created.*/
+#define DF_1_ENDFILTEE 0x00004000 /* Filtee terminates filters search. */
+#define DF_1_DISPRELDNE 0x00008000 /* Disp reloc applied at build time. */
+#define DF_1_DISPRELPND 0x00010000 /* Disp reloc applied at run-time. */
+
+/* Flags for the feature selection in DT_FEATURE_1. */
+#define DTF_1_PARINIT 0x00000001
+#define DTF_1_CONFEXP 0x00000002
+
+/* Flags in the DT_POSFLAG_1 entry effecting only the next DT_* entry. */
+#define DF_P1_LAZYLOAD 0x00000001 /* Lazyload following object. */
+#define DF_P1_GROUPPERM \
+ 0x00000002 /* Symbols from next object are not \
+generally available. */
+
+/* Version definition sections. */
+
+typedef struct
+{
+ Elf32_Half vd_version; /* Version revision */
+ Elf32_Half vd_flags; /* Version information */
+ Elf32_Half vd_ndx; /* Version Index */
+ Elf32_Half vd_cnt; /* Number of associated aux entries */
+ Elf32_Word vd_hash; /* Version name hash value */
+ Elf32_Word vd_aux; /* Offset in bytes to verdaux array */
+ Elf32_Word vd_next; /* Offset in bytes to next verdef
+ entry */
+} Elf32_Verdef;
+
+typedef struct
+{
+ Elf64_Half vd_version; /* Version revision */
+ Elf64_Half vd_flags; /* Version information */
+ Elf64_Half vd_ndx; /* Version Index */
+ Elf64_Half vd_cnt; /* Number of associated aux entries */
+ Elf64_Word vd_hash; /* Version name hash value */
+ Elf64_Word vd_aux; /* Offset in bytes to verdaux array */
+ Elf64_Word vd_next; /* Offset in bytes to next verdef
+ entry */
+} Elf64_Verdef;
+
+/* Legal values for vd_version (version revision). */
+#define VER_DEF_NONE 0 /* No version */
+#define VER_DEF_CURRENT 1 /* Current version */
+#define VER_DEF_NUM 2 /* Given version number */
+
+/* Legal values for vd_flags (version information flags). */
+#define VER_FLG_BASE 0x1 /* Version definition of file itself */
+#define VER_FLG_WEAK 0x2 /* Weak version identifier */
+
+/* Versym symbol index values. */
+#define VER_NDX_LOCAL 0 /* Symbol is local. */
+#define VER_NDX_GLOBAL 1 /* Symbol is global. */
+#define VER_NDX_LORESERVE 0xff00 /* Beginning of reserved entries. */
+#define VER_NDX_ELIMINATE 0xff01 /* Symbol is to be eliminated. */
+
+/* Auxialiary version information. */
+
+typedef struct
+{
+ Elf32_Word vda_name; /* Version or dependency names */
+ Elf32_Word vda_next; /* Offset in bytes to next verdaux
+ entry */
+} Elf32_Verdaux;
+
+typedef struct
+{
+ Elf64_Word vda_name; /* Version or dependency names */
+ Elf64_Word vda_next; /* Offset in bytes to next verdaux
+ entry */
+} Elf64_Verdaux;
+
+/* Version dependency section. */
+
+typedef struct
+{
+ Elf32_Half vn_version; /* Version of structure */
+ Elf32_Half vn_cnt; /* Number of associated aux entries */
+ Elf32_Word vn_file; /* Offset of filename for this
+ dependency */
+ Elf32_Word vn_aux; /* Offset in bytes to vernaux array */
+ Elf32_Word vn_next; /* Offset in bytes to next verneed
+ entry */
+} Elf32_Verneed;
+
+typedef struct
+{
+ Elf64_Half vn_version; /* Version of structure */
+ Elf64_Half vn_cnt; /* Number of associated aux entries */
+ Elf64_Word vn_file; /* Offset of filename for this
+ dependency */
+ Elf64_Word vn_aux; /* Offset in bytes to vernaux array */
+ Elf64_Word vn_next; /* Offset in bytes to next verneed
+ entry */
+} Elf64_Verneed;
+
+/* Legal values for vn_version (version revision). */
+#define VER_NEED_NONE 0 /* No version */
+#define VER_NEED_CURRENT 1 /* Current version */
+#define VER_NEED_NUM 2 /* Given version number */
+
+/* Auxiliary needed version information. */
+
+typedef struct
+{
+ Elf32_Word vna_hash; /* Hash value of dependency name */
+ Elf32_Half vna_flags; /* Dependency specific information */
+ Elf32_Half vna_other; /* Unused */
+ Elf32_Word vna_name; /* Dependency name string offset */
+ Elf32_Word vna_next; /* Offset in bytes to next vernaux
+ entry */
+} Elf32_Vernaux;
+
+typedef struct
+{
+ Elf64_Word vna_hash; /* Hash value of dependency name */
+ Elf64_Half vna_flags; /* Dependency specific information */
+ Elf64_Half vna_other; /* Unused */
+ Elf64_Word vna_name; /* Dependency name string offset */
+ Elf64_Word vna_next; /* Offset in bytes to next vernaux
+ entry */
+} Elf64_Vernaux;
+
+/* Legal values for vna_flags. */
+#define VER_FLG_WEAK 0x2 /* Weak version identifier */
+
+/* Auxiliary vector. */
+
+/* This vector is normally only used by the program interpreter. The
+ usual definition in an ABI supplement uses the name auxv_t. The
+ vector is not usually defined in a standard <elf.h> file, but it
+ can't hurt. We rename it to avoid conflicts. The sizes of these
+ types are an arrangement between the exec server and the program
+ interpreter, so we don't fully specify them here. */
+
+typedef struct
+{
+ int a_type; /* Entry type */
+ union {
+ long int a_val; /* Integer value */
+ void *a_ptr; /* Pointer value */
+ void (*a_fcn)(void); /* Function pointer value */
+ } a_un;
+} Elf32_auxv_t;
+
+typedef struct
+{
+ long int a_type; /* Entry type */
+ union {
+ long int a_val; /* Integer value */
+ void *a_ptr; /* Pointer value */
+ void (*a_fcn)(void); /* Function pointer value */
+ } a_un;
+} Elf64_auxv_t;
+
+/* Legal values for a_type (entry type). */
+
+#define AT_NULL 0 /* End of vector */
+#define AT_IGNORE 1 /* Entry should be ignored */
+#define AT_EXECFD 2 /* File descriptor of program */
+#define AT_PHDR 3 /* Program headers for program */
+#define AT_PHENT 4 /* Size of program header entry */
+#define AT_PHNUM 5 /* Number of program headers */
+#define AT_PAGESZ 6 /* System page size */
+#define AT_BASE 7 /* Base address of interpreter */
+#define AT_FLAGS 8 /* Flags */
+#define AT_ENTRY 9 /* Entry point of program */
+#define AT_NOTELF 10 /* Program is not ELF */
+#define AT_UID 11 /* Real uid */
+#define AT_EUID 12 /* Effective uid */
+#define AT_GID 13 /* Real gid */
+#define AT_EGID 14 /* Effective gid */
+#define AT_CLKTCK 17 /* Frequency of times() */
+
+/* Some more special a_type values describing the hardware. */
+#define AT_PLATFORM 15 /* String identifying platform. */
+#define AT_HWCAP \
+ 16 /* Machine dependent hints about \
+processor capabilities. */
+
+/* This entry gives some information about the FPU initialization
+ performed by the kernel. */
+#define AT_FPUCW 18 /* Used FPU control word. */
+
+/* Cache block sizes. */
+#define AT_DCACHEBSIZE 19 /* Data cache block size. */
+#define AT_ICACHEBSIZE 20 /* Instruction cache block size. */
+#define AT_UCACHEBSIZE 21 /* Unified cache block size. */
+
+/* A special ignored value for PPC, used by the kernel to control the
+ interpretation of the AUXV. Must be > 16. */
+#define AT_IGNOREPPC 22 /* Entry should be ignored. */
+
+#define AT_SECURE 23 /* Boolean, was exec setuid-like? */
+
+/* Pointer to the global system page used for system calls and other
+ nice things. */
+#define AT_SYSINFO 32
+#define AT_SYSINFO_EHDR 33
+
+/* Shapes of the caches. Bits 0-3 contains associativity; bits 4-7 contains
+ log2 of line size; mask those to get cache size. */
+#define AT_L1I_CACHESHAPE 34
+#define AT_L1D_CACHESHAPE 35
+#define AT_L2_CACHESHAPE 36
+#define AT_L3_CACHESHAPE 37
+
+/* Note section contents. Each entry in the note section begins with
+ a header of a fixed form. */
+
+typedef struct
+{
+ Elf32_Word n_namesz; /* Length of the note's name. */
+ Elf32_Word n_descsz; /* Length of the note's descriptor. */
+ Elf32_Word n_type; /* Type of the note. */
+} Elf32_Nhdr;
+
+typedef struct
+{
+ Elf64_Word n_namesz; /* Length of the note's name. */
+ Elf64_Word n_descsz; /* Length of the note's descriptor. */
+ Elf64_Word n_type; /* Type of the note. */
+} Elf64_Nhdr;
+
+/* Known names of notes. */
+
+/* Solaris entries in the note section have this name. */
+#define ELF_NOTE_SOLARIS "SUNW Solaris"
+
+/* Note entries for GNU systems have this name. */
+#define ELF_NOTE_GNU "GNU"
+
+/* Defined types of notes for Solaris. */
+
+/* Value of descriptor (one word) is desired pagesize for the binary. */
+#define ELF_NOTE_PAGESIZE_HINT 1
+
+/* Defined note types for GNU systems. */
+
+/* ABI information. The descriptor consists of words:
+ word 0: OS descriptor
+ word 1: major version of the ABI
+ word 2: minor version of the ABI
+ word 3: subminor version of the ABI
+*/
+#define ELF_NOTE_ABI 1
+
+/* Known OSes. These value can appear in word 0 of an ELF_NOTE_ABI
+ note section entry. */
+#define ELF_NOTE_OS_LINUX 0
+#define ELF_NOTE_OS_GNU 1
+#define ELF_NOTE_OS_SOLARIS2 2
+#define ELF_NOTE_OS_FREEBSD 3
+
+/* Move records. */
+typedef struct
+{
+ Elf32_Xword m_value; /* Symbol value. */
+ Elf32_Word m_info; /* Size and index. */
+ Elf32_Word m_poffset; /* Symbol offset. */
+ Elf32_Half m_repeat; /* Repeat count. */
+ Elf32_Half m_stride; /* Stride info. */
+} Elf32_Move;
+
+typedef struct
+{
+ Elf64_Xword m_value; /* Symbol value. */
+ Elf64_Xword m_info; /* Size and index. */
+ Elf64_Xword m_poffset; /* Symbol offset. */
+ Elf64_Half m_repeat; /* Repeat count. */
+ Elf64_Half m_stride; /* Stride info. */
+} Elf64_Move;
+
+/* Macro to construct move records. */
+#define ELF32_M_SYM(info) ((info) >> 8)
+#define ELF32_M_SIZE(info) ((unsigned char)(info))
+#define ELF32_M_INFO(sym, size) (((sym) << 8) + (unsigned char)(size))
+
+#define ELF64_M_SYM(info) ELF32_M_SYM(info)
+#define ELF64_M_SIZE(info) ELF32_M_SIZE(info)
+#define ELF64_M_INFO(sym, size) ELF32_M_INFO(sym, size)
+
+/* Motorola 68k specific definitions. */
+
+/* Values for Elf32_Ehdr.e_flags. */
+#define EF_CPU32 0x00810000
+
+/* m68k relocs. */
+
+#define R_68K_NONE 0 /* No reloc */
+#define R_68K_32 1 /* Direct 32 bit */
+#define R_68K_16 2 /* Direct 16 bit */
+#define R_68K_8 3 /* Direct 8 bit */
+#define R_68K_PC32 4 /* PC relative 32 bit */
+#define R_68K_PC16 5 /* PC relative 16 bit */
+#define R_68K_PC8 6 /* PC relative 8 bit */
+#define R_68K_GOT32 7 /* 32 bit PC relative GOT entry */
+#define R_68K_GOT16 8 /* 16 bit PC relative GOT entry */
+#define R_68K_GOT8 9 /* 8 bit PC relative GOT entry */
+#define R_68K_GOT32O 10 /* 32 bit GOT offset */
+#define R_68K_GOT16O 11 /* 16 bit GOT offset */
+#define R_68K_GOT8O 12 /* 8 bit GOT offset */
+#define R_68K_PLT32 13 /* 32 bit PC relative PLT address */
+#define R_68K_PLT16 14 /* 16 bit PC relative PLT address */
+#define R_68K_PLT8 15 /* 8 bit PC relative PLT address */
+#define R_68K_PLT32O 16 /* 32 bit PLT offset */
+#define R_68K_PLT16O 17 /* 16 bit PLT offset */
+#define R_68K_PLT8O 18 /* 8 bit PLT offset */
+#define R_68K_COPY 19 /* Copy symbol at runtime */
+#define R_68K_GLOB_DAT 20 /* Create GOT entry */
+#define R_68K_JMP_SLOT 21 /* Create PLT entry */
+#define R_68K_RELATIVE 22 /* Adjust by program base */
+/* Keep this the last entry. */
+#define R_68K_NUM 23
+
+/* Intel 80386 specific definitions. */
+
+/* i386 relocs. */
+
+#define R_386_NONE 0 /* No reloc */
+#define R_386_32 1 /* Direct 32 bit */
+#define R_386_PC32 2 /* PC relative 32 bit */
+#define R_386_GOT32 3 /* 32 bit GOT entry */
+#define R_386_PLT32 4 /* 32 bit PLT address */
+#define R_386_COPY 5 /* Copy symbol at runtime */
+#define R_386_GLOB_DAT 6 /* Create GOT entry */
+#define R_386_JMP_SLOT 7 /* Create PLT entry */
+#define R_386_RELATIVE 8 /* Adjust by program base */
+#define R_386_GOTOFF 9 /* 32 bit offset to GOT */
+#define R_386_GOTPC 10 /* 32 bit PC relative offset to GOT */
+#define R_386_32PLT 11
+#define R_386_TLS_TPOFF 14 /* Offset in static TLS block */
+#define R_386_TLS_IE \
+ 15 /* Address of GOT entry for static TLS \
+block offset */
+#define R_386_TLS_GOTIE \
+ 16 /* GOT entry for static TLS block \
+offset */
+#define R_386_TLS_LE \
+ 17 /* Offset relative to static TLS \
+block */
+#define R_386_TLS_GD \
+ 18 /* Direct 32 bit for GNU version of \
+general dynamic thread local data */
+#define R_386_TLS_LDM \
+ 19 /* Direct 32 bit for GNU version of \
+local dynamic thread local data \
+in LE code */
+#define R_386_16 20
+#define R_386_PC16 21
+#define R_386_8 22
+#define R_386_PC8 23
+#define R_386_TLS_GD_32 \
+ 24 /* Direct 32 bit for general dynamic \
+thread local data */
+#define R_386_TLS_GD_PUSH 25 /* Tag for pushl in GD TLS code */
+#define R_386_TLS_GD_CALL \
+ 26 /* Relocation for call to \
+__tls_get_addr() */
+#define R_386_TLS_GD_POP 27 /* Tag for popl in GD TLS code */
+#define R_386_TLS_LDM_32 \
+ 28 /* Direct 32 bit for local dynamic \
+thread local data in LE code */
+#define R_386_TLS_LDM_PUSH 29 /* Tag for pushl in LDM TLS code */
+#define R_386_TLS_LDM_CALL \
+ 30 /* Relocation for call to \
+__tls_get_addr() in LDM code */
+#define R_386_TLS_LDM_POP 31 /* Tag for popl in LDM TLS code */
+#define R_386_TLS_LDO_32 32 /* Offset relative to TLS block */
+#define R_386_TLS_IE_32 \
+ 33 /* GOT entry for negated static TLS \
+block offset */
+#define R_386_TLS_LE_32 \
+ 34 /* Negated offset relative to static \
+TLS block */
+#define R_386_TLS_DTPMOD32 35 /* ID of module containing symbol */
+#define R_386_TLS_DTPOFF32 36 /* Offset in TLS block */
+#define R_386_TLS_TPOFF32 37 /* Negated offset in static TLS block */
+/* Keep this the last entry. */
+#define R_386_NUM 38
+
+/* SUN SPARC specific definitions. */
+
+/* Legal values for ST_TYPE subfield of st_info (symbol type). */
+
+#define STT_SPARC_REGISTER 13 /* Global register reserved to app. */
+
+/* Values for Elf64_Ehdr.e_flags. */
+
+#define EF_SPARCV9_MM 3
+#define EF_SPARCV9_TSO 0
+#define EF_SPARCV9_PSO 1
+#define EF_SPARCV9_RMO 2
+#define EF_SPARC_LEDATA 0x800000 /* little endian data */
+#define EF_SPARC_EXT_MASK 0xFFFF00
+#define EF_SPARC_32PLUS 0x000100 /* generic V8+ features */
+#define EF_SPARC_SUN_US1 0x000200 /* Sun UltraSPARC1 extensions */
+#define EF_SPARC_HAL_R1 0x000400 /* HAL R1 extensions */
+#define EF_SPARC_SUN_US3 0x000800 /* Sun UltraSPARCIII extensions */
+
+/* SPARC relocs. */
+
+#define R_SPARC_NONE 0 /* No reloc */
+#define R_SPARC_8 1 /* Direct 8 bit */
+#define R_SPARC_16 2 /* Direct 16 bit */
+#define R_SPARC_32 3 /* Direct 32 bit */
+#define R_SPARC_DISP8 4 /* PC relative 8 bit */
+#define R_SPARC_DISP16 5 /* PC relative 16 bit */
+#define R_SPARC_DISP32 6 /* PC relative 32 bit */
+#define R_SPARC_WDISP30 7 /* PC relative 30 bit shifted */
+#define R_SPARC_WDISP22 8 /* PC relative 22 bit shifted */
+#define R_SPARC_HI22 9 /* High 22 bit */
+#define R_SPARC_22 10 /* Direct 22 bit */
+#define R_SPARC_13 11 /* Direct 13 bit */
+#define R_SPARC_LO10 12 /* Truncated 10 bit */
+#define R_SPARC_GOT10 13 /* Truncated 10 bit GOT entry */
+#define R_SPARC_GOT13 14 /* 13 bit GOT entry */
+#define R_SPARC_GOT22 15 /* 22 bit GOT entry shifted */
+#define R_SPARC_PC10 16 /* PC relative 10 bit truncated */
+#define R_SPARC_PC22 17 /* PC relative 22 bit shifted */
+#define R_SPARC_WPLT30 18 /* 30 bit PC relative PLT address */
+#define R_SPARC_COPY 19 /* Copy symbol at runtime */
+#define R_SPARC_GLOB_DAT 20 /* Create GOT entry */
+#define R_SPARC_JMP_SLOT 21 /* Create PLT entry */
+#define R_SPARC_RELATIVE 22 /* Adjust by program base */
+#define R_SPARC_UA32 23 /* Direct 32 bit unaligned */
+
+/* Additional Sparc64 relocs. */
+
+#define R_SPARC_PLT32 24 /* Direct 32 bit ref to PLT entry */
+#define R_SPARC_HIPLT22 25 /* High 22 bit PLT entry */
+#define R_SPARC_LOPLT10 26 /* Truncated 10 bit PLT entry */
+#define R_SPARC_PCPLT32 27 /* PC rel 32 bit ref to PLT entry */
+#define R_SPARC_PCPLT22 28 /* PC rel high 22 bit PLT entry */
+#define R_SPARC_PCPLT10 29 /* PC rel trunc 10 bit PLT entry */
+#define R_SPARC_10 30 /* Direct 10 bit */
+#define R_SPARC_11 31 /* Direct 11 bit */
+#define R_SPARC_64 32 /* Direct 64 bit */
+#define R_SPARC_OLO10 33 /* 10bit with secondary 13bit addend */
+#define R_SPARC_HH22 34 /* Top 22 bits of direct 64 bit */
+#define R_SPARC_HM10 35 /* High middle 10 bits of ... */
+#define R_SPARC_LM22 36 /* Low middle 22 bits of ... */
+#define R_SPARC_PC_HH22 37 /* Top 22 bits of pc rel 64 bit */
+#define R_SPARC_PC_HM10 38 /* High middle 10 bit of ... */
+#define R_SPARC_PC_LM22 39 /* Low miggle 22 bits of ... */
+#define R_SPARC_WDISP16 40 /* PC relative 16 bit shifted */
+#define R_SPARC_WDISP19 41 /* PC relative 19 bit shifted */
+#define R_SPARC_7 43 /* Direct 7 bit */
+#define R_SPARC_5 44 /* Direct 5 bit */
+#define R_SPARC_6 45 /* Direct 6 bit */
+#define R_SPARC_DISP64 46 /* PC relative 64 bit */
+#define R_SPARC_PLT64 47 /* Direct 64 bit ref to PLT entry */
+#define R_SPARC_HIX22 48 /* High 22 bit complemented */
+#define R_SPARC_LOX10 49 /* Truncated 11 bit complemented */
+#define R_SPARC_H44 50 /* Direct high 12 of 44 bit */
+#define R_SPARC_M44 51 /* Direct mid 22 of 44 bit */
+#define R_SPARC_L44 52 /* Direct low 10 of 44 bit */
+#define R_SPARC_REGISTER 53 /* Global register usage */
+#define R_SPARC_UA64 54 /* Direct 64 bit unaligned */
+#define R_SPARC_UA16 55 /* Direct 16 bit unaligned */
+#define R_SPARC_TLS_GD_HI22 56
+#define R_SPARC_TLS_GD_LO10 57
+#define R_SPARC_TLS_GD_ADD 58
+#define R_SPARC_TLS_GD_CALL 59
+#define R_SPARC_TLS_LDM_HI22 60
+#define R_SPARC_TLS_LDM_LO10 61
+#define R_SPARC_TLS_LDM_ADD 62
+#define R_SPARC_TLS_LDM_CALL 63
+#define R_SPARC_TLS_LDO_HIX22 64
+#define R_SPARC_TLS_LDO_LOX10 65
+#define R_SPARC_TLS_LDO_ADD 66
+#define R_SPARC_TLS_IE_HI22 67
+#define R_SPARC_TLS_IE_LO10 68
+#define R_SPARC_TLS_IE_LD 69
+#define R_SPARC_TLS_IE_LDX 70
+#define R_SPARC_TLS_IE_ADD 71
+#define R_SPARC_TLS_LE_HIX22 72
+#define R_SPARC_TLS_LE_LOX10 73
+#define R_SPARC_TLS_DTPMOD32 74
+#define R_SPARC_TLS_DTPMOD64 75
+#define R_SPARC_TLS_DTPOFF32 76
+#define R_SPARC_TLS_DTPOFF64 77
+#define R_SPARC_TLS_TPOFF32 78
+#define R_SPARC_TLS_TPOFF64 79
+/* Keep this the last entry. */
+#define R_SPARC_NUM 80
+
+/* For Sparc64, legal values for d_tag of Elf64_Dyn. */
+
+#define DT_SPARC_REGISTER 0x70000001
+#define DT_SPARC_NUM 2
+
+/* Bits present in AT_HWCAP, primarily for Sparc32. */
+
+#define HWCAP_SPARC_FLUSH 1 /* The cpu supports flush insn. */
+#define HWCAP_SPARC_STBAR 2
+#define HWCAP_SPARC_SWAP 4
+#define HWCAP_SPARC_MULDIV 8
+#define HWCAP_SPARC_V9 16 /* The cpu is v9, so v8plus is ok. */
+#define HWCAP_SPARC_ULTRA3 32
+
+/* MIPS R3000 specific definitions. */
+
+/* Legal values for e_flags field of Elf32_Ehdr. */
+
+#define EF_MIPS_NOREORDER 1 /* A .noreorder directive was used */
+#define EF_MIPS_PIC 2 /* Contains PIC code */
+#define EF_MIPS_CPIC 4 /* Uses PIC calling sequence */
+#define EF_MIPS_XGOT 8
+#define EF_MIPS_64BIT_WHIRL 16
+#define EF_MIPS_ABI2 32
+#define EF_MIPS_ABI_ON32 64
+#define EF_MIPS_ARCH 0xf0000000 /* MIPS architecture level */
+
+/* Legal values for MIPS architecture level. */
+
+#define EF_MIPS_ARCH_1 0x00000000 /* -mips1 code. */
+#define EF_MIPS_ARCH_2 0x10000000 /* -mips2 code. */
+#define EF_MIPS_ARCH_3 0x20000000 /* -mips3 code. */
+#define EF_MIPS_ARCH_4 0x30000000 /* -mips4 code. */
+#define EF_MIPS_ARCH_5 0x40000000 /* -mips5 code. */
+#define EF_MIPS_ARCH_32 0x60000000 /* MIPS32 code. */
+#define EF_MIPS_ARCH_64 0x70000000 /* MIPS64 code. */
+
+/* The following are non-official names and should not be used. */
+
+#define E_MIPS_ARCH_1 0x00000000 /* -mips1 code. */
+#define E_MIPS_ARCH_2 0x10000000 /* -mips2 code. */
+#define E_MIPS_ARCH_3 0x20000000 /* -mips3 code. */
+#define E_MIPS_ARCH_4 0x30000000 /* -mips4 code. */
+#define E_MIPS_ARCH_5 0x40000000 /* -mips5 code. */
+#define E_MIPS_ARCH_32 0x60000000 /* MIPS32 code. */
+#define E_MIPS_ARCH_64 0x70000000 /* MIPS64 code. */
+
+/* Special section indices. */
+
+#define SHN_MIPS_ACOMMON 0xff00 /* Allocated common symbols */
+#define SHN_MIPS_TEXT 0xff01 /* Allocated test symbols. */
+#define SHN_MIPS_DATA 0xff02 /* Allocated data symbols. */
+#define SHN_MIPS_SCOMMON 0xff03 /* Small common symbols */
+#define SHN_MIPS_SUNDEFINED 0xff04 /* Small undefined symbols */
+
+/* Legal values for sh_type field of Elf32_Shdr. */
+
+#define SHT_MIPS_LIBLIST 0x70000000 /* Shared objects used in link */
+#define SHT_MIPS_MSYM 0x70000001
+#define SHT_MIPS_CONFLICT 0x70000002 /* Conflicting symbols */
+#define SHT_MIPS_GPTAB 0x70000003 /* Global data area sizes */
+#define SHT_MIPS_UCODE 0x70000004 /* Reserved for SGI/MIPS compilers */
+#define SHT_MIPS_DEBUG 0x70000005 /* MIPS ECOFF debugging information*/
+#define SHT_MIPS_REGINFO 0x70000006 /* Register usage information */
+#define SHT_MIPS_PACKAGE 0x70000007
+#define SHT_MIPS_PACKSYM 0x70000008
+#define SHT_MIPS_RELD 0x70000009
+#define SHT_MIPS_IFACE 0x7000000b
+#define SHT_MIPS_CONTENT 0x7000000c
+#define SHT_MIPS_OPTIONS 0x7000000d /* Miscellaneous options. */
+#define SHT_MIPS_SHDR 0x70000010
+#define SHT_MIPS_FDESC 0x70000011
+#define SHT_MIPS_EXTSYM 0x70000012
+#define SHT_MIPS_DENSE 0x70000013
+#define SHT_MIPS_PDESC 0x70000014
+#define SHT_MIPS_LOCSYM 0x70000015
+#define SHT_MIPS_AUXSYM 0x70000016
+#define SHT_MIPS_OPTSYM 0x70000017
+#define SHT_MIPS_LOCSTR 0x70000018
+#define SHT_MIPS_LINE 0x70000019
+#define SHT_MIPS_RFDESC 0x7000001a
+#define SHT_MIPS_DELTASYM 0x7000001b
+#define SHT_MIPS_DELTAINST 0x7000001c
+#define SHT_MIPS_DELTACLASS 0x7000001d
+#define SHT_MIPS_DWARF 0x7000001e /* DWARF debugging information. */
+#define SHT_MIPS_DELTADECL 0x7000001f
+#define SHT_MIPS_SYMBOL_LIB 0x70000020
+#define SHT_MIPS_EVENTS 0x70000021 /* Event section. */
+#define SHT_MIPS_TRANSLATE 0x70000022
+#define SHT_MIPS_PIXIE 0x70000023
+#define SHT_MIPS_XLATE 0x70000024
+#define SHT_MIPS_XLATE_DEBUG 0x70000025
+#define SHT_MIPS_WHIRL 0x70000026
+#define SHT_MIPS_EH_REGION 0x70000027
+#define SHT_MIPS_XLATE_OLD 0x70000028
+#define SHT_MIPS_PDR_EXCEPTION 0x70000029
+
+/* Legal values for sh_flags field of Elf32_Shdr. */
+
+#define SHF_MIPS_GPREL 0x10000000 /* Must be part of global data area */
+#define SHF_MIPS_MERGE 0x20000000
+#define SHF_MIPS_ADDR 0x40000000
+#define SHF_MIPS_STRINGS 0x80000000
+#define SHF_MIPS_NOSTRIP 0x08000000
+#define SHF_MIPS_LOCAL 0x04000000
+#define SHF_MIPS_NAMES 0x02000000
+#define SHF_MIPS_NODUPE 0x01000000
+
+/* Symbol tables. */
+
+/* MIPS specific values for `st_other'. */
+#define STO_MIPS_DEFAULT 0x0
+#define STO_MIPS_INTERNAL 0x1
+#define STO_MIPS_HIDDEN 0x2
+#define STO_MIPS_PROTECTED 0x3
+#define STO_MIPS_SC_ALIGN_UNUSED 0xff
+
+/* MIPS specific values for `st_info'. */
+#define STB_MIPS_SPLIT_COMMON 13
+
+/* Entries found in sections of type SHT_MIPS_GPTAB. */
+
+typedef union {
+ struct
+ {
+ Elf32_Word gt_current_g_value; /* -G value used for compilation */
+ Elf32_Word gt_unused; /* Not used */
+ } gt_header; /* First entry in section */
+ struct
+ {
+ Elf32_Word gt_g_value; /* If this value were used for -G */
+ Elf32_Word gt_bytes; /* This many bytes would be used */
+ } gt_entry; /* Subsequent entries in section */
+} Elf32_gptab;
+
+/* Entry found in sections of type SHT_MIPS_REGINFO. */
+
+typedef struct
+{
+ Elf32_Word ri_gprmask; /* General registers used */
+ Elf32_Word ri_cprmask[4]; /* Coprocessor registers used */
+ Elf32_Sword ri_gp_value; /* $gp register value */
+} Elf32_RegInfo;
+
+/* Entries found in sections of type SHT_MIPS_OPTIONS. */
+
+typedef struct
+{
+ unsigned char kind; /* Determines interpretation of the
+ variable part of descriptor. */
+ unsigned char size; /* Size of descriptor, including header. */
+ Elf32_Section section; /* Section header index of section affected,
+ 0 for global options. */
+ Elf32_Word info; /* Kind-specific information. */
+} Elf_Options;
+
+/* Values for `kind' field in Elf_Options. */
+
+#define ODK_NULL 0 /* Undefined. */
+#define ODK_REGINFO 1 /* Register usage information. */
+#define ODK_EXCEPTIONS 2 /* Exception processing options. */
+#define ODK_PAD 3 /* Section padding options. */
+#define ODK_HWPATCH 4 /* Hardware workarounds performed */
+#define ODK_FILL 5 /* record the fill value used by the linker. */
+#define ODK_TAGS 6 /* reserve space for desktop tools to write. */
+#define ODK_HWAND 7 /* HW workarounds. 'AND' bits when merging. */
+#define ODK_HWOR 8 /* HW workarounds. 'OR' bits when merging. */
+
+/* Values for `info' in Elf_Options for ODK_EXCEPTIONS entries. */
+
+#define OEX_FPU_MIN 0x1f /* FPE's which MUST be enabled. */
+#define OEX_FPU_MAX 0x1f00 /* FPE's which MAY be enabled. */
+#define OEX_PAGE0 0x10000 /* page zero must be mapped. */
+#define OEX_SMM 0x20000 /* Force sequential memory mode? */
+#define OEX_FPDBUG 0x40000 /* Force floating point debug mode? */
+#define OEX_PRECISEFP OEX_FPDBUG
+#define OEX_DISMISS 0x80000 /* Dismiss invalid address faults? */
+
+#define OEX_FPU_INVAL 0x10
+#define OEX_FPU_DIV0 0x08
+#define OEX_FPU_OFLO 0x04
+#define OEX_FPU_UFLO 0x02
+#define OEX_FPU_INEX 0x01
+
+/* Masks for `info' in Elf_Options for an ODK_HWPATCH entry. */
+
+#define OHW_R4KEOP 0x1 /* R4000 end-of-page patch. */
+#define OHW_R8KPFETCH 0x2 /* may need R8000 prefetch patch. */
+#define OHW_R5KEOP 0x4 /* R5000 end-of-page patch. */
+#define OHW_R5KCVTL 0x8 /* R5000 cvt.[ds].l bug. clean=1. */
+
+#define OPAD_PREFIX 0x1
+#define OPAD_POSTFIX 0x2
+#define OPAD_SYMBOL 0x4
+
+/* Entry found in `.options' section. */
+
+typedef struct
+{
+ Elf32_Word hwp_flags1; /* Extra flags. */
+ Elf32_Word hwp_flags2; /* Extra flags. */
+} Elf_Options_Hw;
+
+/* Masks for `info' in ElfOptions for ODK_HWAND and ODK_HWOR entries. */
+
+#define OHWA0_R4KEOP_CHECKED 0x00000001
+#define OHWA1_R4KEOP_CLEAN 0x00000002
+
+/* MIPS relocs. */
+
+#define R_MIPS_NONE 0 /* No reloc */
+#define R_MIPS_16 1 /* Direct 16 bit */
+#define R_MIPS_32 2 /* Direct 32 bit */
+#define R_MIPS_REL32 3 /* PC relative 32 bit */
+#define R_MIPS_26 4 /* Direct 26 bit shifted */
+#define R_MIPS_HI16 5 /* High 16 bit */
+#define R_MIPS_LO16 6 /* Low 16 bit */
+#define R_MIPS_GPREL16 7 /* GP relative 16 bit */
+#define R_MIPS_LITERAL 8 /* 16 bit literal entry */
+#define R_MIPS_GOT16 9 /* 16 bit GOT entry */
+#define R_MIPS_PC16 10 /* PC relative 16 bit */
+#define R_MIPS_CALL16 11 /* 16 bit GOT entry for function */
+#define R_MIPS_GPREL32 12 /* GP relative 32 bit */
+
+#define R_MIPS_SHIFT5 16
+#define R_MIPS_SHIFT6 17
+#define R_MIPS_64 18
+#define R_MIPS_GOT_DISP 19
+#define R_MIPS_GOT_PAGE 20
+#define R_MIPS_GOT_OFST 21
+#define R_MIPS_GOT_HI16 22
+#define R_MIPS_GOT_LO16 23
+#define R_MIPS_SUB 24
+#define R_MIPS_INSERT_A 25
+#define R_MIPS_INSERT_B 26
+#define R_MIPS_DELETE 27
+#define R_MIPS_HIGHER 28
+#define R_MIPS_HIGHEST 29
+#define R_MIPS_CALL_HI16 30
+#define R_MIPS_CALL_LO16 31
+#define R_MIPS_SCN_DISP 32
+#define R_MIPS_REL16 33
+#define R_MIPS_ADD_IMMEDIATE 34
+#define R_MIPS_PJUMP 35
+#define R_MIPS_RELGOT 36
+#define R_MIPS_JALR 37
+/* Keep this the last entry. */
+#define R_MIPS_NUM 38
+
+/* Legal values for p_type field of Elf32_Phdr. */
+
+#define PT_MIPS_REGINFO 0x70000000 /* Register usage information */
+#define PT_MIPS_RTPROC 0x70000001 /* Runtime procedure table. */
+#define PT_MIPS_OPTIONS 0x70000002
+
+/* Special program header types. */
+
+#define PF_MIPS_LOCAL 0x10000000
+
+/* Legal values for d_tag field of Elf32_Dyn. */
+
+#define DT_MIPS_RLD_VERSION 0x70000001 /* Runtime linker interface version */
+#define DT_MIPS_TIME_STAMP 0x70000002 /* Timestamp */
+#define DT_MIPS_ICHECKSUM 0x70000003 /* Checksum */
+#define DT_MIPS_IVERSION 0x70000004 /* Version string (string tbl index) */
+#define DT_MIPS_FLAGS 0x70000005 /* Flags */
+#define DT_MIPS_BASE_ADDRESS 0x70000006 /* Base address */
+#define DT_MIPS_MSYM 0x70000007
+#define DT_MIPS_CONFLICT 0x70000008 /* Address of CONFLICT section */
+#define DT_MIPS_LIBLIST 0x70000009 /* Address of LIBLIST section */
+#define DT_MIPS_LOCAL_GOTNO 0x7000000a /* Number of local GOT entries */
+#define DT_MIPS_CONFLICTNO 0x7000000b /* Number of CONFLICT entries */
+#define DT_MIPS_LIBLISTNO 0x70000010 /* Number of LIBLIST entries */
+#define DT_MIPS_SYMTABNO 0x70000011 /* Number of DYNSYM entries */
+#define DT_MIPS_UNREFEXTNO 0x70000012 /* First external DYNSYM */
+#define DT_MIPS_GOTSYM 0x70000013 /* First GOT entry in DYNSYM */
+#define DT_MIPS_HIPAGENO 0x70000014 /* Number of GOT page table entries */
+#define DT_MIPS_RLD_MAP 0x70000016 /* Address of run time loader map. */
+#define DT_MIPS_DELTA_CLASS 0x70000017 /* Delta C++ class definition. */
+#define DT_MIPS_DELTA_CLASS_NO \
+ 0x70000018 /* Number of entries in \
+DT_MIPS_DELTA_CLASS. */
+#define DT_MIPS_DELTA_INSTANCE 0x70000019 /* Delta C++ class instances. */
+#define DT_MIPS_DELTA_INSTANCE_NO \
+ 0x7000001a /* Number of entries in \
+DT_MIPS_DELTA_INSTANCE. */
+#define DT_MIPS_DELTA_RELOC 0x7000001b /* Delta relocations. */
+#define DT_MIPS_DELTA_RELOC_NO \
+ 0x7000001c /* Number of entries in \
+DT_MIPS_DELTA_RELOC. */
+#define DT_MIPS_DELTA_SYM \
+ 0x7000001d /* Delta symbols that Delta \
+relocations refer to. */
+#define DT_MIPS_DELTA_SYM_NO \
+ 0x7000001e /* Number of entries in \
+DT_MIPS_DELTA_SYM. */
+#define DT_MIPS_DELTA_CLASSSYM \
+ 0x70000020 /* Delta symbols that hold the \
+class declaration. */
+#define DT_MIPS_DELTA_CLASSSYM_NO \
+ 0x70000021 /* Number of entries in \
+DT_MIPS_DELTA_CLASSSYM. */
+#define DT_MIPS_CXX_FLAGS 0x70000022 /* Flags indicating for C++ flavor. */
+#define DT_MIPS_PIXIE_INIT 0x70000023
+#define DT_MIPS_SYMBOL_LIB 0x70000024
+#define DT_MIPS_LOCALPAGE_GOTIDX 0x70000025
+#define DT_MIPS_LOCAL_GOTIDX 0x70000026
+#define DT_MIPS_HIDDEN_GOTIDX 0x70000027
+#define DT_MIPS_PROTECTED_GOTIDX 0x70000028
+#define DT_MIPS_OPTIONS 0x70000029 /* Address of .options. */
+#define DT_MIPS_INTERFACE 0x7000002a /* Address of .interface. */
+#define DT_MIPS_DYNSTR_ALIGN 0x7000002b
+#define DT_MIPS_INTERFACE_SIZE 0x7000002c /* Size of the .interface section. \
+ */
+#define DT_MIPS_RLD_TEXT_RESOLVE_ADDR \
+ 0x7000002d /* Address of rld_text_rsolve \
+function stored in GOT. */
+#define DT_MIPS_PERF_SUFFIX \
+ 0x7000002e /* Default suffix of dso to be added \
+ by rld on dlopen() calls. */
+#define DT_MIPS_COMPACT_SIZE 0x7000002f /* (O32)Size of compact rel section. \
+ */
+#define DT_MIPS_GP_VALUE 0x70000030 /* GP value for aux GOTs. */
+#define DT_MIPS_AUX_DYNAMIC 0x70000031 /* Address of aux .dynamic. */
+#define DT_MIPS_NUM 0x32
+
+/* Legal values for DT_MIPS_FLAGS Elf32_Dyn entry. */
+
+#define RHF_NONE 0 /* No flags */
+#define RHF_QUICKSTART (1 << 0) /* Use quickstart */
+#define RHF_NOTPOT (1 << 1) /* Hash size not power of 2 */
+#define RHF_NO_LIBRARY_REPLACEMENT (1 << 2) /* Ignore LD_LIBRARY_PATH */
+#define RHF_NO_MOVE (1 << 3)
+#define RHF_SGI_ONLY (1 << 4)
+#define RHF_GUARANTEE_INIT (1 << 5)
+#define RHF_DELTA_C_PLUS_PLUS (1 << 6)
+#define RHF_GUARANTEE_START_INIT (1 << 7)
+#define RHF_PIXIE (1 << 8)
+#define RHF_DEFAULT_DELAY_LOAD (1 << 9)
+#define RHF_REQUICKSTART (1 << 10)
+#define RHF_REQUICKSTARTED (1 << 11)
+#define RHF_CORD (1 << 12)
+#define RHF_NO_UNRES_UNDEF (1 << 13)
+#define RHF_RLD_ORDER_SAFE (1 << 14)
+
+/* Entries found in sections of type SHT_MIPS_LIBLIST. */
+
+typedef struct
+{
+ Elf32_Word l_name; /* Name (string table index) */
+ Elf32_Word l_time_stamp; /* Timestamp */
+ Elf32_Word l_checksum; /* Checksum */
+ Elf32_Word l_version; /* Interface version */
+ Elf32_Word l_flags; /* Flags */
+} Elf32_Lib;
+
+typedef struct
+{
+ Elf64_Word l_name; /* Name (string table index) */
+ Elf64_Word l_time_stamp; /* Timestamp */
+ Elf64_Word l_checksum; /* Checksum */
+ Elf64_Word l_version; /* Interface version */
+ Elf64_Word l_flags; /* Flags */
+} Elf64_Lib;
+
+/* Legal values for l_flags. */
+
+#define LL_NONE 0
+#define LL_EXACT_MATCH (1 << 0) /* Require exact match */
+#define LL_IGNORE_INT_VER (1 << 1) /* Ignore interface version */
+#define LL_REQUIRE_MINOR (1 << 2)
+#define LL_EXPORTS (1 << 3)
+#define LL_DELAY_LOAD (1 << 4)
+#define LL_DELTA (1 << 5)
+
+/* Entries found in sections of type SHT_MIPS_CONFLICT. */
+
+typedef Elf32_Addr Elf32_Conflict;
+
+/* HPPA specific definitions. */
+
+/* Legal values for e_flags field of Elf32_Ehdr. */
+
+#define EF_PARISC_TRAPNIL 0x00010000 /* Trap nil pointer dereference. */
+#define EF_PARISC_EXT 0x00020000 /* Program uses arch. extensions. */
+#define EF_PARISC_LSB 0x00040000 /* Program expects little endian. */
+#define EF_PARISC_WIDE 0x00080000 /* Program expects wide mode. */
+#define EF_PARISC_NO_KABP \
+ 0x00100000 /* No kernel assisted branch \
+prediction. */
+#define EF_PARISC_LAZYSWAP 0x00400000 /* Allow lazy swapping. */
+#define EF_PARISC_ARCH 0x0000ffff /* Architecture version. */
+
+/* Defined values for `e_flags & EF_PARISC_ARCH' are: */
+
+#define EFA_PARISC_1_0 0x020b /* PA-RISC 1.0 big-endian. */
+#define EFA_PARISC_1_1 0x0210 /* PA-RISC 1.1 big-endian. */
+#define EFA_PARISC_2_0 0x0214 /* PA-RISC 2.0 big-endian. */
+
+/* Additional section indeces. */
+
+#define SHN_PARISC_ANSI_COMMON \
+ 0xff00 /* Section for tenatively declared \
+symbols in ANSI C. */
+#define SHN_PARISC_HUGE_COMMON 0xff01 /* Common blocks in huge model. */
+
+/* Legal values for sh_type field of Elf32_Shdr. */
+
+#define SHT_PARISC_EXT 0x70000000 /* Contains product specific ext. */
+#define SHT_PARISC_UNWIND 0x70000001 /* Unwind information. */
+#define SHT_PARISC_DOC 0x70000002 /* Debug info for optimized code. */
+
+/* Legal values for sh_flags field of Elf32_Shdr. */
+
+#define SHF_PARISC_SHORT 0x20000000 /* Section with short addressing. */
+#define SHF_PARISC_HUGE 0x40000000 /* Section far from gp. */
+#define SHF_PARISC_SBP 0x80000000 /* Static branch prediction code. */
+
+/* Legal values for ST_TYPE subfield of st_info (symbol type). */
+
+#define STT_PARISC_MILLICODE 13 /* Millicode function entry point. */
+
+#define STT_HP_OPAQUE (STT_LOOS + 0x1)
+#define STT_HP_STUB (STT_LOOS + 0x2)
+
+/* HPPA relocs. */
+
+#define R_PARISC_NONE 0 /* No reloc. */
+#define R_PARISC_DIR32 1 /* Direct 32-bit reference. */
+#define R_PARISC_DIR21L 2 /* Left 21 bits of eff. address. */
+#define R_PARISC_DIR17R 3 /* Right 17 bits of eff. address. */
+#define R_PARISC_DIR17F 4 /* 17 bits of eff. address. */
+#define R_PARISC_DIR14R 6 /* Right 14 bits of eff. address. */
+#define R_PARISC_PCREL32 9 /* 32-bit rel. address. */
+#define R_PARISC_PCREL21L 10 /* Left 21 bits of rel. address. */
+#define R_PARISC_PCREL17R 11 /* Right 17 bits of rel. address. */
+#define R_PARISC_PCREL17F 12 /* 17 bits of rel. address. */
+#define R_PARISC_PCREL14R 14 /* Right 14 bits of rel. address. */
+#define R_PARISC_DPREL21L 18 /* Left 21 bits of rel. address. */
+#define R_PARISC_DPREL14R 22 /* Right 14 bits of rel. address. */
+#define R_PARISC_GPREL21L 26 /* GP-relative, left 21 bits. */
+#define R_PARISC_GPREL14R 30 /* GP-relative, right 14 bits. */
+#define R_PARISC_LTOFF21L 34 /* LT-relative, left 21 bits. */
+#define R_PARISC_LTOFF14R 38 /* LT-relative, right 14 bits. */
+#define R_PARISC_SECREL32 41 /* 32 bits section rel. address. */
+#define R_PARISC_SEGBASE 48 /* No relocation, set segment base. */
+#define R_PARISC_SEGREL32 49 /* 32 bits segment rel. address. */
+#define R_PARISC_PLTOFF21L 50 /* PLT rel. address, left 21 bits. */
+#define R_PARISC_PLTOFF14R 54 /* PLT rel. address, right 14 bits. */
+#define R_PARISC_LTOFF_FPTR32 57 /* 32 bits LT-rel. function pointer. */
+#define R_PARISC_LTOFF_FPTR21L 58 /* LT-rel. fct ptr, left 21 bits. */
+#define R_PARISC_LTOFF_FPTR14R 62 /* LT-rel. fct ptr, right 14 bits. */
+#define R_PARISC_FPTR64 64 /* 64 bits function address. */
+#define R_PARISC_PLABEL32 65 /* 32 bits function address. */
+#define R_PARISC_PLABEL21L 66 /* Left 21 bits of fct ptr. */
+#define R_PARISC_PLABEL14R 70 /* Left 21 bits of fct ptr. */
+#define R_PARISC_PCREL64 72 /* 64 bits PC-rel. address. */
+#define R_PARISC_PCREL22F 74 /* 22 bits PC-rel. address. */
+#define R_PARISC_PCREL14WR 75 /* PC-rel. address, right 14 bits. */
+#define R_PARISC_PCREL14DR 76 /* PC rel. address, right 14 bits. */
+#define R_PARISC_PCREL16F 77 /* 16 bits PC-rel. address. */
+#define R_PARISC_PCREL16WF 78 /* 16 bits PC-rel. address. */
+#define R_PARISC_PCREL16DF 79 /* 16 bits PC-rel. address. */
+#define R_PARISC_DIR64 80 /* 64 bits of eff. address. */
+#define R_PARISC_DIR14WR 83 /* 14 bits of eff. address. */
+#define R_PARISC_DIR14DR 84 /* 14 bits of eff. address. */
+#define R_PARISC_DIR16F 85 /* 16 bits of eff. address. */
+#define R_PARISC_DIR16WF 86 /* 16 bits of eff. address. */
+#define R_PARISC_DIR16DF 87 /* 16 bits of eff. address. */
+#define R_PARISC_GPREL64 88 /* 64 bits of GP-rel. address. */
+#define R_PARISC_GPREL14WR 91 /* GP-rel. address, right 14 bits. */
+#define R_PARISC_GPREL14DR 92 /* GP-rel. address, right 14 bits. */
+#define R_PARISC_GPREL16F 93 /* 16 bits GP-rel. address. */
+#define R_PARISC_GPREL16WF 94 /* 16 bits GP-rel. address. */
+#define R_PARISC_GPREL16DF 95 /* 16 bits GP-rel. address. */
+#define R_PARISC_LTOFF64 96 /* 64 bits LT-rel. address. */
+#define R_PARISC_LTOFF14WR 99 /* LT-rel. address, right 14 bits. */
+#define R_PARISC_LTOFF14DR 100 /* LT-rel. address, right 14 bits. */
+#define R_PARISC_LTOFF16F 101 /* 16 bits LT-rel. address. */
+#define R_PARISC_LTOFF16WF 102 /* 16 bits LT-rel. address. */
+#define R_PARISC_LTOFF16DF 103 /* 16 bits LT-rel. address. */
+#define R_PARISC_SECREL64 104 /* 64 bits section rel. address. */
+#define R_PARISC_SEGREL64 112 /* 64 bits segment rel. address. */
+#define R_PARISC_PLTOFF14WR 115 /* PLT-rel. address, right 14 bits. */
+#define R_PARISC_PLTOFF14DR 116 /* PLT-rel. address, right 14 bits. */
+#define R_PARISC_PLTOFF16F 117 /* 16 bits LT-rel. address. */
+#define R_PARISC_PLTOFF16WF 118 /* 16 bits PLT-rel. address. */
+#define R_PARISC_PLTOFF16DF 119 /* 16 bits PLT-rel. address. */
+#define R_PARISC_LTOFF_FPTR64 120 /* 64 bits LT-rel. function ptr. */
+#define R_PARISC_LTOFF_FPTR14WR 123 /* LT-rel. fct. ptr., right 14 bits. */
+#define R_PARISC_LTOFF_FPTR14DR 124 /* LT-rel. fct. ptr., right 14 bits. */
+#define R_PARISC_LTOFF_FPTR16F 125 /* 16 bits LT-rel. function ptr. */
+#define R_PARISC_LTOFF_FPTR16WF 126 /* 16 bits LT-rel. function ptr. */
+#define R_PARISC_LTOFF_FPTR16DF 127 /* 16 bits LT-rel. function ptr. */
+#define R_PARISC_LORESERVE 128
+#define R_PARISC_COPY 128 /* Copy relocation. */
+#define R_PARISC_IPLT 129 /* Dynamic reloc, imported PLT */
+#define R_PARISC_EPLT 130 /* Dynamic reloc, exported PLT */
+#define R_PARISC_TPREL32 153 /* 32 bits TP-rel. address. */
+#define R_PARISC_TPREL21L 154 /* TP-rel. address, left 21 bits. */
+#define R_PARISC_TPREL14R 158 /* TP-rel. address, right 14 bits. */
+#define R_PARISC_LTOFF_TP21L 162 /* LT-TP-rel. address, left 21 bits. */
+#define R_PARISC_LTOFF_TP14R 166 /* LT-TP-rel. address, right 14 bits.*/
+#define R_PARISC_LTOFF_TP14F 167 /* 14 bits LT-TP-rel. address. */
+#define R_PARISC_TPREL64 216 /* 64 bits TP-rel. address. */
+#define R_PARISC_TPREL14WR 219 /* TP-rel. address, right 14 bits. */
+#define R_PARISC_TPREL14DR 220 /* TP-rel. address, right 14 bits. */
+#define R_PARISC_TPREL16F 221 /* 16 bits TP-rel. address. */
+#define R_PARISC_TPREL16WF 222 /* 16 bits TP-rel. address. */
+#define R_PARISC_TPREL16DF 223 /* 16 bits TP-rel. address. */
+#define R_PARISC_LTOFF_TP64 224 /* 64 bits LT-TP-rel. address. */
+#define R_PARISC_LTOFF_TP14WR 227 /* LT-TP-rel. address, right 14 bits.*/
+#define R_PARISC_LTOFF_TP14DR 228 /* LT-TP-rel. address, right 14 bits.*/
+#define R_PARISC_LTOFF_TP16F 229 /* 16 bits LT-TP-rel. address. */
+#define R_PARISC_LTOFF_TP16WF 230 /* 16 bits LT-TP-rel. address. */
+#define R_PARISC_LTOFF_TP16DF 231 /* 16 bits LT-TP-rel. address. */
+#define R_PARISC_HIRESERVE 255
+
+/* Legal values for p_type field of Elf32_Phdr/Elf64_Phdr. */
+
+#define PT_HP_TLS (PT_LOOS + 0x0)
+#define PT_HP_CORE_NONE (PT_LOOS + 0x1)
+#define PT_HP_CORE_VERSION (PT_LOOS + 0x2)
+#define PT_HP_CORE_KERNEL (PT_LOOS + 0x3)
+#define PT_HP_CORE_COMM (PT_LOOS + 0x4)
+#define PT_HP_CORE_PROC (PT_LOOS + 0x5)
+#define PT_HP_CORE_LOADABLE (PT_LOOS + 0x6)
+#define PT_HP_CORE_STACK (PT_LOOS + 0x7)
+#define PT_HP_CORE_SHM (PT_LOOS + 0x8)
+#define PT_HP_CORE_MMF (PT_LOOS + 0x9)
+#define PT_HP_PARALLEL (PT_LOOS + 0x10)
+#define PT_HP_FASTBIND (PT_LOOS + 0x11)
+#define PT_HP_OPT_ANNOT (PT_LOOS + 0x12)
+#define PT_HP_HSL_ANNOT (PT_LOOS + 0x13)
+#define PT_HP_STACK (PT_LOOS + 0x14)
+
+#define PT_PARISC_ARCHEXT 0x70000000
+#define PT_PARISC_UNWIND 0x70000001
+
+/* Legal values for p_flags field of Elf32_Phdr/Elf64_Phdr. */
+
+#define PF_PARISC_SBP 0x08000000
+
+#define PF_HP_PAGE_SIZE 0x00100000
+#define PF_HP_FAR_SHARED 0x00200000
+#define PF_HP_NEAR_SHARED 0x00400000
+#define PF_HP_CODE 0x01000000
+#define PF_HP_MODIFY 0x02000000
+#define PF_HP_LAZYSWAP 0x04000000
+#define PF_HP_SBP 0x08000000
+
+/* Alpha specific definitions. */
+
+/* Legal values for e_flags field of Elf64_Ehdr. */
+
+#define EF_ALPHA_32BIT 1 /* All addresses must be < 2GB. */
+#define EF_ALPHA_CANRELAX 2 /* Relocations for relaxing exist. */
+
+/* Legal values for sh_type field of Elf64_Shdr. */
+
+/* These two are primerily concerned with ECOFF debugging info. */
+#define SHT_ALPHA_DEBUG 0x70000001
+#define SHT_ALPHA_REGINFO 0x70000002
+
+/* Legal values for sh_flags field of Elf64_Shdr. */
+
+#define SHF_ALPHA_GPREL 0x10000000
+
+/* Legal values for st_other field of Elf64_Sym. */
+#define STO_ALPHA_NOPV 0x80 /* No PV required. */
+#define STO_ALPHA_STD_GPLOAD 0x88 /* PV only used for initial ldgp. */
+
+/* Alpha relocs. */
+
+#define R_ALPHA_NONE 0 /* No reloc */
+#define R_ALPHA_REFLONG 1 /* Direct 32 bit */
+#define R_ALPHA_REFQUAD 2 /* Direct 64 bit */
+#define R_ALPHA_GPREL32 3 /* GP relative 32 bit */
+#define R_ALPHA_LITERAL 4 /* GP relative 16 bit w/optimization */
+#define R_ALPHA_LITUSE 5 /* Optimization hint for LITERAL */
+#define R_ALPHA_GPDISP 6 /* Add displacement to GP */
+#define R_ALPHA_BRADDR 7 /* PC+4 relative 23 bit shifted */
+#define R_ALPHA_HINT 8 /* PC+4 relative 16 bit shifted */
+#define R_ALPHA_SREL16 9 /* PC relative 16 bit */
+#define R_ALPHA_SREL32 10 /* PC relative 32 bit */
+#define R_ALPHA_SREL64 11 /* PC relative 64 bit */
+#define R_ALPHA_GPRELHIGH 17 /* GP relative 32 bit, high 16 bits */
+#define R_ALPHA_GPRELLOW 18 /* GP relative 32 bit, low 16 bits */
+#define R_ALPHA_GPREL16 19 /* GP relative 16 bit */
+#define R_ALPHA_COPY 24 /* Copy symbol at runtime */
+#define R_ALPHA_GLOB_DAT 25 /* Create GOT entry */
+#define R_ALPHA_JMP_SLOT 26 /* Create PLT entry */
+#define R_ALPHA_RELATIVE 27 /* Adjust by program base */
+#define R_ALPHA_TLS_GD_HI 28
+#define R_ALPHA_TLSGD 29
+#define R_ALPHA_TLS_LDM 30
+#define R_ALPHA_DTPMOD64 31
+#define R_ALPHA_GOTDTPREL 32
+#define R_ALPHA_DTPREL64 33
+#define R_ALPHA_DTPRELHI 34
+#define R_ALPHA_DTPRELLO 35
+#define R_ALPHA_DTPREL16 36
+#define R_ALPHA_GOTTPREL 37
+#define R_ALPHA_TPREL64 38
+#define R_ALPHA_TPRELHI 39
+#define R_ALPHA_TPRELLO 40
+#define R_ALPHA_TPREL16 41
+/* Keep this the last entry. */
+#define R_ALPHA_NUM 46
+
+/* Magic values of the LITUSE relocation addend. */
+#define LITUSE_ALPHA_ADDR 0
+#define LITUSE_ALPHA_BASE 1
+#define LITUSE_ALPHA_BYTOFF 2
+#define LITUSE_ALPHA_JSR 3
+#define LITUSE_ALPHA_TLS_GD 4
+#define LITUSE_ALPHA_TLS_LDM 5
+
+/* PowerPC specific declarations */
+
+/* Values for Elf32/64_Ehdr.e_flags. */
+#define EF_PPC_EMB 0x80000000 /* PowerPC embedded flag */
+
+/* Cygnus local bits below */
+#define EF_PPC_RELOCATABLE 0x00010000 /* PowerPC -mrelocatable flag*/
+#define EF_PPC_RELOCATABLE_LIB \
+ 0x00008000 /* PowerPC -mrelocatable-lib \
+flag */
+
+/* PowerPC relocations defined by the ABIs */
+#define R_PPC_NONE 0
+#define R_PPC_ADDR32 1 /* 32bit absolute address */
+#define R_PPC_ADDR24 2 /* 26bit address, 2 bits ignored. */
+#define R_PPC_ADDR16 3 /* 16bit absolute address */
+#define R_PPC_ADDR16_LO 4 /* lower 16bit of absolute address */
+#define R_PPC_ADDR16_HI 5 /* high 16bit of absolute address */
+#define R_PPC_ADDR16_HA 6 /* adjusted high 16bit */
+#define R_PPC_ADDR14 7 /* 16bit address, 2 bits ignored */
+#define R_PPC_ADDR14_BRTAKEN 8
+#define R_PPC_ADDR14_BRNTAKEN 9
+#define R_PPC_REL24 10 /* PC relative 26 bit */
+#define R_PPC_REL14 11 /* PC relative 16 bit */
+#define R_PPC_REL14_BRTAKEN 12
+#define R_PPC_REL14_BRNTAKEN 13
+#define R_PPC_GOT16 14
+#define R_PPC_GOT16_LO 15
+#define R_PPC_GOT16_HI 16
+#define R_PPC_GOT16_HA 17
+#define R_PPC_PLTREL24 18
+#define R_PPC_COPY 19
+#define R_PPC_GLOB_DAT 20
+#define R_PPC_JMP_SLOT 21
+#define R_PPC_RELATIVE 22
+#define R_PPC_LOCAL24PC 23
+#define R_PPC_UADDR32 24
+#define R_PPC_UADDR16 25
+#define R_PPC_REL32 26
+#define R_PPC_PLT32 27
+#define R_PPC_PLTREL32 28
+#define R_PPC_PLT16_LO 29
+#define R_PPC_PLT16_HI 30
+#define R_PPC_PLT16_HA 31
+#define R_PPC_SDAREL16 32
+#define R_PPC_SECTOFF 33
+#define R_PPC_SECTOFF_LO 34
+#define R_PPC_SECTOFF_HI 35
+#define R_PPC_SECTOFF_HA 36
+
+/* PowerPC relocations defined for the TLS access ABI. */
+#define R_PPC_TLS 67 /* none (sym+add)@tls */
+#define R_PPC_DTPMOD32 68 /* word32 (sym+add)@dtpmod */
+#define R_PPC_TPREL16 69 /* half16* (sym+add)@tprel */
+#define R_PPC_TPREL16_LO 70 /* half16 (sym+add)@tprel@l */
+#define R_PPC_TPREL16_HI 71 /* half16 (sym+add)@tprel@h */
+#define R_PPC_TPREL16_HA 72 /* half16 (sym+add)@tprel@ha */
+#define R_PPC_TPREL32 73 /* word32 (sym+add)@tprel */
+#define R_PPC_DTPREL16 74 /* half16* (sym+add)@dtprel */
+#define R_PPC_DTPREL16_LO 75 /* half16 (sym+add)@dtprel@l */
+#define R_PPC_DTPREL16_HI 76 /* half16 (sym+add)@dtprel@h */
+#define R_PPC_DTPREL16_HA 77 /* half16 (sym+add)@dtprel@ha */
+#define R_PPC_DTPREL32 78 /* word32 (sym+add)@dtprel */
+#define R_PPC_GOT_TLSGD16 79 /* half16* (sym+add)@got@tlsgd */
+#define R_PPC_GOT_TLSGD16_LO 80 /* half16 (sym+add)@got@tlsgd@l */
+#define R_PPC_GOT_TLSGD16_HI 81 /* half16 (sym+add)@got@tlsgd@h */
+#define R_PPC_GOT_TLSGD16_HA 82 /* half16 (sym+add)@got@tlsgd@ha */
+#define R_PPC_GOT_TLSLD16 83 /* half16* (sym+add)@got@tlsld */
+#define R_PPC_GOT_TLSLD16_LO 84 /* half16 (sym+add)@got@tlsld@l */
+#define R_PPC_GOT_TLSLD16_HI 85 /* half16 (sym+add)@got@tlsld@h */
+#define R_PPC_GOT_TLSLD16_HA 86 /* half16 (sym+add)@got@tlsld@ha */
+#define R_PPC_GOT_TPREL16 87 /* half16* (sym+add)@got@tprel */
+#define R_PPC_GOT_TPREL16_LO 88 /* half16 (sym+add)@got@tprel@l */
+#define R_PPC_GOT_TPREL16_HI 89 /* half16 (sym+add)@got@tprel@h */
+#define R_PPC_GOT_TPREL16_HA 90 /* half16 (sym+add)@got@tprel@ha */
+#define R_PPC_GOT_DTPREL16 91 /* half16* (sym+add)@got@dtprel */
+#define R_PPC_GOT_DTPREL16_LO 92 /* half16* (sym+add)@got@dtprel@l */
+#define R_PPC_GOT_DTPREL16_HI 93 /* half16* (sym+add)@got@dtprel@h */
+#define R_PPC_GOT_DTPREL16_HA 94 /* half16* (sym+add)@got@dtprel@ha */
+
+/* Keep this the last entry. */
+#define R_PPC_NUM 95
+
+/* The remaining relocs are from the Embedded ELF ABI, and are not
+ in the SVR4 ELF ABI. */
+#define R_PPC_EMB_NADDR32 101
+#define R_PPC_EMB_NADDR16 102
+#define R_PPC_EMB_NADDR16_LO 103
+#define R_PPC_EMB_NADDR16_HI 104
+#define R_PPC_EMB_NADDR16_HA 105
+#define R_PPC_EMB_SDAI16 106
+#define R_PPC_EMB_SDA2I16 107
+#define R_PPC_EMB_SDA2REL 108
+#define R_PPC_EMB_SDA21 109 /* 16 bit offset in SDA */
+#define R_PPC_EMB_MRKREF 110
+#define R_PPC_EMB_RELSEC16 111
+#define R_PPC_EMB_RELST_LO 112
+#define R_PPC_EMB_RELST_HI 113
+#define R_PPC_EMB_RELST_HA 114
+#define R_PPC_EMB_BIT_FLD 115
+#define R_PPC_EMB_RELSDA 116 /* 16 bit relative offset in SDA */
+
+/* Diab tool relocations. */
+#define R_PPC_DIAB_SDA21_LO 180 /* like EMB_SDA21, but lower 16 bit */
+#define R_PPC_DIAB_SDA21_HI 181 /* like EMB_SDA21, but high 16 bit */
+#define R_PPC_DIAB_SDA21_HA 182 /* like EMB_SDA21, adjusted high 16 */
+#define R_PPC_DIAB_RELSDA_LO 183 /* like EMB_RELSDA, but lower 16 bit */
+#define R_PPC_DIAB_RELSDA_HI 184 /* like EMB_RELSDA, but high 16 bit */
+#define R_PPC_DIAB_RELSDA_HA 185 /* like EMB_RELSDA, adjusted high 16 */
+
+/* This is a phony reloc to handle any old fashioned TOC16 references
+ that may still be in object files. */
+#define R_PPC_TOC16 255
+
+/* PowerPC64 relocations defined by the ABIs */
+#define R_PPC64_NONE R_PPC_NONE
+#define R_PPC64_ADDR32 R_PPC_ADDR32 /* 32bit absolute address */
+#define R_PPC64_ADDR24 R_PPC_ADDR24 /* 26bit address, word aligned */
+#define R_PPC64_ADDR16 R_PPC_ADDR16 /* 16bit absolute address */
+#define R_PPC64_ADDR16_LO R_PPC_ADDR16_LO /* lower 16bits of address */
+#define R_PPC64_ADDR16_HI R_PPC_ADDR16_HI /* high 16bits of address. */
+#define R_PPC64_ADDR16_HA R_PPC_ADDR16_HA /* adjusted high 16bits. */
+#define R_PPC64_ADDR14 R_PPC_ADDR14 /* 16bit address, word aligned */
+#define R_PPC64_ADDR14_BRTAKEN R_PPC_ADDR14_BRTAKEN
+#define R_PPC64_ADDR14_BRNTAKEN R_PPC_ADDR14_BRNTAKEN
+#define R_PPC64_REL24 R_PPC_REL24 /* PC-rel. 26 bit, word aligned */
+#define R_PPC64_REL14 R_PPC_REL14 /* PC relative 16 bit */
+#define R_PPC64_REL14_BRTAKEN R_PPC_REL14_BRTAKEN
+#define R_PPC64_REL14_BRNTAKEN R_PPC_REL14_BRNTAKEN
+#define R_PPC64_GOT16 R_PPC_GOT16
+#define R_PPC64_GOT16_LO R_PPC_GOT16_LO
+#define R_PPC64_GOT16_HI R_PPC_GOT16_HI
+#define R_PPC64_GOT16_HA R_PPC_GOT16_HA
+
+#define R_PPC64_COPY R_PPC_COPY
+#define R_PPC64_GLOB_DAT R_PPC_GLOB_DAT
+#define R_PPC64_JMP_SLOT R_PPC_JMP_SLOT
+#define R_PPC64_RELATIVE R_PPC_RELATIVE
+
+#define R_PPC64_UADDR32 R_PPC_UADDR32
+#define R_PPC64_UADDR16 R_PPC_UADDR16
+#define R_PPC64_REL32 R_PPC_REL32
+#define R_PPC64_PLT32 R_PPC_PLT32
+#define R_PPC64_PLTREL32 R_PPC_PLTREL32
+#define R_PPC64_PLT16_LO R_PPC_PLT16_LO
+#define R_PPC64_PLT16_HI R_PPC_PLT16_HI
+#define R_PPC64_PLT16_HA R_PPC_PLT16_HA
+
+#define R_PPC64_SECTOFF R_PPC_SECTOFF
+#define R_PPC64_SECTOFF_LO R_PPC_SECTOFF_LO
+#define R_PPC64_SECTOFF_HI R_PPC_SECTOFF_HI
+#define R_PPC64_SECTOFF_HA R_PPC_SECTOFF_HA
+#define R_PPC64_ADDR30 37 /* word30 (S + A - P) >> 2 */
+#define R_PPC64_ADDR64 38 /* doubleword64 S + A */
+#define R_PPC64_ADDR16_HIGHER 39 /* half16 #higher(S + A) */
+#define R_PPC64_ADDR16_HIGHERA 40 /* half16 #highera(S + A) */
+#define R_PPC64_ADDR16_HIGHEST 41 /* half16 #highest(S + A) */
+#define R_PPC64_ADDR16_HIGHESTA 42 /* half16 #highesta(S + A) */
+#define R_PPC64_UADDR64 43 /* doubleword64 S + A */
+#define R_PPC64_REL64 44 /* doubleword64 S + A - P */
+#define R_PPC64_PLT64 45 /* doubleword64 L + A */
+#define R_PPC64_PLTREL64 46 /* doubleword64 L + A - P */
+#define R_PPC64_TOC16 47 /* half16* S + A - .TOC */
+#define R_PPC64_TOC16_LO 48 /* half16 #lo(S + A - .TOC.) */
+#define R_PPC64_TOC16_HI 49 /* half16 #hi(S + A - .TOC.) */
+#define R_PPC64_TOC16_HA 50 /* half16 #ha(S + A - .TOC.) */
+#define R_PPC64_TOC 51 /* doubleword64 .TOC */
+#define R_PPC64_PLTGOT16 52 /* half16* M + A */
+#define R_PPC64_PLTGOT16_LO 53 /* half16 #lo(M + A) */
+#define R_PPC64_PLTGOT16_HI 54 /* half16 #hi(M + A) */
+#define R_PPC64_PLTGOT16_HA 55 /* half16 #ha(M + A) */
+
+#define R_PPC64_ADDR16_DS 56 /* half16ds* (S + A) >> 2 */
+#define R_PPC64_ADDR16_LO_DS 57 /* half16ds #lo(S + A) >> 2 */
+#define R_PPC64_GOT16_DS 58 /* half16ds* (G + A) >> 2 */
+#define R_PPC64_GOT16_LO_DS 59 /* half16ds #lo(G + A) >> 2 */
+#define R_PPC64_PLT16_LO_DS 60 /* half16ds #lo(L + A) >> 2 */
+#define R_PPC64_SECTOFF_DS 61 /* half16ds* (R + A) >> 2 */
+#define R_PPC64_SECTOFF_LO_DS 62 /* half16ds #lo(R + A) >> 2 */
+#define R_PPC64_TOC16_DS 63 /* half16ds* (S + A - .TOC.) >> 2 */
+#define R_PPC64_TOC16_LO_DS 64 /* half16ds #lo(S + A - .TOC.) >> 2 */
+#define R_PPC64_PLTGOT16_DS 65 /* half16ds* (M + A) >> 2 */
+#define R_PPC64_PLTGOT16_LO_DS 66 /* half16ds #lo(M + A) >> 2 */
+
+/* PowerPC64 relocations defined for the TLS access ABI. */
+#define R_PPC64_TLS 67 /* none (sym+add)@tls */
+#define R_PPC64_DTPMOD64 68 /* doubleword64 (sym+add)@dtpmod */
+#define R_PPC64_TPREL16 69 /* half16* (sym+add)@tprel */
+#define R_PPC64_TPREL16_LO 70 /* half16 (sym+add)@tprel@l */
+#define R_PPC64_TPREL16_HI 71 /* half16 (sym+add)@tprel@h */
+#define R_PPC64_TPREL16_HA 72 /* half16 (sym+add)@tprel@ha */
+#define R_PPC64_TPREL64 73 /* doubleword64 (sym+add)@tprel */
+#define R_PPC64_DTPREL16 74 /* half16* (sym+add)@dtprel */
+#define R_PPC64_DTPREL16_LO 75 /* half16 (sym+add)@dtprel@l */
+#define R_PPC64_DTPREL16_HI 76 /* half16 (sym+add)@dtprel@h */
+#define R_PPC64_DTPREL16_HA 77 /* half16 (sym+add)@dtprel@ha */
+#define R_PPC64_DTPREL64 78 /* doubleword64 (sym+add)@dtprel */
+#define R_PPC64_GOT_TLSGD16 79 /* half16* (sym+add)@got@tlsgd */
+#define R_PPC64_GOT_TLSGD16_LO 80 /* half16 (sym+add)@got@tlsgd@l */
+#define R_PPC64_GOT_TLSGD16_HI 81 /* half16 (sym+add)@got@tlsgd@h */
+#define R_PPC64_GOT_TLSGD16_HA 82 /* half16 (sym+add)@got@tlsgd@ha */
+#define R_PPC64_GOT_TLSLD16 83 /* half16* (sym+add)@got@tlsld */
+#define R_PPC64_GOT_TLSLD16_LO 84 /* half16 (sym+add)@got@tlsld@l */
+#define R_PPC64_GOT_TLSLD16_HI 85 /* half16 (sym+add)@got@tlsld@h */
+#define R_PPC64_GOT_TLSLD16_HA 86 /* half16 (sym+add)@got@tlsld@ha */
+#define R_PPC64_GOT_TPREL16_DS 87 /* half16ds* (sym+add)@got@tprel */
+#define R_PPC64_GOT_TPREL16_LO_DS 88 /* half16ds (sym+add)@got@tprel@l */
+#define R_PPC64_GOT_TPREL16_HI 89 /* half16 (sym+add)@got@tprel@h */
+#define R_PPC64_GOT_TPREL16_HA 90 /* half16 (sym+add)@got@tprel@ha */
+#define R_PPC64_GOT_DTPREL16_DS 91 /* half16ds* (sym+add)@got@dtprel */
+#define R_PPC64_GOT_DTPREL16_LO_DS 92 /* half16ds (sym+add)@got@dtprel@l */
+#define R_PPC64_GOT_DTPREL16_HI 93 /* half16 (sym+add)@got@dtprel@h */
+#define R_PPC64_GOT_DTPREL16_HA 94 /* half16 (sym+add)@got@dtprel@ha */
+#define R_PPC64_TPREL16_DS 95 /* half16ds* (sym+add)@tprel */
+#define R_PPC64_TPREL16_LO_DS 96 /* half16ds (sym+add)@tprel@l */
+#define R_PPC64_TPREL16_HIGHER 97 /* half16 (sym+add)@tprel@higher */
+#define R_PPC64_TPREL16_HIGHERA 98 /* half16 (sym+add)@tprel@highera */
+#define R_PPC64_TPREL16_HIGHEST 99 /* half16 (sym+add)@tprel@highest */
+#define R_PPC64_TPREL16_HIGHESTA 100 /* half16 (sym+add)@tprel@highesta */
+#define R_PPC64_DTPREL16_DS 101 /* half16ds* (sym+add)@dtprel */
+#define R_PPC64_DTPREL16_LO_DS 102 /* half16ds (sym+add)@dtprel@l */
+#define R_PPC64_DTPREL16_HIGHER 103 /* half16 (sym+add)@dtprel@higher */
+#define R_PPC64_DTPREL16_HIGHERA 104 /* half16 (sym+add)@dtprel@highera */
+#define R_PPC64_DTPREL16_HIGHEST 105 /* half16 (sym+add)@dtprel@highest */
+#define R_PPC64_DTPREL16_HIGHESTA 106 /* half16 (sym+add)@dtprel@highesta */
+
+/* Keep this the last entry. */
+#define R_PPC64_NUM 107
+
+/* PowerPC64 specific values for the Dyn d_tag field. */
+#define DT_PPC64_GLINK (DT_LOPROC + 0)
+#define DT_PPC64_OPD (DT_LOPROC + 1)
+#define DT_PPC64_OPDSZ (DT_LOPROC + 2)
+#define DT_PPC64_NUM 3
+
+/* ARM specific declarations */
+
+/* Processor specific flags for the ELF header e_flags field. */
+#define EF_ARM_RELEXEC 0x01
+#define EF_ARM_HASENTRY 0x02
+#define EF_ARM_INTERWORK 0x04
+#define EF_ARM_APCS_26 0x08
+#define EF_ARM_APCS_FLOAT 0x10
+#define EF_ARM_PIC 0x20
+#define EF_ARM_ALIGN8 0x40 /* 8-bit structure alignment is in use */
+#define EF_ARM_NEW_ABI 0x80
+#define EF_ARM_OLD_ABI 0x100
+
+/* Other constants defined in the ARM ELF spec. version B-01. */
+/* NB. These conflict with values defined above. */
+#define EF_ARM_SYMSARESORTED 0x04
+#define EF_ARM_DYNSYMSUSESEGIDX 0x08
+#define EF_ARM_MAPSYMSFIRST 0x10
+#define EF_ARM_EABIMASK 0XFF000000
+
+#define EF_ARM_EABI_VERSION(flags) ((flags)&EF_ARM_EABIMASK)
+#define EF_ARM_EABI_UNKNOWN 0x00000000
+#define EF_ARM_EABI_VER1 0x01000000
+#define EF_ARM_EABI_VER2 0x02000000
+
+/* Additional symbol types for Thumb */
+#define STT_ARM_TFUNC 0xd
+
+/* ARM-specific values for sh_flags */
+#define SHF_ARM_ENTRYSECT 0x10000000 /* Section contains an entry point */
+#define SHF_ARM_COMDEF \
+ 0x80000000 /* Section may be multiply defined \
+in the input to a link step */
+
+/* ARM-specific program header flags */
+#define PF_ARM_SB \
+ 0x10000000 /* Segment contains the location \
+addressed by the static base */
+
+/* ARM relocs. */
+#define R_ARM_NONE 0 /* No reloc */
+#define R_ARM_PC24 1 /* PC relative 26 bit branch */
+#define R_ARM_ABS32 2 /* Direct 32 bit */
+#define R_ARM_REL32 3 /* PC relative 32 bit */
+#define R_ARM_PC13 4
+#define R_ARM_ABS16 5 /* Direct 16 bit */
+#define R_ARM_ABS12 6 /* Direct 12 bit */
+#define R_ARM_THM_ABS5 7
+#define R_ARM_ABS8 8 /* Direct 8 bit */
+#define R_ARM_SBREL32 9
+#define R_ARM_THM_PC22 10
+#define R_ARM_THM_PC8 11
+#define R_ARM_AMP_VCALL9 12
+#define R_ARM_SWI24 13
+#define R_ARM_THM_SWI8 14
+#define R_ARM_XPC25 15
+#define R_ARM_THM_XPC22 16
+#define R_ARM_COPY 20 /* Copy symbol at runtime */
+#define R_ARM_GLOB_DAT 21 /* Create GOT entry */
+#define R_ARM_JUMP_SLOT 22 /* Create PLT entry */
+#define R_ARM_RELATIVE 23 /* Adjust by program base */
+#define R_ARM_GOTOFF 24 /* 32 bit offset to GOT */
+#define R_ARM_GOTPC 25 /* 32 bit PC relative offset to GOT */
+#define R_ARM_GOT32 26 /* 32 bit GOT entry */
+#define R_ARM_PLT32 27 /* 32 bit PLT address */
+#define R_ARM_ALU_PCREL_7_0 32
+#define R_ARM_ALU_PCREL_15_8 33
+#define R_ARM_ALU_PCREL_23_15 34
+#define R_ARM_LDR_SBREL_11_0 35
+#define R_ARM_ALU_SBREL_19_12 36
+#define R_ARM_ALU_SBREL_27_20 37
+#define R_ARM_GNU_VTENTRY 100
+#define R_ARM_GNU_VTINHERIT 101
+#define R_ARM_THM_PC11 102 /* thumb unconditional branch */
+#define R_ARM_THM_PC9 103 /* thumb conditional branch */
+#define R_ARM_RXPC25 249
+#define R_ARM_RSBREL32 250
+#define R_ARM_THM_RPC22 251
+#define R_ARM_RREL32 252
+#define R_ARM_RABS22 253
+#define R_ARM_RPC24 254
+#define R_ARM_RBASE 255
+/* Keep this the last entry. */
+#define R_ARM_NUM 256
+
+/* IA-64 specific declarations. */
+
+/* Processor specific flags for the Ehdr e_flags field. */
+#define EF_IA_64_MASKOS 0x0000000f /* os-specific flags */
+#define EF_IA_64_ABI64 0x00000010 /* 64-bit ABI */
+#define EF_IA_64_ARCH 0xff000000 /* arch. version mask */
+
+/* Processor specific values for the Phdr p_type field. */
+#define PT_IA_64_ARCHEXT (PT_LOPROC + 0) /* arch extension bits */
+#define PT_IA_64_UNWIND (PT_LOPROC + 1) /* ia64 unwind bits */
+#define PT_IA_64_HP_OPT_ANOT (PT_LOOS + 0x12)
+#define PT_IA_64_HP_HSL_ANOT (PT_LOOS + 0x13)
+#define PT_IA_64_HP_STACK (PT_LOOS + 0x14)
+
+/* Processor specific flags for the Phdr p_flags field. */
+#define PF_IA_64_NORECOV 0x80000000 /* spec insns w/o recovery */
+
+/* Processor specific values for the Shdr sh_type field. */
+#define SHT_IA_64_EXT (SHT_LOPROC + 0) /* extension bits */
+#define SHT_IA_64_UNWIND (SHT_LOPROC + 1) /* unwind bits */
+
+/* Processor specific flags for the Shdr sh_flags field. */
+#define SHF_IA_64_SHORT 0x10000000 /* section near gp */
+#define SHF_IA_64_NORECOV 0x20000000 /* spec insns w/o recovery */
+
+/* Processor specific values for the Dyn d_tag field. */
+#define DT_IA_64_PLT_RESERVE (DT_LOPROC + 0)
+#define DT_IA_64_NUM 1
+
+/* IA-64 relocations. */
+#define R_IA64_NONE 0x00 /* none */
+#define R_IA64_IMM14 0x21 /* symbol + addend, add imm14 */
+#define R_IA64_IMM22 0x22 /* symbol + addend, add imm22 */
+#define R_IA64_IMM64 0x23 /* symbol + addend, mov imm64 */
+#define R_IA64_DIR32MSB 0x24 /* symbol + addend, data4 MSB */
+#define R_IA64_DIR32LSB 0x25 /* symbol + addend, data4 LSB */
+#define R_IA64_DIR64MSB 0x26 /* symbol + addend, data8 MSB */
+#define R_IA64_DIR64LSB 0x27 /* symbol + addend, data8 LSB */
+#define R_IA64_GPREL22 0x2a /* @gprel(sym + add), add imm22 */
+#define R_IA64_GPREL64I 0x2b /* @gprel(sym + add), mov imm64 */
+#define R_IA64_GPREL32MSB 0x2c /* @gprel(sym + add), data4 MSB */
+#define R_IA64_GPREL32LSB 0x2d /* @gprel(sym + add), data4 LSB */
+#define R_IA64_GPREL64MSB 0x2e /* @gprel(sym + add), data8 MSB */
+#define R_IA64_GPREL64LSB 0x2f /* @gprel(sym + add), data8 LSB */
+#define R_IA64_LTOFF22 0x32 /* @ltoff(sym + add), add imm22 */
+#define R_IA64_LTOFF64I 0x33 /* @ltoff(sym + add), mov imm64 */
+#define R_IA64_PLTOFF22 0x3a /* @pltoff(sym + add), add imm22 */
+#define R_IA64_PLTOFF64I 0x3b /* @pltoff(sym + add), mov imm64 */
+#define R_IA64_PLTOFF64MSB 0x3e /* @pltoff(sym + add), data8 MSB */
+#define R_IA64_PLTOFF64LSB 0x3f /* @pltoff(sym + add), data8 LSB */
+#define R_IA64_FPTR64I 0x43 /* @fptr(sym + add), mov imm64 */
+#define R_IA64_FPTR32MSB 0x44 /* @fptr(sym + add), data4 MSB */
+#define R_IA64_FPTR32LSB 0x45 /* @fptr(sym + add), data4 LSB */
+#define R_IA64_FPTR64MSB 0x46 /* @fptr(sym + add), data8 MSB */
+#define R_IA64_FPTR64LSB 0x47 /* @fptr(sym + add), data8 LSB */
+#define R_IA64_PCREL60B 0x48 /* @pcrel(sym + add), brl */
+#define R_IA64_PCREL21B 0x49 /* @pcrel(sym + add), ptb, call */
+#define R_IA64_PCREL21M 0x4a /* @pcrel(sym + add), chk.s */
+#define R_IA64_PCREL21F 0x4b /* @pcrel(sym + add), fchkf */
+#define R_IA64_PCREL32MSB 0x4c /* @pcrel(sym + add), data4 MSB */
+#define R_IA64_PCREL32LSB 0x4d /* @pcrel(sym + add), data4 LSB */
+#define R_IA64_PCREL64MSB 0x4e /* @pcrel(sym + add), data8 MSB */
+#define R_IA64_PCREL64LSB 0x4f /* @pcrel(sym + add), data8 LSB */
+#define R_IA64_LTOFF_FPTR22 0x52 /* @ltoff(@fptr(s+a)), imm22 */
+#define R_IA64_LTOFF_FPTR64I 0x53 /* @ltoff(@fptr(s+a)), imm64 */
+#define R_IA64_LTOFF_FPTR32MSB 0x54 /* @ltoff(@fptr(s+a)), data4 MSB */
+#define R_IA64_LTOFF_FPTR32LSB 0x55 /* @ltoff(@fptr(s+a)), data4 LSB */
+#define R_IA64_LTOFF_FPTR64MSB 0x56 /* @ltoff(@fptr(s+a)), data8 MSB */
+#define R_IA64_LTOFF_FPTR64LSB 0x57 /* @ltoff(@fptr(s+a)), data8 LSB */
+#define R_IA64_SEGREL32MSB 0x5c /* @segrel(sym + add), data4 MSB */
+#define R_IA64_SEGREL32LSB 0x5d /* @segrel(sym + add), data4 LSB */
+#define R_IA64_SEGREL64MSB 0x5e /* @segrel(sym + add), data8 MSB */
+#define R_IA64_SEGREL64LSB 0x5f /* @segrel(sym + add), data8 LSB */
+#define R_IA64_SECREL32MSB 0x64 /* @secrel(sym + add), data4 MSB */
+#define R_IA64_SECREL32LSB 0x65 /* @secrel(sym + add), data4 LSB */
+#define R_IA64_SECREL64MSB 0x66 /* @secrel(sym + add), data8 MSB */
+#define R_IA64_SECREL64LSB 0x67 /* @secrel(sym + add), data8 LSB */
+#define R_IA64_REL32MSB 0x6c /* data 4 + REL */
+#define R_IA64_REL32LSB 0x6d /* data 4 + REL */
+#define R_IA64_REL64MSB 0x6e /* data 8 + REL */
+#define R_IA64_REL64LSB 0x6f /* data 8 + REL */
+#define R_IA64_LTV32MSB 0x74 /* symbol + addend, data4 MSB */
+#define R_IA64_LTV32LSB 0x75 /* symbol + addend, data4 LSB */
+#define R_IA64_LTV64MSB 0x76 /* symbol + addend, data8 MSB */
+#define R_IA64_LTV64LSB 0x77 /* symbol + addend, data8 LSB */
+#define R_IA64_PCREL21BI 0x79 /* @pcrel(sym + add), 21bit inst */
+#define R_IA64_PCREL22 0x7a /* @pcrel(sym + add), 22bit inst */
+#define R_IA64_PCREL64I 0x7b /* @pcrel(sym + add), 64bit inst */
+#define R_IA64_IPLTMSB 0x80 /* dynamic reloc, imported PLT, MSB */
+#define R_IA64_IPLTLSB 0x81 /* dynamic reloc, imported PLT, LSB */
+#define R_IA64_COPY 0x84 /* copy relocation */
+#define R_IA64_SUB 0x85 /* Addend and symbol difference */
+#define R_IA64_LTOFF22X 0x86 /* LTOFF22, relaxable. */
+#define R_IA64_LDXMOV 0x87 /* Use of LTOFF22X. */
+#define R_IA64_TPREL14 0x91 /* @tprel(sym + add), imm14 */
+#define R_IA64_TPREL22 0x92 /* @tprel(sym + add), imm22 */
+#define R_IA64_TPREL64I 0x93 /* @tprel(sym + add), imm64 */
+#define R_IA64_TPREL64MSB 0x96 /* @tprel(sym + add), data8 MSB */
+#define R_IA64_TPREL64LSB 0x97 /* @tprel(sym + add), data8 LSB */
+#define R_IA64_LTOFF_TPREL22 0x9a /* @ltoff(@tprel(s+a)), imm2 */
+#define R_IA64_DTPMOD64MSB 0xa6 /* @dtpmod(sym + add), data8 MSB */
+#define R_IA64_DTPMOD64LSB 0xa7 /* @dtpmod(sym + add), data8 LSB */
+#define R_IA64_LTOFF_DTPMOD22 0xaa /* @ltoff(@dtpmod(sym + add)), imm22 */
+#define R_IA64_DTPREL14 0xb1 /* @dtprel(sym + add), imm14 */
+#define R_IA64_DTPREL22 0xb2 /* @dtprel(sym + add), imm22 */
+#define R_IA64_DTPREL64I 0xb3 /* @dtprel(sym + add), imm64 */
+#define R_IA64_DTPREL32MSB 0xb4 /* @dtprel(sym + add), data4 MSB */
+#define R_IA64_DTPREL32LSB 0xb5 /* @dtprel(sym + add), data4 LSB */
+#define R_IA64_DTPREL64MSB 0xb6 /* @dtprel(sym + add), data8 MSB */
+#define R_IA64_DTPREL64LSB 0xb7 /* @dtprel(sym + add), data8 LSB */
+#define R_IA64_LTOFF_DTPREL22 0xba /* @ltoff(@dtprel(s+a)), imm22 */
+
+/* SH specific declarations */
+
+/* SH relocs. */
+#define R_SH_NONE 0
+#define R_SH_DIR32 1
+#define R_SH_REL32 2
+#define R_SH_DIR8WPN 3
+#define R_SH_IND12W 4
+#define R_SH_DIR8WPL 5
+#define R_SH_DIR8WPZ 6
+#define R_SH_DIR8BP 7
+#define R_SH_DIR8W 8
+#define R_SH_DIR8L 9
+#define R_SH_SWITCH16 25
+#define R_SH_SWITCH32 26
+#define R_SH_USES 27
+#define R_SH_COUNT 28
+#define R_SH_ALIGN 29
+#define R_SH_CODE 30
+#define R_SH_DATA 31
+#define R_SH_LABEL 32
+#define R_SH_SWITCH8 33
+#define R_SH_GNU_VTINHERIT 34
+#define R_SH_GNU_VTENTRY 35
+#define R_SH_TLS_GD_32 144
+#define R_SH_TLS_LD_32 145
+#define R_SH_TLS_LDO_32 146
+#define R_SH_TLS_IE_32 147
+#define R_SH_TLS_LE_32 148
+#define R_SH_TLS_DTPMOD32 149
+#define R_SH_TLS_DTPOFF32 150
+#define R_SH_TLS_TPOFF32 151
+#define R_SH_GOT32 160
+#define R_SH_PLT32 161
+#define R_SH_COPY 162
+#define R_SH_GLOB_DAT 163
+#define R_SH_JMP_SLOT 164
+#define R_SH_RELATIVE 165
+#define R_SH_GOTOFF 166
+#define R_SH_GOTPC 167
+/* Keep this the last entry. */
+#define R_SH_NUM 256
+
+/* Additional s390 relocs */
+
+#define R_390_NONE 0 /* No reloc. */
+#define R_390_8 1 /* Direct 8 bit. */
+#define R_390_12 2 /* Direct 12 bit. */
+#define R_390_16 3 /* Direct 16 bit. */
+#define R_390_32 4 /* Direct 32 bit. */
+#define R_390_PC32 5 /* PC relative 32 bit. */
+#define R_390_GOT12 6 /* 12 bit GOT offset. */
+#define R_390_GOT32 7 /* 32 bit GOT offset. */
+#define R_390_PLT32 8 /* 32 bit PC relative PLT address. */
+#define R_390_COPY 9 /* Copy symbol at runtime. */
+#define R_390_GLOB_DAT 10 /* Create GOT entry. */
+#define R_390_JMP_SLOT 11 /* Create PLT entry. */
+#define R_390_RELATIVE 12 /* Adjust by program base. */
+#define R_390_GOTOFF32 13 /* 32 bit offset to GOT. */
+#define R_390_GOTPC 14 /* 32 bit PC relative offset to GOT. */
+#define R_390_GOT16 15 /* 16 bit GOT offset. */
+#define R_390_PC16 16 /* PC relative 16 bit. */
+#define R_390_PC16DBL 17 /* PC relative 16 bit shifted by 1. */
+#define R_390_PLT16DBL 18 /* 16 bit PC rel. PLT shifted by 1. */
+#define R_390_PC32DBL 19 /* PC relative 32 bit shifted by 1. */
+#define R_390_PLT32DBL 20 /* 32 bit PC rel. PLT shifted by 1. */
+#define R_390_GOTPCDBL 21 /* 32 bit PC rel. GOT shifted by 1. */
+#define R_390_64 22 /* Direct 64 bit. */
+#define R_390_PC64 23 /* PC relative 64 bit. */
+#define R_390_GOT64 24 /* 64 bit GOT offset. */
+#define R_390_PLT64 25 /* 64 bit PC relative PLT address. */
+#define R_390_GOTENT 26 /* 32 bit PC rel. to GOT entry >> 1. */
+#define R_390_GOTOFF16 27 /* 16 bit offset to GOT. */
+#define R_390_GOTOFF64 28 /* 64 bit offset to GOT. */
+#define R_390_GOTPLT12 29 /* 12 bit offset to jump slot. */
+#define R_390_GOTPLT16 30 /* 16 bit offset to jump slot. */
+#define R_390_GOTPLT32 31 /* 32 bit offset to jump slot. */
+#define R_390_GOTPLT64 32 /* 64 bit offset to jump slot. */
+#define R_390_GOTPLTENT 33 /* 32 bit rel. offset to jump slot. */
+#define R_390_PLTOFF16 34 /* 16 bit offset from GOT to PLT. */
+#define R_390_PLTOFF32 35 /* 32 bit offset from GOT to PLT. */
+#define R_390_PLTOFF64 36 /* 16 bit offset from GOT to PLT. */
+#define R_390_TLS_LOAD 37 /* Tag for load insn in TLS code. */
+#define R_390_TLS_GDCALL \
+ 38 /* Tag for function call in general \
+dynamic TLS code. */
+#define R_390_TLS_LDCALL \
+ 39 /* Tag for function call in local \
+dynamic TLS code. */
+#define R_390_TLS_GD32 \
+ 40 /* Direct 32 bit for general dynamic \
+thread local data. */
+#define R_390_TLS_GD64 \
+ 41 /* Direct 64 bit for general dynamic \
+thread local data. */
+#define R_390_TLS_GOTIE12 \
+ 42 /* 12 bit GOT offset for static TLS \
+block offset. */
+#define R_390_TLS_GOTIE32 \
+ 43 /* 32 bit GOT offset for static TLS \
+block offset. */
+#define R_390_TLS_GOTIE64 \
+ 44 /* 64 bit GOT offset for static TLS \
+block offset. */
+#define R_390_TLS_LDM32 \
+ 45 /* Direct 32 bit for local dynamic \
+thread local data in LE code. */
+#define R_390_TLS_LDM64 \
+ 46 /* Direct 64 bit for local dynamic \
+thread local data in LE code. */
+#define R_390_TLS_IE32 \
+ 47 /* 32 bit address of GOT entry for \
+negated static TLS block offset. */
+#define R_390_TLS_IE64 \
+ 48 /* 64 bit address of GOT entry for \
+negated static TLS block offset. */
+#define R_390_TLS_IEENT \
+ 49 /* 32 bit rel. offset to GOT entry for \
+negated static TLS block offset. */
+#define R_390_TLS_LE32 \
+ 50 /* 32 bit negated offset relative to \
+static TLS block. */
+#define R_390_TLS_LE64 \
+ 51 /* 64 bit negated offset relative to \
+static TLS block. */
+#define R_390_TLS_LDO32 \
+ 52 /* 32 bit offset relative to TLS \
+block. */
+#define R_390_TLS_LDO64 \
+ 53 /* 64 bit offset relative to TLS \
+block. */
+#define R_390_TLS_DTPMOD 54 /* ID of module containing symbol. */
+#define R_390_TLS_DTPOFF 55 /* Offset in TLS block. */
+#define R_390_TLS_TPOFF \
+ 56 /* Negated offset in static TLS \
+block. */
+#define R_390_20 57 /* Direct 20 bit. */
+#define R_390_GOT20 58 /* 20 bit GOT offset. */
+#define R_390_GOTPLT20 59 /* 20 bit offset to jump slot. */
+#define R_390_TLS_GOTIE20 \
+ 60 /* 20 bit GOT offset for static TLS \
+block offset. */
+/* Keep this the last entry. */
+#define R_390_NUM 61
+
+/* CRIS relocations. */
+#define R_CRIS_NONE 0
+#define R_CRIS_8 1
+#define R_CRIS_16 2
+#define R_CRIS_32 3
+#define R_CRIS_8_PCREL 4
+#define R_CRIS_16_PCREL 5
+#define R_CRIS_32_PCREL 6
+#define R_CRIS_GNU_VTINHERIT 7
+#define R_CRIS_GNU_VTENTRY 8
+#define R_CRIS_COPY 9
+#define R_CRIS_GLOB_DAT 10
+#define R_CRIS_JUMP_SLOT 11
+#define R_CRIS_RELATIVE 12
+#define R_CRIS_16_GOT 13
+#define R_CRIS_32_GOT 14
+#define R_CRIS_16_GOTPLT 15
+#define R_CRIS_32_GOTPLT 16
+#define R_CRIS_32_GOTREL 17
+#define R_CRIS_32_PLT_GOTREL 18
+#define R_CRIS_32_PLT_PCREL 19
+
+#define R_CRIS_NUM 20
+
+/* AMD x86-64 relocations. */
+#define R_X86_64_NONE 0 /* No reloc */
+#define R_X86_64_64 1 /* Direct 64 bit */
+#define R_X86_64_PC32 2 /* PC relative 32 bit signed */
+#define R_X86_64_GOT32 3 /* 32 bit GOT entry */
+#define R_X86_64_PLT32 4 /* 32 bit PLT address */
+#define R_X86_64_COPY 5 /* Copy symbol at runtime */
+#define R_X86_64_GLOB_DAT 6 /* Create GOT entry */
+#define R_X86_64_JUMP_SLOT 7 /* Create PLT entry */
+#define R_X86_64_RELATIVE 8 /* Adjust by program base */
+#define R_X86_64_GOTPCREL \
+ 9 /* 32 bit signed PC relative \
+offset to GOT */
+#define R_X86_64_32 10 /* Direct 32 bit zero extended */
+#define R_X86_64_32S 11 /* Direct 32 bit sign extended */
+#define R_X86_64_16 12 /* Direct 16 bit zero extended */
+#define R_X86_64_PC16 13 /* 16 bit sign extended pc relative */
+#define R_X86_64_8 14 /* Direct 8 bit sign extended */
+#define R_X86_64_PC8 15 /* 8 bit sign extended pc relative */
+#define R_X86_64_DTPMOD64 16 /* ID of module containing symbol */
+#define R_X86_64_DTPOFF64 17 /* Offset in module's TLS block */
+#define R_X86_64_TPOFF64 18 /* Offset in initial TLS block */
+#define R_X86_64_TLSGD \
+ 19 /* 32 bit signed PC relative offset \
+to two GOT entries for GD symbol */
+#define R_X86_64_TLSLD \
+ 20 /* 32 bit signed PC relative offset \
+to two GOT entries for LD symbol */
+#define R_X86_64_DTPOFF32 21 /* Offset in TLS block */
+#define R_X86_64_GOTTPOFF \
+ 22 /* 32 bit signed PC relative offset \
+to GOT entry for IE symbol */
+#define R_X86_64_TPOFF32 23 /* Offset in initial TLS block */
+
+#define R_X86_64_NUM 24
+
+/* AM33 relocations. */
+#define R_MN10300_NONE 0 /* No reloc. */
+#define R_MN10300_32 1 /* Direct 32 bit. */
+#define R_MN10300_16 2 /* Direct 16 bit. */
+#define R_MN10300_8 3 /* Direct 8 bit. */
+#define R_MN10300_PCREL32 4 /* PC-relative 32-bit. */
+#define R_MN10300_PCREL16 5 /* PC-relative 16-bit signed. */
+#define R_MN10300_PCREL8 6 /* PC-relative 8-bit signed. */
+#define R_MN10300_GNU_VTINHERIT 7 /* Ancient C++ vtable garbage... */
+#define R_MN10300_GNU_VTENTRY 8 /* ... collection annotation. */
+#define R_MN10300_24 9 /* Direct 24 bit. */
+#define R_MN10300_GOTPC32 10 /* 32-bit PCrel offset to GOT. */
+#define R_MN10300_GOTPC16 11 /* 16-bit PCrel offset to GOT. */
+#define R_MN10300_GOTOFF32 12 /* 32-bit offset from GOT. */
+#define R_MN10300_GOTOFF24 13 /* 24-bit offset from GOT. */
+#define R_MN10300_GOTOFF16 14 /* 16-bit offset from GOT. */
+#define R_MN10300_PLT32 15 /* 32-bit PCrel to PLT entry. */
+#define R_MN10300_PLT16 16 /* 16-bit PCrel to PLT entry. */
+#define R_MN10300_GOT32 17 /* 32-bit offset to GOT entry. */
+#define R_MN10300_GOT24 18 /* 24-bit offset to GOT entry. */
+#define R_MN10300_GOT16 19 /* 16-bit offset to GOT entry. */
+#define R_MN10300_COPY 20 /* Copy symbol at runtime. */
+#define R_MN10300_GLOB_DAT 21 /* Create GOT entry. */
+#define R_MN10300_JMP_SLOT 22 /* Create PLT entry. */
+#define R_MN10300_RELATIVE 23 /* Adjust by program base. */
+
+#define R_MN10300_NUM 24
+
+/* M32R relocs. */
+#define R_M32R_NONE 0 /* No reloc. */
+#define R_M32R_16 1 /* Direct 16 bit. */
+#define R_M32R_32 2 /* Direct 32 bit. */
+#define R_M32R_24 3 /* Direct 24 bit. */
+#define R_M32R_10_PCREL 4 /* PC relative 10 bit shifted. */
+#define R_M32R_18_PCREL 5 /* PC relative 18 bit shifted. */
+#define R_M32R_26_PCREL 6 /* PC relative 26 bit shifted. */
+#define R_M32R_HI16_ULO 7 /* High 16 bit with unsigned low. */
+#define R_M32R_HI16_SLO 8 /* High 16 bit with signed low. */
+#define R_M32R_LO16 9 /* Low 16 bit. */
+#define R_M32R_SDA16 10 /* 16 bit offset in SDA. */
+#define R_M32R_GNU_VTINHERIT 11
+#define R_M32R_GNU_VTENTRY 12
+/* M32R relocs use SHT_RELA. */
+#define R_M32R_16_RELA 33 /* Direct 16 bit. */
+#define R_M32R_32_RELA 34 /* Direct 32 bit. */
+#define R_M32R_24_RELA 35 /* Direct 24 bit. */
+#define R_M32R_10_PCREL_RELA 36 /* PC relative 10 bit shifted. */
+#define R_M32R_18_PCREL_RELA 37 /* PC relative 18 bit shifted. */
+#define R_M32R_26_PCREL_RELA 38 /* PC relative 26 bit shifted. */
+#define R_M32R_HI16_ULO_RELA 39 /* High 16 bit with unsigned low */
+#define R_M32R_HI16_SLO_RELA 40 /* High 16 bit with signed low */
+#define R_M32R_LO16_RELA 41 /* Low 16 bit */
+#define R_M32R_SDA16_RELA 42 /* 16 bit offset in SDA */
+#define R_M32R_RELA_GNU_VTINHERIT 43
+#define R_M32R_RELA_GNU_VTENTRY 44
+
+#define R_M32R_GOT24 48 /* 24 bit GOT entry */
+#define R_M32R_26_PLTREL 49 /* 26 bit PC relative to PLT shifted */
+#define R_M32R_COPY 50 /* Copy symbol at runtime */
+#define R_M32R_GLOB_DAT 51 /* Create GOT entry */
+#define R_M32R_JMP_SLOT 52 /* Create PLT entry */
+#define R_M32R_RELATIVE 53 /* Adjust by program base */
+#define R_M32R_GOTOFF 54 /* 24 bit offset to GOT */
+#define R_M32R_GOTPC24 55 /* 24 bit PC relative offset to GOT */
+#define R_M32R_GOT16_HI_ULO \
+ 56 /* High 16 bit GOT entry with unsigned \
+low */
+#define R_M32R_GOT16_HI_SLO \
+ 57 /* High 16 bit GOT entry with signed \
+ low */
+#define R_M32R_GOT16_LO 58 /* Low 16 bit GOT entry */
+#define R_M32R_GOTPC_HI_ULO \
+ 59 /* High 16 bit PC relative offset to \
+GOT with unsigned low */
+#define R_M32R_GOTPC_HI_SLO \
+ 60 /* High 16 bit PC relative offset to \
+GOT with signed low */
+#define R_M32R_GOTPC_LO \
+ 61 /* Low 16 bit PC relative offset to \
+GOT */
+#define R_M32R_GOTOFF_HI_ULO \
+ 62 /* High 16 bit offset to GOT \
+with unsigned low */
+#define R_M32R_GOTOFF_HI_SLO \
+ 63 /* High 16 bit offset to GOT \
+ with signed low */
+#define R_M32R_GOTOFF_LO 64 /* Low 16 bit offset to GOT */
+#define R_M32R_NUM 256 /* Keep this the last entry. */
+
+/* __END_DECLS */
diff --git a/kernel/include/api/exec.h b/kernel/include/api/exec.h
new file mode 100644
index 0000000..854ce9e
--- /dev/null
+++ b/kernel/include/api/exec.h
@@ -0,0 +1,12 @@
+#pragma once
+
+#include "types.h"
+
+struct regs;
+
+long do_execve(const char *filename, char *const *argv, char *const *envp,
+ struct regs *regs);
+
+void kernel_execve(const char *filename, char *const *argv, char *const *envp);
+
+void userland_entry(struct regs regs);
diff --git a/kernel/include/api/syscall.h b/kernel/include/api/syscall.h
new file mode 100644
index 0000000..ea924c3
--- /dev/null
+++ b/kernel/include/api/syscall.h
@@ -0,0 +1,196 @@
+#pragma once
+
+/* Kernel and user header (via symlink) */
+
+#ifdef __KERNEL__
+#include "types.h"
+#else
+
+#include "sys/types.h"
+
+#endif
+
+/* Trap number for syscalls */
+#define INTR_SYSCALL 0x2e
+
+/* Keep all lists IN ORDER! */
+
+#define SYS_syscall 0
+#define SYS_exit 1
+#define SYS_fork 2
+#define SYS_read 3
+#define SYS_write 4
+#define SYS_open 5
+#define SYS_close 6
+#define SYS_waitpid 7
+#define SYS_link 8
+#define SYS_unlink 9
+#define SYS_execve 10
+#define SYS_chdir 11
+#define SYS_sleep 12 /* NYI */
+#define SYS_lseek 14
+#define SYS_sync 15
+#define SYS_nuke 16 /* NYI */
+#define SYS_dup 17
+#define SYS_pipe 18
+#define SYS_ioctl 19 /* NYI */
+#define SYS_rmdir 21
+#define SYS_mkdir 22
+#define SYS_getdents 23
+#define SYS_mmap 24
+#define SYS_mprotect 25 /* NYI */
+#define SYS_munmap 26
+#define SYS_rename 27 /* NYI */
+#define SYS_uname 28
+#define SYS_thr_create 29 /* NYI */
+#define SYS_thr_cancel 30
+#define SYS_thr_exit 31
+#define SYS_sched_yield 32
+#define SYS_thr_join 33 /* NYI */
+#define SYS_gettid 34 /* NYI */
+#define SYS_getpid 35
+#define SYS_errno 39
+#define SYS_halt 40
+#define SYS_get_free_mem 41 /* NYI */
+#define SYS_set_errno 42
+#define SYS_dup2 43
+#define SYS_brk 44
+#define SYS_mount 45
+#define SYS_umount 46
+#define SYS_stat 47
+#define SYS_time 48
+#define SYS_usleep 49
+
+/*
+ * ... what does the scouter say about his syscall?
+ * IT'S OVER 9000!
+ * WHAT?! 9000?!
+ */
+#define SYS_debug 9001
+#define SYS_kshell 9002
+
+struct regs;
+struct stat;
+
+typedef struct argstr
+{
+ const char *as_str;
+ size_t as_len; /* Not including null character */
+} argstr_t;
+
+typedef struct argvec
+{
+ argstr_t *av_vec;
+ size_t av_len; /* Not including null entry */
+} argvec_t;
+
+typedef struct waitpid_args
+{
+ pid_t wpa_pid;
+ int *wpa_status;
+ int wpa_options;
+} waitpid_args_t;
+
+typedef struct mmap_args
+{
+ void *mma_addr;
+ size_t mma_len;
+ int mma_prot;
+ int mma_flags;
+ int mma_fd;
+ off_t mma_off;
+} mmap_args_t;
+
+typedef struct munmap_args
+{
+ void *addr;
+ size_t len;
+} munmap_args_t;
+
+typedef struct open_args
+{
+ argstr_t filename;
+ int flags;
+ int mode;
+} open_args_t;
+
+typedef struct read_args
+{
+ int fd;
+ void *buf;
+ size_t nbytes;
+} read_args_t;
+
+typedef struct write_args
+{
+ int fd;
+ void *buf;
+ size_t nbytes;
+} write_args_t;
+
+typedef struct mkdir_args
+{
+ argstr_t path;
+ int mode;
+} mkdir_args_t;
+
+typedef struct link_args
+{
+ argstr_t to;
+ argstr_t from;
+} link_args_t;
+
+typedef struct execve_args
+{
+ argstr_t filename;
+ argvec_t argv;
+ argvec_t envp;
+} execve_args_t;
+
+typedef struct rename_args
+{
+ argstr_t oldpath;
+ argstr_t newpath;
+} rename_args_t;
+
+typedef struct getdents_args
+{
+ int fd;
+ struct dirent *dirp;
+ size_t count;
+} getdents_args_t;
+
+typedef struct lseek_args
+{
+ int fd;
+ off_t offset;
+ int whence;
+} lseek_args_t;
+
+typedef struct dup2_args
+{
+ int ofd;
+ int nfd;
+} dup2_args_t;
+
+#ifdef __MOUNTING__
+typedef struct mount_args
+{
+ argstr_t spec;
+ argstr_t dir;
+ argstr_t fstype;
+} mount_args_t;
+#endif
+
+typedef struct stat_args
+{
+ argstr_t path;
+ struct stat *buf;
+} stat_args_t;
+
+typedef struct usleep_args
+{
+ useconds_t usec;
+} usleep_args_t;
+
+struct utsname;
diff --git a/kernel/include/api/utsname.h b/kernel/include/api/utsname.h
new file mode 100644
index 0000000..c60ae81
--- /dev/null
+++ b/kernel/include/api/utsname.h
@@ -0,0 +1,14 @@
+#pragma once
+
+#define _UTSNAME_LENGTH 128
+
+struct utsname
+{
+ char sysname[_UTSNAME_LENGTH];
+ char nodename[_UTSNAME_LENGTH];
+ char release[_UTSNAME_LENGTH];
+ char version[_UTSNAME_LENGTH];
+ char machine[_UTSNAME_LENGTH];
+};
+
+int uname(struct utsname *buf);
diff --git a/kernel/include/boot/config.h b/kernel/include/boot/config.h
new file mode 100644
index 0000000..74e0d42
--- /dev/null
+++ b/kernel/include/boot/config.h
@@ -0,0 +1,12 @@
+#pragma once
+
+#define IDENTITY_MAPPED_RAM_SIZE (1 << 16)
+
+#define KERNEL_PHYS_BASE ((uintptr_t)(&kernel_phys_base))
+#define KERNEL_PHYS_END ((uintptr_t)(&kernel_phys_end))
+#define KERNEL_VMA 0xffff800000000000
+
+// https://www.usenix.org/sites/default/files/conference/protected-files/sec14_slides_kemerlis.pdf
+#define PHYS_OFFSET 0xffff880000000000
+
+#define MEMORY_MAP_BASE 0x9000
diff --git a/kernel/include/boot/multiboot_macros.h b/kernel/include/boot/multiboot_macros.h
new file mode 100644
index 0000000..1ca6383
--- /dev/null
+++ b/kernel/include/boot/multiboot_macros.h
@@ -0,0 +1,6 @@
+#pragma once
+
+// random macro for multiboot header
+#define TAG_SIZE(x) (((x)-1) / MULTIBOOT_TAG_ALIGN + 1)
+
+extern struct multiboot_tag *mb_tag;
diff --git a/kernel/include/config.h b/kernel/include/config.h
new file mode 100644
index 0000000..a57edd4
--- /dev/null
+++ b/kernel/include/config.h
@@ -0,0 +1,50 @@
+/*
+ * FILE: config.h
+ * AUTHOR: kma
+ * DESCR: tunable kernel parameters
+ */
+
+#pragma once
+
+/* Kernel and user header (via symlink) */
+
+/*
+ * kernel configuration parameters
+ */
+#define DEFAULT_STACK_SIZE_PAGES 16
+#define DEFAULT_STACK_SIZE (DEFAULT_STACK_SIZE_PAGES << PAGE_SHIFT)
+#define TICK_MSECS 10 /* msecs between clock interrupts */
+
+/*
+ * Memory-management-related:
+ */
+
+/*
+ * Finds fraction of available page frames that will be dedicated to kmem
+ * the rest are given to the vm system. This is currently unused.
+ */
+#define KMEM_FRAC(x) (((x) >> 2) + ((x) >> 3)) /* 37.5%-ish */
+
+/* pframe/mobj-system-related: */
+#define PF_HASH_SIZE 17 /* Number of buckets in pn/mobj->pframe hash. This is currently unused. */
+
+/*
+ * filesystem/vfs configuration parameters
+ */
+
+#define MAXPATHLEN 1024 /* maximum size of a pathname */
+#define MAX_FILES 1024 /* max number of files */
+#define MAX_VFS 8 /* max # of vfses */
+#define MAX_VNODES 1024 /* max number of in-core vnodes */
+#define NAME_LEN 28 /* maximum directory entry length */
+#define NFILES 32 /* maximum number of open files */
+
+/* Note: if rootfs is ramfs, this is completely ignored */
+#define VFS_ROOTFS_DEV "disk0" /* device containing root filesystem */
+
+/* root filesystem type - either "ramfs" or "s5fs" */
+#ifdef __S5FS__
+#define VFS_ROOTFS_TYPE "s5fs"
+#else
+#define VFS_ROOTFS_TYPE "ramfs"
+#endif
diff --git a/kernel/include/ctype.h b/kernel/include/ctype.h
new file mode 100644
index 0000000..95e5496
--- /dev/null
+++ b/kernel/include/ctype.h
@@ -0,0 +1,124 @@
+#pragma once
+
+#ifdef __KERNEL__
+#include "kernel.h"
+#include "types.h"
+#else
+
+#include "stddef.h"
+#include "sys/types.h"
+
+#endif
+
+/* the original implementation for the following functions
+ * was ported from the old Weenix on Xen architecture which
+ * used the mini-os functions */
+/*
+ * NOTE! This ctype does not handle EOF like the standard C
+ * library is required to.
+ */
+
+#define _U 0x01 /* upper */
+#define _L 0x02 /* lower */
+#define _D 0x04 /* digit */
+#define _C 0x08 /* cntrl */
+#define _P 0x10 /* punct */
+#define _S 0x20 /* white space (space/lf/tab) */
+#define _X 0x40 /* hex digit */
+#define _SP 0x80 /* hard space (0x20) */
+
+static unsigned char
+ _ctype[] = {_C, _C, _C, _C, _C, _C,
+ _C, _C, /* 0-7 */
+ _C, _C | _S, _C | _S, _C | _S, _C | _S, _C | _S,
+ _C, _C, /* 8-15 */
+ _C, _C, _C, _C, _C, _C,
+ _C, _C, /* 16-23 */
+ _C, _C, _C, _C, _C, _C,
+ _C, _C, /* 24-31 */
+ _S | _SP, _P, _P, _P, _P, _P,
+ _P, _P, /* 32-39 */
+ _P, _P, _P, _P, _P, _P,
+ _P, _P, /* 40-47 */
+ _D, _D, _D, _D, _D, _D,
+ _D, _D, /* 48-55 */
+ _D, _D, _P, _P, _P, _P,
+ _P, _P, /* 56-63 */
+ _P, _U | _X, _U | _X, _U | _X, _U | _X, _U | _X,
+ _U | _X, _U, /* 64-71 */
+ _U, _U, _U, _U, _U, _U,
+ _U, _U, /* 72-79 */
+ _U, _U, _U, _U, _U, _U,
+ _U, _U, /* 80-87 */
+ _U, _U, _U, _P, _P, _P,
+ _P, _P, /* 88-95 */
+ _P, _L | _X, _L | _X, _L | _X, _L | _X, _L | _X,
+ _L | _X, _L, /* 96-103 */
+ _L, _L, _L, _L, _L, _L,
+ _L, _L, /* 104-111 */
+ _L, _L, _L, _L, _L, _L,
+ _L, _L, /* 112-119 */
+ _L, _L, _L, _P, _P, _P,
+ _P, _C, /* 120-127 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, /* 128-143 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, /* 144-159 */
+ _S | _SP, _P, _P, _P, _P, _P,
+ _P, _P, _P, _P, _P, _P,
+ _P, _P, _P, _P, /* 160-175 */
+ _P, _P, _P, _P, _P, _P,
+ _P, _P, _P, _P, _P, _P,
+ _P, _P, _P, _P, /* 176-191 */
+ _U, _U, _U, _U, _U, _U,
+ _U, _U, _U, _U, _U, _U,
+ _U, _U, _U, _U, /* 192-207 */
+ _U, _U, _U, _U, _U, _U,
+ _U, _P, _U, _U, _U, _U,
+ _U, _U, _U, _L, /* 208-223 */
+ _L, _L, _L, _L, _L, _L,
+ _L, _L, _L, _L, _L, _L,
+ _L, _L, _L, _L, /* 224-239 */
+ _L, _L, _L, _L, _L, _L,
+ _L, _P, _L, _L, _L, _L,
+ _L, _L, _L, _L}; /* 240-255 */
+
+#define __ismask(x) (_ctype[(int)(unsigned char)(x)])
+
+#define isalnum(c) ((__ismask(c) & (_U | _L | _D)) != 0)
+#define isalpha(c) ((__ismask(c) & (_U | _L)) != 0)
+#define iscntrl(c) ((__ismask(c) & (_C)) != 0)
+#define isdigit(c) ((__ismask(c) & (_D)) != 0)
+#define isgraph(c) ((__ismask(c) & (_P | _U | _L | _D)) != 0)
+#define islower(c) ((__ismask(c) & (_L)) != 0)
+#define isprint(c) ((__ismask(c) & (_P | _U | _L | _D | _SP)) != 0)
+#define ispunct(c) ((__ismask(c) & (_P)) != 0)
+#define isspace(c) ((__ismask(c) & (_S)) != 0)
+#define isupper(c) ((__ismask(c) & (_U)) != 0)
+#define isxdigit(c) ((__ismask(c) & (_D | _X)) != 0)
+
+#define isascii(c) (((unsigned char)(c)) <= 0x7f)
+#define toascii(c) (((unsigned char)(c)) & 0x7f)
+
+static inline unsigned char __tolower(unsigned char c)
+{
+ if (isupper(c))
+ {
+ c -= 'A' - 'a';
+ }
+ return c;
+}
+
+static inline unsigned char __toupper(unsigned char c)
+{
+ if (islower(c))
+ {
+ c -= 'a' - 'A';
+ }
+ return c;
+}
+
+#define tolower(c) __tolower(c)
+#define toupper(c) __toupper(c)
diff --git a/kernel/include/drivers/blockdev.h b/kernel/include/drivers/blockdev.h
new file mode 100644
index 0000000..d1b3062
--- /dev/null
+++ b/kernel/include/drivers/blockdev.h
@@ -0,0 +1,99 @@
+/*
+ * FILE: dev_byte.h
+ * DESCR: device management: block-oriented devices
+ */
+
+#pragma once
+
+#include "types.h"
+
+#include "drivers/dev.h"
+#include "util/list.h"
+
+#include "mm/mobj.h"
+#include "mm/page.h"
+
+#define BLOCK_SIZE PAGE_SIZE
+
+struct blockdev_ops;
+
+/*
+ * Represents a Weenix block device.
+ */
+typedef struct blockdev
+{
+ /* Fields that should be initialized by drivers: */
+ devid_t bd_id;
+
+ struct blockdev_ops *bd_ops;
+
+#ifdef NO
+ /* Fields that should be ignored by drivers: */
+ mobj_t bd_mobj;
+#endif
+
+ /* Link on the list of block-oriented devices */
+ list_link_t bd_link;
+} blockdev_t;
+
+typedef struct blockdev_ops
+{
+ /**
+ * Reads a block from the block device. This call will block.
+ *
+ * @param bdev the block device
+ * @param buf the memory into which to read the block (must be
+ * page-aligned)
+ * @param loc the number of the block to start reading from
+ * @param count the number of blocks to read
+ * @return 0 on success, -errno on failure
+ */
+ long (*read_block)(blockdev_t *bdev, char *buf, blocknum_t loc,
+ size_t block_count);
+
+ /**
+ * Writes a block to the block device. This call will block.
+ *
+ * @param bdev the block device
+ * @param buf the memory from which to write the block (must be
+ * page-aligned)
+ * @param loc the number of the block to start writing at
+ * @param count the number of blocks to write
+ * @return 0 on success, -errno on failure
+ */
+ long (*write_block)(blockdev_t *bdev, const char *buf, blocknum_t loc,
+ size_t block_count);
+} blockdev_ops_t;
+
+/**
+ * Initializes the block device subsystem.
+ */
+void blockdev_init(void);
+
+/**
+ * Registers a given block device.
+ *
+ * @param dev the block device to register
+ */
+long blockdev_register(blockdev_t *dev);
+
+/**
+ * Finds a block device with a given device id.
+ *
+ * @param id the device id of the block device to find
+ * @return the block device with the given id if it exists, or NULL if
+ * it cannot be found
+ */
+blockdev_t *blockdev_lookup(devid_t id);
+
+/**
+ * Cleans and frees all resident pages belonging to a given block
+ * device.
+ *
+ * @param dev the block device to flush
+ */
+void blockdev_flush_all(blockdev_t *dev);
+
+// restructure, perhaps, so that these don't have to be exported
+long blockdev_fill_pframe(mobj_t *mobj, pframe_t *pf);
+long blockdev_flush_pframe(mobj_t *mobj, pframe_t *pf); \ No newline at end of file
diff --git a/kernel/include/drivers/chardev.h b/kernel/include/drivers/chardev.h
new file mode 100644
index 0000000..f6083d8
--- /dev/null
+++ b/kernel/include/drivers/chardev.h
@@ -0,0 +1,51 @@
+#pragma once
+
+#include "drivers/dev.h"
+#include "util/list.h"
+
+struct vnode;
+struct pframe;
+
+struct chardev_ops;
+struct mobj;
+
+typedef struct chardev
+{
+ devid_t cd_id;
+ struct chardev_ops *cd_ops;
+ list_link_t cd_link;
+} chardev_t;
+
+typedef struct chardev_ops
+{
+ ssize_t (*read)(chardev_t *dev, size_t pos, void *buf, size_t count);
+
+ ssize_t (*write)(chardev_t *dev, size_t pos, const void *buf, size_t count);
+
+ long (*mmap)(struct vnode *file, struct mobj **ret);
+
+ long (*fill_pframe)(struct vnode *file, struct pframe *pf);
+
+ long (*flush_pframe)(struct vnode *file, struct pframe *pf);
+} chardev_ops_t;
+
+/**
+ * Initializes the byte device subsystem.
+ */
+void chardev_init(void);
+
+/**
+ * Registers the given byte device.
+ *
+ * @param dev the byte device to register
+ */
+long chardev_register(chardev_t *dev);
+
+/**
+ * Finds a byte device with a given device id.
+ *
+ * @param id the device id of the byte device to find
+ * @return the byte device with the given id if it exists, or NULL if
+ * it cannot be found
+ */
+chardev_t *chardev_lookup(devid_t id);
diff --git a/kernel/include/drivers/cmos.h b/kernel/include/drivers/cmos.h
new file mode 100644
index 0000000..bbbc282
--- /dev/null
+++ b/kernel/include/drivers/cmos.h
@@ -0,0 +1,40 @@
+#ifndef CMOS_H
+#define CMOS_H
+
+#include "main/io.h"
+
+// See: https://wiki.osdev.org/CMOS
+#define CMOS_ADDR 0x70
+#define CMOS_DATA 0x71
+
+#define CMOS_REG_SECOND 0x00
+#define CMOS_REG_MINUTE 0x02
+#define CMOS_REG_HOUR 0x04
+#define CMOS_REG_DAY 0x07
+#define CMOS_REG_MONTH 0x08
+#define CMOS_REG_YEAR 0x09
+
+// We're on a modern computer. It'll have a century register.
+#define CMOS_REG_CENTURY 0x32
+#define CMOS_REG_STAT_A 0x0A
+#define CMOS_REG_STAT_B 0x0B
+
+typedef struct rtc_time_t
+{
+ unsigned char second;
+ unsigned char minute;
+ unsigned char hour;
+ unsigned char day;
+ unsigned char month;
+ unsigned int year;
+
+ // Internal use ONLY
+ unsigned int __century;
+} rtc_time_t;
+
+unsigned char cmos_read_register(int reg);
+
+/* Get the time from the CMOS RTC */
+rtc_time_t rtc_get_time();
+
+#endif \ No newline at end of file
diff --git a/kernel/include/drivers/dev.h b/kernel/include/drivers/dev.h
new file mode 100644
index 0000000..883dcba
--- /dev/null
+++ b/kernel/include/drivers/dev.h
@@ -0,0 +1,49 @@
+#pragma once
+
+#include "types.h"
+
+/*
+ * A Weenix "device identifier" is the concatenation of:
+ * - a "driver number" or "device type" (major number)
+ * - a "device number" (minor number)
+ *
+ * The device identifiers for block devices and character devices are
+ * independent. That is, you could have both a block device and a char device
+ * with major 3, minor 5 (for example). They would be distinct.
+ *
+ * Weenix's device number allocation/assignment scheme is as follows:
+ *
+ * - major 0 (byte or block), minor 0: reserved as an analogue of NULL
+ * for device id's
+ *
+ * - char major 1: Memory devices (mem)
+ * - minor 0: /dev/null The null device
+ * - minor 1: /dev/zero The zero device
+ *
+ * - char major 2: TTY devices (tty)
+ * - minor 0: /dev/tty0 First TTY device
+ * - minor 1: /dev/tty1 Second TTY device
+ * - and so on...
+ *
+ * - block major 1: Disk devices
+ * - minor 0: first disk device
+ * - minor 1: second disk device
+ * - and so on...
+ */
+
+#define MINOR_BITS 8
+#define MINOR_MASK ((1U << MINOR_BITS) - 1)
+#define MAJOR(devid) ((unsigned)((devid) >> MINOR_BITS))
+#define MINOR(devid) ((unsigned)((devid)&MINOR_MASK))
+#define MKDEVID(major, minor) ((devid_t)(((major) << MINOR_BITS) | (minor)))
+
+/* convenience definition: the NULL device id: */
+#define NULL_DEVID (MKDEVID(0, 0))
+#define MEM_NULL_DEVID (MKDEVID(1, 0))
+#define MEM_ZERO_DEVID (MKDEVID(1, 1))
+
+#define DISK_MAJOR 1
+
+#define MEM_MAJOR 1
+#define MEM_NULL_MINOR 0
+#define MEM_ZERO_MINOR 1
diff --git a/kernel/include/drivers/disk/ahci.h b/kernel/include/drivers/disk/ahci.h
new file mode 100644
index 0000000..1c7acf6
--- /dev/null
+++ b/kernel/include/drivers/disk/ahci.h
@@ -0,0 +1,325 @@
+#pragma once
+
+#include <types.h>
+
+/* Documents referenced:
+ * ATA Command Set 4:
+ * http://www.t13.org/Documents/UploadedDocuments/docs2016/di529r14-ATAATAPI_Command_Set_-_4.pdf
+ * AHCI SATA 1.3.1:
+ * https://www.intel.com/content/www/us/en/io/serial-ata/serial-ata-ahci-spec-rev1-3-1.html
+ * Serial ATA Revision 2.6:
+ * http://read.pudn.com/downloads157/doc/project/697017/SerialATA_Revision_2_6_Gold.pdf
+ */
+
+/* Macros for working with physical region descriptors. */
+#define AHCI_PRDT_DBC_WIDTH 22
+#define AHCI_MAX_PRDT_SIZE (1 << AHCI_PRDT_DBC_WIDTH)
+#define ATA_SECTOR_SIZE 512
+#define AHCI_SECTORS_PER_PRDT (AHCI_MAX_PRDT_SIZE / ATA_SECTOR_SIZE)
+#define AHCI_MAX_SECTORS_PER_COMMAND \
+ (1 << 16) /* FLAG: Where does this come from? */
+#define ACHI_NUM_PRDTS_PER_COMMAND_TABLE \
+ (AHCI_MAX_SECTORS_PER_COMMAND / AHCI_SECTORS_PER_PRDT)
+
+#define AHCI_MAX_NUM_PORTS 32
+#define AHCI_COMMAND_HEADERS_PER_LIST 32
+
+#define AHCI_COMMAND_LIST_ARRAY_BASE(ahci_base) (ahci_base)
+#define AHCI_COMMAND_LIST_ARRAY_SIZE \
+ (AHCI_MAX_NUM_PORTS * sizeof(command_list_t))
+
+#define AHCI_RECEIVED_FIS_ARRAY_BASE(ahci_base) \
+ ((ahci_base) + AHCI_COMMAND_LIST_ARRAY_SIZE)
+#define AHCI_RECEIVED_FIS_ARRAY_SIZE \
+ (AHCI_MAX_NUM_PORTS * sizeof(received_fis_t))
+
+#define AHCI_COMMAND_TABLE_ARRAY_BASE(ahci_base) \
+ (AHCI_RECEIVED_FIS_ARRAY_BASE(ahci_base) + AHCI_RECEIVED_FIS_ARRAY_SIZE)
+#define AHCI_COMMAND_TABLE_ARRAY_SIZE \
+ (AHCI_MAX_NUM_PORTS * AHCI_COMMAND_HEADERS_PER_LIST * \
+ sizeof(command_table_t))
+
+#define AHCI_SIZE \
+ (AHCI_COMMAND_LIST_ARRAY_SIZE + AHCI_RECEIVED_FIS_ARRAY_SIZE + \
+ AHCI_COMMAND_TABLE_ARRAY_SIZE)
+#define AHCI_SIZE_PAGES ((uintptr_t)PAGE_ALIGN_UP(AHCI_SIZE) / PAGE_SIZE)
+
+#define ALIGN_DOWN_POW_2(x, align) ((x) & -(align))
+#define ALIGN_UP_POW_2(x, align) (ALIGN_DOWN_POW_2((x)-1, align) + (align))
+
+/*=============================
+ * Frame Information Structures
+ *============================*/
+
+/* fis_type_t - FIS types are recognized by an ID.
+ * For more info, see section 10.3 (FIS Types) of Serial ATA Revision 2.6. */
+typedef enum fis_type
+{
+ fis_type_h2d_register = 0x27
+} packed fis_type_t;
+
+/* Command codes used when forming the host-to-device FIS (see: ATA Command Set
+ * 4). The first two are standard commands. The second two are for NCQ commands.
+ */
+#define ATA_READ_DMA_EXT_COMMAND 0x25
+#define ATA_WRITE_DMA_EXT_COMMAND 0x35
+#define ATA_READ_FPDMA_QUEUED_COMMAND 0x60
+#define ATA_WRITE_FPDMA_QUEUED_COMMAND 0x61
+
+/* 8-bit device setting for host-to-device FIS.
+ * Bit 6 is specified as either obsolete or "shall be set to one" for all
+ * commands used in Weenix. So, we can safely just default to this value for all
+ * commands. More info in sections 7.20, 7.21, 7.55, and 7.57 of ATA Command
+ * Set 4. */
+#define ATA_DEVICE_LBA_MODE 0x40
+
+/* h2d_register_fis - Register Host to Device FIS.
+ * This is the only FIS used in Weenix.
+ */
+typedef struct h2d_register_fis
+{
+ uint8_t fis_type; /* Must be set to fis_type_h2d_register. */
+ uint8_t : 7;
+ uint8_t c : 1; /* When set, indicates that this is an FIS for a command.
+ * This is always the case in Weenix. */
+ uint8_t command; /* See command codes further up. */
+ uint8_t
+ features; /* For regular read/write, no use.
+ * For NCQ commands, features and features_exp form the lower
+ * and upper 8 bits of sector count, respectively. */
+ uint32_t lba : 24; /* lba and lba_exp form the lower and upper 24 bits of
+ the first logical block address, respectively. */
+ uint8_t device; /* Device register.
+ * For Weenix's purposes, this should always be set to
+ * ATA_DEVICE_LBA_MODE. */
+ uint32_t lba_exp : 24;
+ uint8_t features_exp;
+ uint16_t sector_count; /* For regular read/write, specifies number of
+ * sectors to read/write.
+ * For NCQ commands, bits 7:3 specify NCQ tag. */
+ uint16_t : 16;
+ uint32_t : 32;
+} packed h2d_register_fis_t;
+
+/*========================
+ * Command List Structures
+ *=======================*/
+
+/* command_fis_t - Represents a software-constructed FIS stored in a
+ * command_table_t. */
+typedef union command_fis {
+ h2d_register_fis_t h2d_register_fis;
+ /* Must occupy 64 bytes in its corresponding command_table_t.
+ * Recall that unions conform to the size of the largest member. */
+ struct
+ {
+ uint8_t size[64];
+ };
+} packed command_fis_t;
+
+/* received_fis_t - Per-port structure that contains information on received
+ * FISes. More info in section 4.2.1 of the 1.3.1 spec. */
+typedef struct received_fis
+{
+ uint8_t _omit[256]; /* Weenix does not make use of any received FIS from the
+ device. */
+} packed received_fis_t;
+
+/* prd_t - Physical Region Descriptor.
+ * Represents an entry in the PRD table in a command table
+ * (command_table_t->prdt). Points to a chunk of system memory for the device to
+ * use according to whatever command it is executing.
+ */
+typedef struct prd
+{
+ uint64_t dba; /* Data Base Address. */
+ uint32_t : 32;
+ uint32_t
+ dbc : 22; /* Data Byte Count: Indicates length of data block in bytes,
+ * but starts counting from 0. Ex: Length 1 is 0x0. Length 2
+ * is 0x1. Length 3 is 0x10. And so on... Must be even. Due to
+ * counting from 0, this means least-significant bit MUST
+ * be 1. Max length is 4MB (all bits set). */
+ uint16_t : 9;
+ uint8_t i : 1; /* Interrupt on Completion: When set, then upon processing
+ * all PRDs in the current FIS, the port will try to generate
+ * an interrupt by setting PxIS.DPS.
+ *
+ * Whether or not this actually behaves as expected, or ever
+ * is even used, is unclear.
+ */
+} packed prd_t;
+
+/* command_table_t - Structure detailing a command and associated data / memory.
+ * More info in section 4.2.3 of SATA AHCI 1.3.1.
+ */
+typedef struct command_table
+{
+ command_fis_t
+ cfis; /* Command FIS: The actual software constructed command. */
+ uint8_t _omit[64];
+ prd_t prdt[ACHI_NUM_PRDTS_PER_COMMAND_TABLE]; /* Physical Region Descriptor
+ * Table: A list of,
+ * theoretically, up to 2^16
+ * entries of PRDs.
+ * Number of actual usable
+ * entries is indicated by
+ * command_header_t->prdtl. */
+} packed command_table_t;
+
+/* command_header_t - Structure detailing command details. Stored in a
+ * command_list_t. More info in section 4.2.2 of the SATA AHCI 1.3.1 spec. */
+typedef struct command_header
+{
+ uint8_t cfl : 5; /* Command FIS length in DW (4 bytes). Max value is 0x10
+ (16). */
+ uint8_t : 1;
+ uint8_t write : 1; /* Write: Set indicates write, clear indicates read. */
+ uint16_t : 9;
+ uint16_t prdtl; /* Physical Region Descriptor Table Length: Number of PRD
+ entries. */
+ uint32_t : 32;
+ uint64_t ctba; /* Command Table Descriptor Base Address: Pointer to the
+ command table. */
+ uint64_t : 64;
+ uint64_t : 64;
+} packed command_header_t;
+
+/* command_list_t - Per-port command list.
+ * More info in section 4.2.2 of the SATA AHCI 1.3.1 spec.
+ * See also: Figure 5: Port System Memory Structures. */
+typedef struct command_list
+{
+ command_header_t command_headers[AHCI_COMMAND_HEADERS_PER_LIST];
+} packed command_list_t;
+
+/*=================
+ * Host Bus Adapter
+ *================*/
+
+/* px_interrupt_status - Per-port bitmap indicating that a corresponding
+ * interrupt has occurred on the port. Observe that this is a union, making
+ * initialization a little easier. */
+typedef union px_interrupt_status {
+ struct
+ {
+ uint8_t dhrs : 1; /* Interrupt requested by a device-to-host FIS.
+ * Used by normal read/write commands, see 5.6.2
+ * in 1.3.1. */
+ uint8_t : 2;
+ uint8_t
+ sdbs : 1; /* Interrupt requested by a set device bits FIS.
+ * Used by NCQ read/write commands, see 5.6.4 in 1.3.1. */
+ uint8_t : 1;
+ uint8_t dps : 1; /* Interrupt set upon completing an FIS that requested
+ * an interrupt upon completion.
+ * Currently doesn't seem to be working... */
+ uint32_t : 26;
+ } bits;
+ uint32_t value;
+} packed px_interrupt_status_t;
+
+/* Observe that, to clear interrupt status, must set to 1. */
+static px_interrupt_status_t px_interrupt_status_clear = {.value =
+ (uint32_t)-1};
+
+/* Port x Interrupt Enable - Bitwise register controlling generation of various
+ * interrupts. */
+typedef union px_interrupt_enable {
+ uint32_t value;
+} packed px_interrupt_enable_t;
+
+/* Weenix uses this to initialize all ports to enable all interrupts by default.
+ */
+static px_interrupt_enable_t px_interrupt_enable_all_enabled = {
+ .value = (uint32_t)-1};
+
+/* hba_ghc_t - Generic Host Control: Information and control registers
+ * pertaining to the entire HBA. More info in section 3.1 of 1.3.1.
+ */
+typedef struct hba_ghc
+{
+ struct
+ {
+ uint32_t : 30;
+ uint8_t sncq : 1; /* Supports Native Command Queueing. */
+ uint8_t : 1;
+ } packed cap;
+ struct
+ {
+ uint8_t : 1;
+ uint8_t ie : 1; /* Interrupt Enable: Enables/disables interrupts from
+ HBA. */
+ uint32_t : 29;
+ uint8_t ae : 1; /* AHCI Enable: Indicates software adheres to AHCI
+ specification. */
+ } packed ghc;
+ uint32_t is; /* Interrupt Status: If bit x is set, then port x has a pending
+ interrupt. */
+ uint32_t pi; /* Ports Implemented: If bit x is set, then port x is available
+ for use. */
+ uint32_t _omit[7];
+} packed hba_ghc_t;
+
+/* Signature for SATA devices. Compare this against hba_port_t->px_sig to
+ * determine if a SATA device is sitting behind a given port. */
+#define SATA_SIG_ATA 0x00000101
+
+/* hba_port - A per-port structure storing port information.
+ * Each port represents a device that the HBA is communicating with (e.g. a
+ * SATA device!). Details not relevant to Weenix have been omitted. More info in
+ * section 3.3 of the SATA AHCI 1.3.1 spec.
+ */
+typedef struct hba_port
+{
+ uint64_t px_clb; /* 1K-byte aligned base physical address of this port's
+ * command list. This is a pointer to a command_list_t. */
+ uint64_t px_fb; /* Base physical address for received FISes.
+ * Weenix never uses received FIS, but we allocate and set
+ * up memory to make the HBA happy. */
+ px_interrupt_status_t px_is; /* Interrupt Status. */
+ px_interrupt_enable_t px_ie; /* Interrupt Enable. */
+ struct
+ {
+ uint8_t st : 1; /* Start: Allows the HBA to process the command list. */
+ uint8_t : 3;
+ uint8_t fre : 1; /* FIS Receive Enable: Allows HBA to post received
+ FISes in px_fb. */
+ uint16_t : 9;
+ uint8_t fr : 1; /* FIS Receive Running: Read-only indicating if FIS
+ Receive DMA is running. */
+ uint8_t cr : 1; /* Command List Running: Read-only indicating if command
+ list DMA is running. */
+ uint16_t : 16;
+ } packed px_cmd; /* Port Command and Status. */
+ uint64_t : 64;
+ uint32_t px_sig; /* Signature: Contains attached device's signature.
+ * SATA devices should have signature SATA_SIG_ATA, defined
+ * above. */
+ uint64_t : 64;
+ uint32_t px_serr; /* SATA Error: Unclear how Weenix is actually making use
+ of this register. */
+ uint32_t px_sact; /* SATA Active: Used for NCQ.
+ * Each bit corresponds to TAG and command slot of an NCQ
+ * command. Must be set by software before issuing a NCQ
+ * for a command slot.
+ */
+ uint32_t px_ci; /* Commands Issued: Software sets bit x if a command x is
+ * ready to be sent. Each bit corresponds to a command slot.
+ * HBA clears bit upon completing a command.
+ */
+ uint32_t _omit[17];
+} packed hba_port_t;
+
+/* Host Bus Adapter - Control block for the device that actually interfaces
+ * between the OS and the SATA disk device. For more info, see section 3 of
+ * the 1.3.1 spec.
+ */
+typedef struct hba
+{
+ hba_ghc_t ghc; /* Generic Host Control. */
+ uint32_t _omit[53];
+ hba_port_t ports[32]; /* Static array of port descriptors. */
+} packed hba_t;
+
+#define PORT_INDEX(hba, port) ((port) - (hba)->ports)
diff --git a/kernel/include/drivers/disk/sata.h b/kernel/include/drivers/disk/sata.h
new file mode 100644
index 0000000..6bdb573
--- /dev/null
+++ b/kernel/include/drivers/disk/sata.h
@@ -0,0 +1,14 @@
+#pragma once
+
+#define SATA_BLOCK_SIZE 4096
+
+#include <drivers/blockdev.h>
+#include <drivers/disk/ahci.h>
+
+void sata_init();
+
+typedef struct ata_disk
+{
+ hba_port_t *port;
+ blockdev_t bdev;
+} ata_disk_t;
diff --git a/kernel/include/drivers/keyboard.h b/kernel/include/drivers/keyboard.h
new file mode 100644
index 0000000..8ac3762
--- /dev/null
+++ b/kernel/include/drivers/keyboard.h
@@ -0,0 +1,43 @@
+#pragma once
+
+#include <types.h>
+
+#define BS 0x08
+#define DEL 0x7F
+#define ESC 0x1B
+#define LF 0x0A
+#define CR 0x0D
+#define SPACE 0x20
+
+// CTRL-D
+#define EOT 0x04
+
+// CTRL-C
+#define ETX 0x03
+
+/* Special stuff for scrolling (note that these only work when ctrl is held) */
+#define SCROLL_UP 0x0e
+#define SCROLL_DOWN 0x1c
+#define SCROLL_UP_PAGE 0x0f
+#define SCROLL_DOWN_PAGE 0x1d
+
+// pretty arbitrarily chosen, just the first extended ASCII code point and on...
+#define F1 ((uint8_t)128)
+#define F2 ((uint8_t)(F1 + 1))
+#define F3 ((uint8_t)(F1 + 2))
+#define F4 ((uint8_t)(F1 + 3))
+#define F5 ((uint8_t)(F1 + 4))
+#define F6 ((uint8_t)(F1 + 5))
+#define F7 ((uint8_t)(F1 + 6))
+#define F8 ((uint8_t)(F1 + 7))
+#define F9 ((uint8_t)(F1 + 8))
+#define F10 ((uint8_t)(F1 + 9))
+#define F11 ((uint8_t)(F1 + 10))
+#define F12 ((uint8_t)(F1 + 11))
+
+typedef void (*keyboard_char_handler_t)(uint8_t);
+
+/**
+ * Initializes the keyboard subsystem.
+ */
+void keyboard_init(keyboard_char_handler_t handler);
diff --git a/kernel/include/drivers/memdevs.h b/kernel/include/drivers/memdevs.h
new file mode 100644
index 0000000..420c5d0
--- /dev/null
+++ b/kernel/include/drivers/memdevs.h
@@ -0,0 +1,6 @@
+#pragma once
+
+/**
+ * Initializes the memdevs subsystem.
+ */
+void memdevs_init(void);
diff --git a/kernel/include/drivers/pcie.h b/kernel/include/drivers/pcie.h
new file mode 100644
index 0000000..83d182f
--- /dev/null
+++ b/kernel/include/drivers/pcie.h
@@ -0,0 +1,112 @@
+#pragma once
+
+#include <util/list.h>
+
+#define PCI_NUM_BUSES 256
+#define PCI_NUM_DEVICES_PER_BUS 32
+#define PCI_NUM_FUNCTIONS_PER_DEVICE 8
+#define PCI_DEVICE_FUNCTION_SIZE 4096
+#define PCI_CAPABILITY_PTR_MASK (0b11111100)
+#define PCI_MSI_CAPABILITY_ID 0x5
+
+// Intel Vol 3A 10.11.1
+//#define MSI_BASE_ADDRESS 0x0FEE0000
+#define MSI_ADDRESS_FOR(destination) \
+ ((uint32_t)((0x0FEE << 20) | ((destination) << 12) | (0b1100)))
+#define MSI_DATA_FOR(vector) ((uint16_t)(0b00000001 << 8) | (vector))
+
+typedef struct pci_capability
+{
+ uint8_t id;
+ uint8_t next_cap;
+ uint16_t control;
+} packed pci_capability_t;
+
+typedef struct msi_capability
+{
+ uint8_t id;
+ uint8_t next_cap;
+ struct
+ {
+ uint8_t msie : 1; // MSI Enable
+ uint8_t mmc : 3; // Multiple Message Capable
+ uint8_t mme : 3; // Multiple Message Enable
+ uint8_t c64 : 1; // 64 Bit Address Capable
+ uint8_t _reserved;
+ } control;
+ union {
+ struct
+ {
+ uint32_t addr;
+ uint16_t data;
+ } ad32;
+ struct
+ {
+ uint64_t addr;
+ uint16_t data;
+ } ad64;
+ } address_data;
+} packed msi_capability_t;
+
+typedef union pcie_device {
+ struct
+ {
+ char data[PCI_DEVICE_FUNCTION_SIZE];
+ } raw;
+ struct
+ {
+ uint16_t vendor_id;
+ uint16_t device_id;
+ uint16_t command;
+ uint16_t status;
+ uint8_t revision_id;
+ uint8_t prog_if;
+ uint8_t subclass;
+ uint8_t class;
+ uint8_t cache_line_size;
+ uint8_t latency_type;
+ uint8_t header_type;
+ uint8_t bist;
+ uint32_t bar[6];
+ uint32_t cardbus_cis_pointer;
+ uint16_t subsystem_vendor_id;
+ uint16_t subsystem_id;
+ uint32_t expansion_rom_base_addr;
+ uint8_t capabilities_ptr;
+ uint8_t _reserved1[7];
+ uint8_t interrupt_line;
+ uint8_t interrupt_pin;
+ uint8_t min_grant;
+ uint8_t max_latency;
+ pci_capability_t pm_capability;
+ uint16_t pmcsr;
+ uint8_t bse;
+ uint8_t data;
+ pci_capability_t msi_capability;
+ uint64_t message_address;
+ uint16_t message_data;
+ uint8_t _reserved2[2];
+ pci_capability_t pe_capability;
+ uint32_t pcie_device_capabilities;
+ uint16_t device_control;
+ uint16_t device_status;
+ uint32_t pcie_link_capabilities;
+ uint16_t link_control;
+ uint16_t link_status;
+ } standard;
+} packed pcie_device_t;
+
+#define PCI_LOOKUP_WILDCARD 0xff
+
+typedef struct pcie_device_wrapper
+{
+ uint8_t class;
+ uint8_t subclass;
+ uint8_t interface;
+ pcie_device_t *dev;
+ list_link_t link;
+} pcie_device_wrapper_t;
+
+void pci_init(void);
+
+pcie_device_t *pcie_lookup(uint8_t class, uint8_t subclass, uint8_t interface);
diff --git a/kernel/include/drivers/screen.h b/kernel/include/drivers/screen.h
new file mode 100644
index 0000000..97f7e2a
--- /dev/null
+++ b/kernel/include/drivers/screen.h
@@ -0,0 +1,72 @@
+#pragma once
+
+#include "types.h"
+
+#ifdef __VGABUF___
+
+#define SCREEN_CHARACTER_WIDTH 9
+#define SCREEN_CHARACTER_HEIGHT 15
+
+typedef union color {
+ struct
+ {
+ uint8_t blue;
+ uint8_t green;
+ uint8_t red;
+ uint8_t alpha;
+ } channels;
+ uint32_t value;
+} packed color_t;
+
+void screen_init();
+
+size_t screen_get_width();
+
+size_t screen_get_height();
+
+size_t screen_get_character_width();
+
+size_t screen_get_character_height();
+
+void screen_draw_string(size_t x, size_t y, const char *s, size_t len,
+ color_t color);
+
+void screen_fill(color_t color);
+
+void screen_fill_rect(size_t x, size_t y, size_t width, size_t height,
+ color_t color);
+
+void screen_draw_rect(size_t x, size_t y, size_t width, size_t height,
+ color_t color);
+
+void screen_copy_rect(size_t fromx, size_t fromy, size_t width, size_t height,
+ size_t tox, size_t toy);
+
+void screen_flush();
+
+void screen_print_shutdown();
+
+#else
+
+#define VGA_WIDTH ((uint16_t)80)
+#define VGA_HEIGHT ((uint16_t)25)
+#define VGA_LINE_SIZE ((size_t)(VGA_WIDTH * sizeof(uint16_t)))
+#define VGA_AREA ((uint16_t)(VGA_WIDTH * VGA_HEIGHT))
+#define VGA_BUFFER_SIZE ((uint16_t)(VGA_WIDTH * VGA_HEIGHT))
+#define VGA_DEFAULT_ATTRIB 0xF
+
+void vga_init();
+
+void vga_write_char_at(size_t row, size_t col, uint16_t v);
+
+void vga_set_cursor(size_t row, size_t col);
+
+void vga_clear_screen();
+
+void screen_print_shutdown();
+
+void vga_enable_cursor();
+
+void vga_disable_cursor();
+
+#endif \ No newline at end of file
diff --git a/kernel/include/drivers/tty/ldisc.h b/kernel/include/drivers/tty/ldisc.h
new file mode 100644
index 0000000..920c816
--- /dev/null
+++ b/kernel/include/drivers/tty/ldisc.h
@@ -0,0 +1,68 @@
+#pragma once
+
+#include "types.h"
+#include <proc/kmutex.h>
+
+#define LDISC_BUFFER_SIZE 128
+
+/**
+ * The line discipline is implemented as a circular buffer containing two
+ * sections: cooked and raw. These sections are tracked by three indices:
+ * ldisc_cooked, ldisc_tail, and ldisc_head.
+ *
+ * New characters (via ldisc_key_pressed) are put at the head position (and the
+ * head is incremented). If a newline is received, cooked is moved up to the head.
+ * Characters are read from tail up until cooked, and the tail is updated
+ * to equal cooked.
+ *
+ * The cooked portion (ready for reading) runs from ldisc_tail (inclusive) to
+ * ldisc_cooked (exclusive). The raw portion (subject to editing) runs from
+ * ldisc_cooked (inclusive) to ldisc_head (exclusive).
+ *
+ * e.g.
+ * [..........t........c...h.......]
+ * (cooked) ^^^^^^^^^
+ * ^^^^ (raw)
+ *
+ * Bear in mind that the buffer is circular, so another possible configuration
+ * might be
+ *
+ * [....h............t......c......]
+ * (cooked) ^^^^^^^
+ * ^^^^ ^^^^^^^ (raw)
+ *
+ * When incrementing the indices, make sure that you take the circularity of
+ * the buffer into account! (Hint: using LDISC_BUFFER_SIZE macro will be helpful.)
+ *
+ * The field ldisc_full is used to indicate when the circular buffer has been
+ * completely filled. This is necessary because there are two possible states
+ * in which cooked == tail == head:
+ *
+ * 1) The buffer is empty, or
+ *
+ * 2) The buffer is full: head has wrapped around and is equal to tail.
+ *
+ * ldisc_full is used to differentiate between these two states.
+ */
+typedef struct ldisc
+{
+ size_t ldisc_cooked; // Cooked is the index after the most last or most recent '\n' in the buffer.
+ size_t ldisc_tail; // Tail is the index from which characters are read by processes
+ size_t ldisc_head; // Head is the index from which new characters are placed
+ char ldisc_full; // Full identifies if the buffer is full
+ // 1 -> full
+ // 0 -> not full
+
+ ktqueue_t ldisc_read_queue; // Queue for threads waiting for data to be read
+ char ldisc_buffer[LDISC_BUFFER_SIZE];
+} ldisc_t;
+
+void ldisc_init(ldisc_t *ldisc);
+
+long ldisc_wait_read(ldisc_t *ldisc);
+
+size_t ldisc_read(ldisc_t *ldisc, char *buf, size_t count);
+
+void ldisc_key_pressed(ldisc_t *ldisc, char c);
+
+size_t ldisc_get_current_line_raw(ldisc_t *ldisc, char *s); \ No newline at end of file
diff --git a/kernel/include/drivers/tty/tty.h b/kernel/include/drivers/tty/tty.h
new file mode 100644
index 0000000..ec22b68
--- /dev/null
+++ b/kernel/include/drivers/tty/tty.h
@@ -0,0 +1,21 @@
+#pragma once
+
+#include "drivers/chardev.h"
+#include "ldisc.h"
+#include "vterminal.h"
+
+#define TTY_MAJOR 2
+#define cd_to_tty(bd) \
+ CONTAINER_OF((bd), tty_t, tty_cdev) // Should this be cd, for chardev?
+
+typedef struct tty
+{
+ vterminal_t tty_vterminal; // the virtual terminal, where the characters will be displayed
+ ldisc_t tty_ldisc; // the line discipline for the tty
+ chardev_t tty_cdev; // the super struct for the tty
+ kmutex_t tty_read_mutex;
+ kmutex_t tty_write_mutex;
+} tty_t;
+
+void tty_init(void);
+
diff --git a/kernel/include/drivers/tty/vterminal.h b/kernel/include/drivers/tty/vterminal.h
new file mode 100644
index 0000000..99123a7
--- /dev/null
+++ b/kernel/include/drivers/tty/vterminal.h
@@ -0,0 +1,249 @@
+#pragma once
+
+#include <drivers/screen.h>
+#include <mm/page.h>
+#include <types.h>
+#include <util/list.h>
+//
+//
+//#define VGA_WIDTH ((uint16_t) 80)
+//#define VGA_HEIGHT ((uint16_t) 25)
+//#define VGA_AREA ((uint16_t) (VGA_WIDTH * VGA_HEIGHT))
+//#define VGA_BUFFER_COUNT ((uint16_t) (1024 * 16))
+//#define VGA_BUFFER_SIZE ((uint16_t) (VGA_BUFFER_COUNT * sizeof(short)))
+//
+//
+//#define SCREEN_GET_FOREGROUND(x) ((uint8_t) (x & 0b00001111))
+//#define SCREEN_GET_BACKGROUND(x) ((uint8_t) (x & 0b01110000))
+//#define SCREEN_MAKE_COLOR(b, f) ((uint8_t) (b << 4) | f)
+//
+//#define SCREEN_DEFAULT_FOREGROUND ((uint8_t) 0xF)
+//#define SCREEN_DEFAULT_BACKGROUND ((uint8_t) 0x0)
+//#define SCREEN_DEFAULT_COLOR SCREEN_MAKE_COLOR(SCREEN_DEFAULT_BACKGROUND,
+//SCREEN_DEFAULT_FOREGROUND)
+
+// typedef struct screen {
+// uint16_t screen_cursor_pos;
+// uint16_t screen_buffer_pos;
+// uint16_t screen_visible_pos;
+// uint8_t screen_current_color;
+//
+// uint16_t *screen_buffer;
+// uint16_t screen_inactive_buffer[VGA_BUFFER_COUNT];
+//} screen_t;
+
+// typedef struct vterminal_char {
+// char c;
+//// color_t foreground;
+//// color_t background;
+//} vterminal_char_t;
+
+#ifdef __VGABUF___
+
+#define VT_PAGES_PER_HISTORY_CHUNK 1
+#define VT_CHARS_PER_HISTORY_CHUNK \
+ (VT_PAGES_PER_HISTORY_CHUNK * PAGE_SIZE - sizeof(list_link_t))
+
+typedef struct vterminal_history_chunk
+{
+ char chars[VT_CHARS_PER_HISTORY_CHUNK];
+ list_link_t link;
+} vterminal_history_chunk_t;
+
+typedef struct vterminal
+{
+ size_t vt_width;
+ size_t vt_height;
+
+ size_t vt_len;
+ list_t vt_history_chunks;
+
+ size_t *vt_line_positions;
+
+ off_t vt_line_offset;
+
+ size_t *vt_line_widths;
+
+ size_t vt_input_pos;
+ size_t vt_cursor_pos;
+} vterminal_t;
+
+void vterminal_init(vterminal_t *vt);
+
+void vterminal_make_active(vterminal_t *vt);
+
+void vterminal_scroll(vterminal_t *vt, long count);
+
+void vterminal_scroll_to_bottom(vterminal_t *t);
+
+void vterminal_clear(vterminal_t *vt);
+
+size_t vterminal_write(vterminal_t *vt, const char *buf, size_t len);
+
+void vterminal_key_pressed(vterminal_t *vt);
+
+#elif 0
+
+struct vt_cursor
+{
+ int y;
+ int x;
+};
+
+struct vt_attributes
+{
+ int underline : 1;
+ int bold : 1;
+ int blink : 1;
+ uint16_t fg;
+ uint16_t bg;
+};
+
+struct vt_char
+{
+ int codepoint;
+ struct vt_attributes attribs;
+};
+
+struct vt_buffer
+{
+ struct vt_char screen[VGA_HEIGHT][VGA_WIDTH];
+ size_t input_position;
+};
+
+typedef struct vterminal
+{
+ size_t height;
+ size_t width;
+ struct vt_cursor cursor;
+ struct vt_cursor saved_cursor;
+ struct vt_attributes current_attribs;
+ struct vt_buffer *active_buffer;
+ struct vt_buffer pri_buffer;
+ struct vt_buffer alt_buffer;
+} vterminal_t;
+
+void vterminal_init(vterminal_t *vt);
+
+void vterminal_make_active(vterminal_t *vt);
+
+void vterminal_scroll(vterminal_t *vt, long count);
+
+void vterminal_clear(vterminal_t *vt);
+
+size_t vterminal_write(vterminal_t *vt, const char *buf, size_t len);
+
+size_t vterminal_echo_input(vterminal_t *vt, const char *buf, size_t len);
+
+void vterminal_key_pressed(vterminal_t *vt);
+
+void vterminal_scroll_to_bottom(vterminal_t *vt);
+
+#endif
+
+#define VTC_DEFAULT_FOREGROUND VTCOLOR_GREY
+#define VTC_DEFAULT_BACKGROUND VTCOLOR_BLACK
+#define VTC_DEFAULT_ATTR \
+ (vtattr_t) { 0, VTC_DEFAULT_FOREGROUND, VTC_DEFAULT_BACKGROUND }
+#define VTC_ANSI_PARSER_STACK_SIZE 8
+
+struct vtconsole;
+
+typedef enum
+{
+ VTCOLOR_BLACK,
+ VTCOLOR_RED,
+ VTCOLOR_GREEN,
+ VTCOLOR_YELLOW,
+ VTCOLOR_BLUE,
+ VTCOLOR_MAGENTA,
+ VTCOLOR_CYAN,
+ VTCOLOR_GREY,
+} vtcolor_t;
+
+typedef enum
+{
+ VTSTATE_ESC,
+ VTSTATE_BRACKET,
+ VTSTATE_ATTR,
+ VTSTATE_ENDVAL,
+} vtansi_parser_state_t;
+
+typedef struct
+{
+ int value;
+ int empty;
+} vtansi_arg_t;
+
+typedef struct
+{
+ vtansi_parser_state_t state;
+ vtansi_arg_t stack[VTC_ANSI_PARSER_STACK_SIZE];
+ int index;
+} vtansi_parser_t;
+
+typedef struct
+{
+ int bright;
+ vtcolor_t fg;
+ vtcolor_t bg;
+} vtattr_t;
+
+typedef struct
+{
+ char c;
+ vtattr_t attr;
+} vtcell_t;
+
+typedef struct
+{
+ int x;
+ int y;
+} vtcursor_t;
+
+typedef void (*vtc_paint_handler_t)(struct vtconsole *vtc, vtcell_t *cell,
+ int x, int y);
+typedef void (*vtc_cursor_handler_t)(struct vtconsole *vtc, vtcursor_t *cur);
+
+typedef struct vtconsole
+{
+ int width;
+ int height;
+
+ vtattr_t attr;
+ vtansi_parser_t ansiparser;
+
+ vtcell_t *buffer;
+ int *tabs;
+ int tab_index;
+ vtcursor_t cursor;
+
+ vtc_paint_handler_t on_paint;
+ vtc_cursor_handler_t on_move;
+} vtconsole_t;
+
+typedef vtconsole_t vterminal_t;
+
+vtconsole_t *vtconsole(vtconsole_t *vtc, int width, int height,
+ vtc_paint_handler_t on_paint,
+ vtc_cursor_handler_t on_move);
+void vtconsole_delete(vtconsole_t *c);
+
+void vtconsole_clear(vtconsole_t *vtc, int fromx, int fromy, int tox, int toy);
+void vtconsole_scroll(vtconsole_t *vtc, int lines);
+void vtconsole_newline(vtconsole_t *vtc);
+
+void vtconsole_putchar(vtconsole_t *vtc, char c);
+void vtconsole_write(vtconsole_t *vtc, const char *buffer, uint32_t size);
+
+size_t vterminal_write(vterminal_t *vt, const char *buf, size_t len);
+
+size_t vterminal_echo_input(vterminal_t *vt, const char *buf, size_t len);
+
+void vterminal_key_pressed(vterminal_t *vt);
+
+void vterminal_scroll_to_bottom(vterminal_t *vt);
+
+void vterminal_init(vterminal_t *vt);
+
+void vterminal_make_active(vterminal_t *vt);
diff --git a/kernel/include/errno.h b/kernel/include/errno.h
new file mode 100644
index 0000000..c9e82c8
--- /dev/null
+++ b/kernel/include/errno.h
@@ -0,0 +1,151 @@
+#pragma once
+
+/* Kernel and user header (via symlink) */
+
+#ifndef __KERNEL__
+#ifndef errno
+#define errno _libc_errno
+#endif
+extern int _libc_errno;
+#endif
+
+#define EPERM 1 /* Operation not permitted */
+#define ENOENT 2 /* No such file or directory */
+#define ESRCH 3 /* No such process */
+#define EINTR 4 /* Interrupted system call */
+#define EIO 5 /* I/O error */
+#define ENXIO 6 /* No such device or address */
+#define E2BIG 7 /* Argument list too long */
+#define ENOEXEC 8 /* Exec format error */
+#define EBADF 9 /* Bad file number */
+#define ECHILD 10 /* No child processes */
+#define EAGAIN 11 /* Try again */
+#define ENOMEM 12 /* Out of memory */
+#define EACCES 13 /* Permission denied */
+#define EFAULT 14 /* Bad address */
+#define ENOTBLK 15 /* Block device required */
+#define EBUSY 16 /* Device or resource busy */
+#define EEXIST 17 /* File exists */
+#define EXDEV 18 /* Cross-device link */
+#define ENODEV 19 /* No such device */
+#define ENOTDIR 20 /* Not a directory */
+#define EISDIR 21 /* Is a directory */
+#define EINVAL 22 /* Invalid argument */
+#define ENFILE 23 /* File table overflow */
+#define EMFILE 24 /* Too many open files */
+#define ENOTTY 25 /* Not a typewriter */
+#define ETXTBSY 26 /* Text file busy */
+#define EFBIG 27 /* File too large */
+#define ENOSPC 28 /* No space left on device */
+#define ESPIPE 29 /* Illegal seek */
+#define EROFS 30 /* Read-only file system */
+#define EMLINK 31 /* Too many links */
+#define EPIPE 32 /* Broken pipe */
+#define EDOM 33 /* Math argument out of domain of func */
+#define ERANGE 34 /* Math result not representable */
+
+#define EDEADLK 35 /* Resource deadlock would occur */
+#define ENAMETOOLONG 36 /* File name too long */
+#define ENOLCK 37 /* No record locks available */
+#define ENOSYS 38 /* Function not implemented */
+#define ENOTEMPTY 39 /* Directory not empty */
+#define ELOOP 40 /* Too many symbolic links encountered */
+#define EWOULDBLOCK EAGAIN /* Operation would block */
+#define ENOMSG 42 /* No message of desired type */
+#define EIDRM 43 /* Identifier removed */
+#define ECHRNG 44 /* Channel number out of range */
+#define EL2NSYNC 45 /* Level 2 not synchronized */
+#define EL3HLT 46 /* Level 3 halted */
+#define EL3RST 47 /* Level 3 reset */
+#define ELNRNG 48 /* Link number out of range */
+#define EUNATCH 49 /* Protocol driver not attached */
+#define ENOCSI 50 /* No CSI structure available */
+#define EL2HLT 51 /* Level 2 halted */
+#define EBADE 52 /* Invalid exchange */
+#define EBADR 53 /* Invalid request descriptor */
+#define EXFULL 54 /* Exchange full */
+#define ENOANO 55 /* No anode */
+#define EBADRQC 56 /* Invalid request code */
+#define EBADSLT 57 /* Invalid slot */
+
+#define EDEADLOCK EDEADLK
+
+#define EBFONT 59 /* Bad font file format */
+#define ENOSTR 60 /* Device not a stream */
+#define ENODATA 61 /* No data available */
+#define ETIME 62 /* Timer expired */
+#define ENOSR 63 /* Out of streams resources */
+#define ENONET 64 /* Machine is not on the network */
+#define ENOPKG 65 /* Package not installed */
+#define EREMOTE 66 /* Object is remote */
+#define ENOLINK 67 /* Link has been severed */
+#define EADV 68 /* Advertise error */
+#define ESRMNT 69 /* Srmount error */
+#define ECOMM 70 /* Communication error on send */
+#define EPROTO 71 /* Protocol error */
+#define EMULTIHOP 72 /* Multihop attempted */
+#define EDOTDOT 73 /* RFS specific error */
+#define EBADMSG 74 /* Not a data message */
+#define EOVERFLOW 75 /* Value too large for defined data type */
+#define ENOTUNIQ 76 /* Name not unique on network */
+#define EBADFD 77 /* File descriptor in bad state */
+#define EREMCHG 78 /* Remote address changed */
+#define ELIBACC 79 /* Can not access a needed shared library */
+#define ELIBBAD 80 /* Accessing a corrupted shared library */
+#define ELIBSCN 81 /* .lib section in a.out corrupted */
+#define ELIBMAX 82 /* Attempting to link in too many shared libraries */
+#define ELIBEXEC 83 /* Cannot exec a shared library directly */
+#define EILSEQ 84 /* Illegal byte sequence */
+#define ERESTART 85 /* Interrupted system call should be restarted */
+#define ESTRPIPE 86 /* Streams pipe error */
+#define EUSERS 87 /* Too many users */
+#define ENOTSOCK 88 /* Socket operation on non-socket */
+#define EDESTADDRREQ 89 /* Destination address required */
+#define EMSGSIZE 90 /* Message too long */
+#define EPROTOTYPE 91 /* Protocol wrong type for socket */
+#define ENOPROTOOPT 92 /* Protocol not available */
+#define EPROTONOSUPPORT 93 /* Protocol not supported */
+#define ESOCKTNOSUPPORT 94 /* Socket type not supported */
+#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */
+#define EPFNOSUPPORT 96 /* Protocol family not supported */
+#define EAFNOSUPPORT 97 /* Address family not supported by protocol */
+#define EADDRINUSE 98 /* Address already in use */
+#define EADDRNOTAVAIL 99 /* Cannot assign requested address */
+#define ENETDOWN 100 /* Network is down */
+#define ENETUNREACH 101 /* Network is unreachable */
+#define ENETRESET 102 /* Network dropped connection because of reset */
+#define ECONNABORTED 103 /* Software caused connection abort */
+#define ECONNRESET 104 /* Connection reset by peer */
+#define ENOBUFS 105 /* No buffer space available */
+#define EISCONN 106 /* Transport endpoint is already connected */
+#define ENOTCONN 107 /* Transport endpoint is not connected */
+#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */
+#define ETOOMANYREFS 109 /* Too many references: cannot splice */
+#define ETIMEDOUT 110 /* Connection timed out */
+#define ECONNREFUSED 111 /* Connection refused */
+#define EHOSTDOWN 112 /* Host is down */
+#define EHOSTUNREACH 113 /* No route to host */
+#define EALREADY 114 /* Operation already in progress */
+#define EINPROGRESS 115 /* Operation now in progress */
+#define ESTALE 116 /* Stale NFS file handle */
+#define EUCLEAN 117 /* Structure needs cleaning */
+#define ENOTNAM 118 /* Not a XENIX named type file */
+#define ENAVAIL 119 /* No XENIX semaphores available */
+#define EISNAM 120 /* Is a named type file */
+#define EREMOTEIO 121 /* Remote I/O error */
+#define EDQUOT 122 /* Quota exceeded */
+
+#define ENOMEDIUM 123 /* No medium found */
+#define EMEDIUMTYPE 124 /* Wrong medium type */
+#define ECANCELED 125 /* Operation Canceled */
+#define ENOKEY 126 /* Required key not available */
+#define EKEYEXPIRED 127 /* Key has expired */
+#define EKEYREVOKED 128 /* Key has been revoked */
+#define EKEYREJECTED 129 /* Key was rejected by service */
+
+/* for robust mutexes */
+#define EOWNERDEAD 130 /* Owner died */
+#define ENOTRECOVERABLE 131 /* State not recoverable */
+
+/* added by dap from Linux */
+#define ENOTSUP EOPNOTSUPP
diff --git a/kernel/include/fs/dirent.h b/kernel/include/fs/dirent.h
new file mode 100644
index 0000000..10fa845
--- /dev/null
+++ b/kernel/include/fs/dirent.h
@@ -0,0 +1,25 @@
+/* dirent.h - filesystem-independent directory entry
+ * mcc, kma, jal
+ */
+#pragma once
+
+/* Kernel and user header (via symlink) */
+
+#ifdef __KERNEL__
+#include "config.h"
+#include "types.h"
+#else
+
+#include "sys/types.h"
+#include "weenix/config.h"
+
+#endif
+
+typedef struct dirent
+{
+ ino_t d_ino; /* entry inode number */
+ off_t d_off; /* seek pointer of next entry */
+ char d_name[NAME_LEN]; /* filename */
+} dirent_t;
+
+#define d_fileno d_ino
diff --git a/kernel/include/fs/fcntl.h b/kernel/include/fs/fcntl.h
new file mode 100644
index 0000000..fd719f2
--- /dev/null
+++ b/kernel/include/fs/fcntl.h
@@ -0,0 +1,18 @@
+/* fcntl.h - File access bits
+ * mcc, jal
+ */
+
+#pragma once
+
+/* Kernel and user header (via symlink) */
+
+/* File access modes for open(). */
+#define O_RDONLY 0
+#define O_WRONLY 1
+#define O_RDWR 2
+#define O_ACCESSMODE_MASK (O_RDONLY | O_WRONLY | O_RDWR)
+
+/* File status flags for open(). */
+#define O_CREAT 0x100 /* Create file if non-existent. */
+#define O_TRUNC 0x200 /* Truncate to zero length. */
+#define O_APPEND 0x400 /* Append to file. */
diff --git a/kernel/include/fs/file.h b/kernel/include/fs/file.h
new file mode 100644
index 0000000..72caee4
--- /dev/null
+++ b/kernel/include/fs/file.h
@@ -0,0 +1,62 @@
+#pragma once
+
+#include "types.h"
+
+#define FMODE_READ 1
+#define FMODE_WRITE 2
+#define FMODE_APPEND 4
+#define FMODE_MAX_VALUE (FMODE_READ | FMODE_WRITE | FMODE_APPEND)
+
+struct vnode;
+
+typedef struct file
+{
+ /*
+ * The current position in the file. Can be modified by system calls
+ * like lseek(2), read(2), and write(2) (and possibly others) as
+ * described in the man pages of those calls.
+ */
+ size_t f_pos;
+
+ /*
+ * The mode in which this file was opened. This is a mask of the flags
+ * FMODE_READ, FMODE_WRITE, and FMODE_APPEND. It is set when the file
+ * is first opened, and use to restrict the operations that can be
+ * performed on the underlying vnode.
+ */
+ unsigned int f_mode;
+
+ /*
+ * The number of references to this struct.
+ */
+ size_t f_refcount;
+
+ /*
+ * The vnode which corresponds to this file.
+ */
+ struct vnode *f_vnode;
+} file_t;
+
+struct file *fcreate(int fd, struct vnode *vnode, unsigned int mode);
+
+/*
+ * Returns the file_t assiciated with the given file descriptor for the
+ * current process. If there is no associated file_t, returns NULL.
+ */
+struct file *fget(int fd);
+
+/*
+ * fref() increments the reference count on the given file.
+ */
+void fref(file_t *file);
+
+/*
+ * fput() decrements the reference count on the given file.
+ *
+ * If the refcount reaches 0, the storage for the given file_t will be
+ * released (f won't point to a valid memory address anymore), and the
+ * refcount on the associated vnode (if any) will be decremented.
+ *
+ * The vnode release operation will also be called if it exists.
+ */
+void fput(file_t **filep);
diff --git a/kernel/include/fs/lseek.h b/kernel/include/fs/lseek.h
new file mode 100644
index 0000000..3520e77
--- /dev/null
+++ b/kernel/include/fs/lseek.h
@@ -0,0 +1,5 @@
+#pragma once
+
+#define SEEK_SET 0
+#define SEEK_CUR 1
+#define SEEK_END 2
diff --git a/kernel/include/fs/open.h b/kernel/include/fs/open.h
new file mode 100644
index 0000000..fd10234
--- /dev/null
+++ b/kernel/include/fs/open.h
@@ -0,0 +1,5 @@
+#pragma once
+
+long do_open(const char *filename, int flags);
+
+long get_empty_fd(int *fd);
diff --git a/kernel/include/fs/pipe.h b/kernel/include/fs/pipe.h
new file mode 100644
index 0000000..61b9cc9
--- /dev/null
+++ b/kernel/include/fs/pipe.h
@@ -0,0 +1,10 @@
+/*
+ * FILE: pipe.h
+ * AUTH: eric
+ * DESC:
+ * DATE: Thu Dec 26 17:07:10 2013
+ */
+
+#pragma once
+
+int do_pipe(int pipefd[2]);
diff --git a/kernel/include/fs/ramfs/ramfs.h b/kernel/include/fs/ramfs/ramfs.h
new file mode 100644
index 0000000..b43f4eb
--- /dev/null
+++ b/kernel/include/fs/ramfs/ramfs.h
@@ -0,0 +1,5 @@
+#pragma once
+
+#include "fs/vfs.h"
+
+long ramfs_mount(struct fs *fs);
diff --git a/kernel/include/fs/s5fs/s5fs.h b/kernel/include/fs/s5fs/s5fs.h
new file mode 100644
index 0000000..7bde185
--- /dev/null
+++ b/kernel/include/fs/s5fs/s5fs.h
@@ -0,0 +1,145 @@
+/*
+ * FILE: s5fs.h
+ * AUTHOR: kma
+ * DESCR: shared structures for the System V file system...
+ */
+
+#pragma once
+
+#ifdef __FSMAKER__
+#include <stdint.h>
+#else
+
+#include "config.h"
+
+#include "drivers/blockdev.h"
+#include "fs/vfs.h"
+#include "fs/vnode.h"
+#include "mm/page.h"
+#include "proc/kmutex.h"
+
+#endif
+
+#define S5_SUPER_BLOCK 0 /* the blockno of the superblock */
+#define S5_IS_SUPER(blkno) ((blkno) == S5_SUPER_BLOCK)
+
+#define S5_NBLKS_PER_FNODE 30
+
+#define S5_BLOCK_SIZE 4096
+#define S5_NDIRECT_BLOCKS 28
+#define S5_INODES_PER_BLOCK (S5_BLOCK_SIZE / sizeof(s5_inode_t))
+#define S5_DIRENTS_PER_BLOCK (S5_BLOCK_SIZE / sizeof(s5_dirent_t))
+#define S5_MAX_FILE_BLOCKS (S5_NDIRECT_BLOCKS + S5_NIDIRECT_BLOCKS)
+#define S5_MAX_FILE_SIZE (S5_MAX_FILE_BLOCKS * S5_BLOCK_SIZE)
+#define S5_NAME_LEN 28
+
+#define S5_TYPE_FREE 0x0
+#define S5_TYPE_DATA 0x1
+#define S5_TYPE_DIR 0x2
+#define S5_TYPE_CHR 0x4
+#define S5_TYPE_BLK 0x8
+
+#define S5_MAGIC 071177
+#define S5_CURRENT_VERSION 3
+
+/* Number of blocks stored in the indirect block */
+#define S5_NIDIRECT_BLOCKS (S5_BLOCK_SIZE / sizeof(uint32_t))
+
+/* Given a file offset, returns the block number that it is in */
+#define S5_DATA_BLOCK(seekptr) ((seekptr) / S5_BLOCK_SIZE)
+
+/* Given a file offset, returns the offset into the pointer's block */
+#define S5_DATA_OFFSET(seekptr) ((seekptr) % S5_BLOCK_SIZE)
+
+/* Given an inode number, tells the block that inode is stored in. */
+#define S5_INODE_BLOCK(inum) ((inum) / S5_INODES_PER_BLOCK + 1)
+
+/*
+ * Given an inode number, tells the offset (in units of s5_inode_t) of
+ * that inode within the block returned by S5_INODE_BLOCK.
+ */
+#define S5_INODE_OFFSET(inum) ((inum) % S5_INODES_PER_BLOCK)
+
+/* Given an FS struct, get the S5FS (private data) struct. */
+#define FS_TO_S5FS(fs) ((s5fs_t *)(fs)->fs_i)
+
+/* each node of the free block list looks like this: */
+/*
+typedef struct s5_fbl_node {
+ int free_blocks[S5_NBLKS_PER_FNODE-1];
+ int more;
+} s5_fbl_node_t;
+*/
+
+/* Note that all on-disk types need to have hard-coded sizes (to ensure
+ * inter-machine compatibility of s5 disks) */
+
+/* The contents of the superblock, as stored on disk. */
+typedef struct s5_super
+{
+ uint32_t s5s_magic; /* the magic number */
+ uint32_t s5s_free_inode; /* the free inode pointer */
+ uint32_t s5s_nfree; /* number of blocks currently in
+ * s5s_free_blocks */
+ /* First "node" of free block list */
+ uint32_t s5s_free_blocks[S5_NBLKS_PER_FNODE];
+
+ uint32_t s5s_root_inode; /* root inode */
+ uint32_t s5s_num_inodes; /* number of inodes */
+ uint32_t s5s_version; /* version of this disk format */
+} s5_super_t;
+
+/* The contents of an inode, as stored on disk. */
+typedef struct s5_inode
+{
+ union {
+ uint32_t s5_next_free; /* inode free list ptr */
+ uint32_t s5_size; /* file size */
+ } s5_un;
+ uint32_t s5_number; /* this inode's number */
+ uint16_t s5_type; /* one of S5_TYPE_{FREE,DATA,DIR,CHR,BLK} */
+ int16_t s5_linkcount; /* link count of this inode */
+ uint32_t s5_direct_blocks[S5_NDIRECT_BLOCKS];
+ uint32_t s5_indirect_block;
+} s5_inode_t;
+
+typedef struct s5_node
+{
+ vnode_t vnode;
+ s5_inode_t inode;
+ long dirtied_inode;
+} s5_node_t;
+
+#define VNODE_TO_S5NODE(vn) CONTAINER_OF(vn, s5_node_t, vnode)
+
+/* The contents of a directory entry, as stored on disk. */
+typedef struct s5_dirent
+{
+ uint32_t s5d_inode;
+ char s5d_name[S5_NAME_LEN];
+} s5_dirent_t;
+
+#ifndef __FSMAKER__
+/* Our in-memory representation of a s5fs filesytem (fs_i points to this) */
+typedef struct s5fs
+{
+ blockdev_t *s5f_bdev;
+ s5_super_t s5f_super;
+ kmutex_t s5f_mutex;
+ fs_t *s5f_fs;
+#ifndef OLD
+ mobj_t s5f_mobj;
+#endif
+} s5fs_t;
+
+long s5fs_mount(struct fs *fs);
+
+void s5_get_meta_disk_block(s5fs_t *s5fs, uint64_t blocknum, long forwrite,
+ pframe_t **pfp);
+
+//void s5_get_file_disk_block(vnode_t *vnode, blocknum_t blocknum, long forwrite,
+// pframe_t **pfp);
+
+void s5_release_disk_block(pframe_t **pfp);
+
+#endif
diff --git a/kernel/include/fs/s5fs/s5fs_privtest.h b/kernel/include/fs/s5fs/s5fs_privtest.h
new file mode 100644
index 0000000..38278ef
--- /dev/null
+++ b/kernel/include/fs/s5fs/s5fs_privtest.h
@@ -0,0 +1,6 @@
+#ifndef __S5FS_PRIVTEST_H
+#define __S5FS_PRIVTEST_H
+
+int s5fs_start(const char *testroot);
+
+#endif
diff --git a/kernel/include/fs/s5fs/s5fs_subr.h b/kernel/include/fs/s5fs/s5fs_subr.h
new file mode 100644
index 0000000..ff4c570
--- /dev/null
+++ b/kernel/include/fs/s5fs/s5fs_subr.h
@@ -0,0 +1,53 @@
+/*
+ * FILE: s5fs_subr.h
+ * AUTHOR: afenn
+ * DESCR: S5 low-level subroutines
+ */
+
+#pragma once
+
+#include "types.h"
+#include "mm/pframe.h"
+#include "fs/s5fs/s5fs.h"
+
+struct s5fs;
+struct s5_node;
+
+long s5_alloc_inode(struct s5fs *s5fs, uint16_t type, devid_t devid);
+
+void s5_free_inode(struct s5fs *s5fs, ino_t ino);
+
+ssize_t s5_read_file(struct s5_node *sn, size_t pos, char *buf, size_t len);
+
+ssize_t s5_write_file(struct s5_node *sn, size_t pos, const char *buf,
+ size_t len);
+
+long s5_link(struct s5_node *dir, const char *name, size_t namelen,
+ struct s5_node *child);
+
+long s5_find_dirent(struct s5_node *dir, const char *name, size_t namelen,
+ size_t *filepos);
+
+void s5_remove_dirent(struct s5_node *dir, const char *name, size_t namelen,
+ struct s5_node *ent);
+
+void s5_replace_dirent(struct s5_node *sn, const char *name, size_t namelen,
+ struct s5_node *old, struct s5_node *new);
+
+long s5_file_block_to_disk_block(struct s5_node *sn, size_t file_blocknum,
+ int alloc, int *new);
+
+long s5_inode_blocks(struct s5_node *vnode);
+
+void s5_remove_blocks(struct s5_node *vnode);
+
+/* Converts a vnode_t* to the s5fs_t* (s5fs file system) struct */
+#define VNODE_TO_S5FS(vn) ((s5fs_t *)((vn)->vn_fs->fs_i))
+
+#ifdef OLD
+/* Converts an s5fs_t* to its memory object (the memory object of the block device) */
+#define S5FS_TO_VMOBJ(s5fs) (&(s5fs)->s5f_bdev->bd_mobj)
+#endif
+
+
+pframe_t *s5_cache_and_clear_block(mobj_t *mo, long block, long loc);
diff --git a/kernel/include/fs/stat.h b/kernel/include/fs/stat.h
new file mode 100644
index 0000000..08e477d
--- /dev/null
+++ b/kernel/include/fs/stat.h
@@ -0,0 +1,44 @@
+/*
+ * FILE: stat.h
+ * AUTH: mcc
+ * DESC:
+ * DATE: Fri Mar 13 23:10:46 1998
+ */
+
+#pragma once
+
+/* Kernel and user header (via symlink) */
+
+typedef struct stat
+{
+ int st_mode;
+ int st_ino;
+ int st_dev;
+ int st_rdev;
+ int st_nlink;
+ int st_uid;
+ int st_gid;
+ int st_size;
+ int st_atime;
+ int st_mtime;
+ int st_ctime;
+ int st_blksize;
+ int st_blocks;
+} stat_t;
+
+/* vnode vn_mode masks */
+
+#define S_IFCHR 0x0100 /* character special */
+#define S_IFDIR 0x0200 /* directory */
+#define S_IFBLK 0x0400 /* block special */
+#define S_IFREG 0x0800 /* regular */
+#define S_IFLNK 0x1000 /* symlink */
+#define S_IFIFO 0x2000 /* fifo/pipe */
+
+#define _S_TYPE(m) ((m)&0xFF00)
+#define S_ISCHR(m) (_S_TYPE(m) == S_IFCHR)
+#define S_ISDIR(m) (_S_TYPE(m) == S_IFDIR)
+#define S_ISBLK(m) (_S_TYPE(m) == S_IFBLK)
+#define S_ISREG(m) (_S_TYPE(m) == S_IFREG)
+#define S_ISLNK(m) (_S_TYPE(m) == S_IFLNK)
+#define S_ISFIFO(m) (_S_TYPE(m) == S_IFIFO)
diff --git a/kernel/include/fs/vfs.h b/kernel/include/fs/vfs.h
new file mode 100644
index 0000000..23f418a
--- /dev/null
+++ b/kernel/include/fs/vfs.h
@@ -0,0 +1,162 @@
+#pragma once
+
+#include "types.h"
+
+#include "fs/open.h"
+#include "proc/kmutex.h"
+#include "util/list.h"
+
+struct vnode;
+struct file;
+struct vfs;
+struct fs;
+struct slab_allocator;
+
+/* name_match: fname should be null-terminated, name is namelen long */
+#define name_match(fname, name, namelen) \
+ (strlen(fname) == namelen && !strncmp((fname), (name), (namelen)))
+
+typedef struct fs_ops
+{
+ /*
+ * Initialize vn_ops, vn_mode, vn_devid and vn_len.
+ * If the filesystem wishes, it may initialize and use vn_i.
+ */
+ void (*read_vnode)(struct fs *fs, struct vnode *vn);
+
+ /*
+ * Called when the vnode's reference count drops to 0.
+ * Perform any necessary cleanup for the corresponding inode.
+ */
+ void (*delete_vnode)(struct fs *fs, struct vnode *vn);
+
+ /*
+ * Optional. Default behavior is to vput() fs_root.
+ * Unmount the filesystem, performing any desired sanity checks
+ * and/or necessary cleanup.
+ * Return 0 on success; negative number on error.
+ */
+ long (*umount)(struct fs *fs);
+
+ void (*sync)(struct fs *fs);
+} fs_ops_t;
+
+#ifndef STR_MAX
+#define STR_MAX 32
+#endif
+
+/* similar to Linux's super_block. */
+typedef struct fs
+{
+ /*
+ * The string name of the device from which this file system should
+ * be mounted. This may be used by the mount function of some file
+ * systems which need to know which device they are mounting.
+ */
+ char fs_dev[STR_MAX];
+ /*
+ * The type of file system this structure represents (given as a
+ * well-defined string). This is used by the generic VFS mount
+ * function to decide which filesystem-specific mount function to
+ * call. Valid values are hard-coded in vfs.c.
+ */
+ char fs_type[STR_MAX];
+
+#ifdef __MOUNTING__
+ /*
+ * If mounting is implemented then this should point to the vnode
+ * of the file that this file system is mounted on. For the root file
+ * system this will just point to the root of that file system.
+ */
+ struct vnode *fs_mtpt;
+
+ /*
+ * An identifier for the mounted file system. This should be enlisted
+ * by the the kernel to keep track of all mounted file systems.
+ */
+ list_link_t fs_link;
+#endif
+
+ /*
+ * The following members are initialized by the filesystem
+ * implementation's mount routine:
+ */
+
+ /*
+ * The struct of operations that define which filesystem-specific
+ * functions to call to perform filesystem manipulation.
+ */
+ fs_ops_t *fs_ops;
+
+ /*
+ * The root vnode for this filesystem (not to be confused with
+ * either / (the root of VFS) or the vnode where the filesystem is
+ * mounted, which is on a different file system.
+ */
+ struct vnode *fs_root;
+
+ /* Filesystem-specific data. */
+ void *fs_i;
+
+ struct slab_allocator *fs_vnode_allocator;
+ list_t vnode_list;
+ kmutex_t vnode_list_mutex;
+ kmutex_t vnode_rename_mutex;
+
+} fs_t;
+
+/* - this is the vnode on which we will mount the vfsroot fs.
+ */
+extern fs_t vfs_root_fs;
+
+void do_sync();
+
+/* VFS {{{ */
+/*
+ * - called by the init process at system shutdown
+ * - at this point, init process is the only process running
+ * => so, there should be no "live" vnodes
+ *
+ * unmount the root filesystem (and first unmount any filesystems mounted
+ * on the root filesystem in the proper order (bottom up)).
+ *
+ */
+
+/* VFS }}} */
+/* VFS Shutdown: */
+/*
+ * Called by the init process at system shutdown.
+ *
+ * At this point, the init process is the only process running
+ * => so, there should be no "live" vnodes
+ */
+long vfs_shutdown();
+
+/* Pathname resolution: */
+/* (the corresponding definitions live in namev.c) */
+long namev_lookup(struct vnode *dir, const char *name, size_t namelen,
+ struct vnode **out);
+
+long namev_dir(struct vnode *base, const char *path, struct vnode **res_vnode,
+ const char **name, size_t *namelen);
+
+long namev_open(struct vnode *base, const char *path, int oflags, int mode,
+ devid_t devid, struct vnode **res_vnode);
+
+long namev_resolve(struct vnode *base, const char *path,
+ struct vnode **res_vnode);
+
+long namev_get_child(struct vnode *dir, char *name, size_t namelen,
+ struct vnode **out);
+
+long namev_get_parent(struct vnode *dir, struct vnode **out);
+
+long namev_is_descendant(struct vnode *a, struct vnode *b);
+
+#ifdef __GETCWD__
+long lookup_name(struct vnode *dir, struct vnode *entry, char *buf,
+ size_t size);
+long lookup_dirpath(struct vnode *dir, char *buf, size_t size);
+#endif /* __GETCWD__ */
+
+long mountfunc(fs_t *fs);
diff --git a/kernel/include/fs/vfs_privtest.h b/kernel/include/fs/vfs_privtest.h
new file mode 100644
index 0000000..1b5fb0b
--- /dev/null
+++ b/kernel/include/fs/vfs_privtest.h
@@ -0,0 +1,3 @@
+#pragma once
+
+void vfs_privtest(void);
diff --git a/kernel/include/fs/vfs_syscall.h b/kernel/include/fs/vfs_syscall.h
new file mode 100644
index 0000000..c5be65d
--- /dev/null
+++ b/kernel/include/fs/vfs_syscall.h
@@ -0,0 +1,39 @@
+#pragma once
+
+#include "dirent.h"
+
+#include "types.h"
+
+#include "fs/open.h"
+#include "fs/pipe.h"
+#include "fs/stat.h"
+
+long do_close(int fd);
+
+ssize_t do_read(int fd, void *buf, size_t len);
+
+ssize_t do_write(int fd, const void *buf, size_t len);
+
+long do_dup(int fd);
+
+long do_dup2(int ofd, int nfd);
+
+long do_mknod(const char *path, int mode, devid_t devid);
+
+long do_mkdir(const char *path);
+
+long do_rmdir(const char *path);
+
+long do_unlink(const char *path);
+
+long do_link(const char *oldpath, const char *newpath);
+
+long do_rename(const char *oldpath, const char *newpath);
+
+long do_chdir(const char *path);
+
+ssize_t do_getdent(int fd, struct dirent *dirp);
+
+off_t do_lseek(int fd, off_t offset, int whence);
+
+long do_stat(const char *path, struct stat *uf);
diff --git a/kernel/include/fs/vnode.h b/kernel/include/fs/vnode.h
new file mode 100644
index 0000000..ff4b9be
--- /dev/null
+++ b/kernel/include/fs/vnode.h
@@ -0,0 +1,358 @@
+/*
+ * FILE: vnode.h
+ * AUTH: mcc
+ * DESC:
+ * DATE: Fri Mar 13 18:54:11 1998
+ * $Id: vnode.h,v 1.2.2.2 2006/06/04 01:02:32 afenn Exp $
+ */
+
+#pragma once
+
+#include "drivers/blockdev.h"
+#include "drivers/chardev.h"
+#include "drivers/dev.h"
+#include "mm/mobj.h"
+#include "mm/pframe.h"
+#include "proc/kmutex.h"
+#include "util/list.h"
+
+struct fs;
+struct dirent;
+struct stat;
+struct file;
+struct vnode;
+struct kmutex;
+
+#define VNODE_LOADING 0
+#define VNODE_LOADED 1
+
+typedef struct vnode_ops
+{
+ /* The following functions map directly to their corresponding
+ * system calls. Unless otherwise noted, they return 0 on
+ * success, and -errno on failure.
+ */
+
+ /* Operations that can be performed on non-directory files: */
+ /*
+ * read transfers at most count bytes from file into buf. It
+ * begins reading from the file at pos bytes into the file. On
+ * success, it returns the number of bytes transferred, or 0 if the
+ * end of the file has been reached (pos >= file->vn_len).
+ */
+ ssize_t (*read)(struct vnode *file, size_t pos, void *buf, size_t count);
+
+ /*
+ * write transfers count bytes from buf into file. It begins
+ * writing at pos bytes into the file. If offset+count extends
+ * past the end of the file, the file's length will be increased.
+ * If offset is before the end of the file, the existing data is
+ * overwritten. On success, it returns the number of bytes
+ * transferred.
+ */
+ ssize_t (*write)(struct vnode *file, size_t pos, const void *buf,
+ size_t count);
+
+ /*
+ * Implementations should supply an mobj through the "ret"
+ * argument (not by setting vma->vma_obj). If for any reason
+ * this cannot be done an appropriate error code should be
+ * returned instead.
+ */
+ long (*mmap)(struct vnode *file, struct mobj **ret);
+
+ /* Operations that can be performed on directory files: */
+
+ /*
+ * mknod creates a special specified by name and namelen in the
+ * directory pointed to by dir with the specified mode and devid.
+ *
+ * Upon success, ret must point to the newly created file.
+ */
+ long (*mknod)(struct vnode *dir, const char *name, size_t namelen, int mode,
+ devid_t devid, struct vnode **ret);
+
+ /*
+ * lookup attempts to find the file specified by name and namelen in the
+ * directory pointed to by dir.
+ *
+ * Upon success, ret must point to the child vnode.
+ */
+ long (*lookup)(struct vnode *dir, const char *name, size_t namelen,
+ struct vnode **out);
+
+ /*
+ * Creates a directory entry in dir specified by name and namelen pointing
+ * to the inode of target.
+ */
+ long (*link)(struct vnode *dir, const char *name, size_t namelen,
+ struct vnode *target);
+
+ /*
+ * unlink removes the directory entry in dir corresponding to the file
+ * specified by name and namelen.
+ */
+ long (*unlink)(struct vnode *dir, const char *name, size_t namelen);
+
+ /*
+ * rename
+ */
+ long (*rename)(struct vnode *olddir, const char *oldname, size_t oldnamelen,
+ struct vnode *newdir, const char *newname,
+ size_t newnamelen);
+
+ /*
+ * mkdir creates a directory specified by name and namelen in the
+ * directory pointed to by out.
+ *
+ * Upon success, out must point to the newly created directory.
+ * Upon failure, out must be unchanged.
+ */
+ long (*mkdir)(struct vnode *dir, const char *name, size_t namelen,
+ struct vnode **out);
+
+ /*
+ * rmdir removes the directory specified by name and namelen from dir.
+ * The directory to be removed must be empty: the only directory entries
+ * must be "." and "..".
+ */
+ long (*rmdir)(struct vnode *dir, const char *name, size_t namelen);
+
+ /*
+ * readdir reads one directory entry from the dir into the struct
+ * dirent. On success, it returns the amount that offset should be
+ * increased by to obtain the next directory entry with a
+ * subsequent call to readdir. If the end of the file as been
+ * reached (offset == file->vn_len), no directory entry will be
+ * read and 0 will be returned.
+ */
+ ssize_t (*readdir)(struct vnode *dir, size_t pos, struct dirent *d);
+
+ /* Operations that can be performed on any type of "file" (
+ * includes normal file, directory, block/byte device */
+ /*
+ * stat sets the fields in the given buf, filling it with
+ * information about file.
+ */
+ long (*stat)(struct vnode *vnode, struct stat *buf);
+
+ /*
+ * acquire is called on a vnode when a file takes its first
+ * reference to the vnode. The file is passed in.
+ */
+ long (*acquire)(struct vnode *vnode, struct file *file);
+
+ /*
+ * release is called on a vnode when the refcount of a file
+ * descriptor that has it open comes down to 0. Each call to
+ * acquire has exactly one matching call to release with the
+ * same file that was passed to acquire.
+ */
+ long (*release)(struct vnode *vnode, struct file *file);
+
+ long (*get_pframe)(struct vnode *vnode, size_t pagenum, long forwrite,
+ pframe_t **pfp);
+
+ /*
+ * Read the page of 'vnode' containing 'offset' into the
+ * page-aligned and page-sized buffer pointed to by
+ * 'buf'.
+ */
+ long (*fill_pframe)(struct vnode *vnode, pframe_t *pf);
+
+ /*
+ * Write the contents of the page-aligned and page-sized
+ * buffer pointed to by 'buf' to the page of 'vnode'
+ * containing 'offset'.
+ */
+ long (*flush_pframe)(struct vnode *vnode, pframe_t *pf);
+
+ /*
+ * This will truncate the file to have a length of zero
+ * Should only be used on regular files, not directories.
+ */
+ void (*truncate_file)(struct vnode *vnode);
+} vnode_ops_t;
+
+typedef struct vnode
+{
+ /*
+ * Function pointers to the implementations of file operations (the
+ * functions are provided by the filesystem implementation).
+ */
+ struct vnode_ops *vn_ops;
+
+ /*
+ * The filesystem to which this vnode belongs. This is initialized by
+ * the VFS subsystem when the vnode is first created and should never
+ * change.
+ */
+ struct fs *vn_fs;
+
+#ifdef __MOUNTING__
+ /* This field is used only for implementing mount points (not required) */
+ /* This field points the the root of the file system mounted at
+ * this vnode. If no file system is mounted at this point this is a
+ * self pointer (i.e. vn->vn_mount = vn). See vget for why this is
+ * makes things easier for us. */
+ struct vnode *vn_mount;
+#endif
+
+ /*
+ * The object responsible for managing the memory where pages read
+ * from this file reside. The VFS subsystem may use this field, but it
+ * does not need to create it.
+ */
+ struct mobj vn_mobj;
+
+ /*
+ * A number which uniquely identifies this vnode within its filesystem.
+ * (Similar and usually identical to what you might know as the inode
+ * number of a file).
+ */
+ ino_t vn_vno;
+
+ /*
+ * File type. See stat.h.
+ */
+ int vn_mode;
+
+ /*
+ * Length of file. Initialized at the fs-implementation-level (in the
+ * 'read_vnode' fs_t entry point). Maintained at the filesystem
+ * implementation level (within the implementations of relevant vnode
+ * entry points).
+ */
+ size_t vn_len;
+
+ /*
+ * A generic pointer which the file system can use to store any extra
+ * data it needs.
+ */
+ void *vn_i;
+
+ /*
+ * The device identifier.
+ * Only relevant to vnodes representing device files.
+ */
+ devid_t vn_devid;
+
+ /*
+ * The state of the vnode. Can either be loading or loaded. The vnode
+ * cannot be used until the vnode is in the loaded state. Potential
+ * users should wait on `vn_waitq` if the vnode is being loaded.
+ * This field is protected by the 'vn_state_lock'.
+ */
+ int vn_state;
+
+ /*
+ * Allows vnode users to wait on the vnode, until the vnode is ready.
+ */
+ ktqueue_t vn_waitq;
+
+ union {
+ chardev_t *chardev;
+ blockdev_t *blockdev;
+ } vn_dev;
+
+ /* Used (only) by the v{get,ref,put} facilities (vfs/vnode.c): */
+ list_link_t vn_link; /* link on system vnode list */
+} vnode_t;
+
+void init_special_vnode(vnode_t *vn);
+
+/* Core vnode management routines: */
+/*
+ * Obtain a vnode representing the file that filesystem 'fs' identifies
+ * by inode number 'vnum'; returns the vnode_t corresponding to the
+ * given filesystem and vnode number. If a vnode for the given file
+ * already exists (it already has an entry in the system inode table) then
+ * the reference count of that vnode is incremented and it is returned.
+ * Otherwise a new vnode is created in the system inode table with a
+ * reference count of 1.
+ * This function has no unsuccessful return.
+ *
+ * MAY BLOCK.
+ */
+struct vnode *vget(struct fs *fs, ino_t vnum);
+
+/*
+ * Lock a vnode (locks vn_mobj).
+ */
+void vlock(vnode_t *vn);
+
+/*
+ * Lock two vnodes in order! This prevents the A/B locking problem when locking
+ * two directories or two files.
+ */
+void vlock_in_order(vnode_t *a, vnode_t *b);
+
+/*
+ * Acquires a vnode locked (see vget above)
+ */
+vnode_t *vget_locked(struct fs *fs, ino_t ino);
+
+/**
+ * Unlock and put a vnode (see vput)
+ */
+void vput_locked(struct vnode **vnp);
+
+/**
+ * Unlocks a vnode
+ */
+void vunlock(vnode_t *vn);
+
+/**
+ * Unlocks two vnodes (effectively just 2 unlocks)
+ */
+void vunlock_in_order(vnode_t *a, vnode_t *b);
+
+/*
+ * Increments the reference count of the provided vnode
+ * (i.e. the refcount of vn_mobj).
+ */
+void vref(vnode_t *vn);
+
+/*
+ * This function decrements the reference count on this vnode
+ * (i.e. the refcount of vn_mobj).
+ *
+ * If, as a result of this, refcount reaches zero, the underlying
+ * fs's 'delete_vnode' entry point will be called and the vnode will be
+ * freed.
+ *
+ * If the linkcount of the corresponding on inode on the filesystem is zero,
+ * then the inode will be freed.
+ *
+ */
+void vput(vnode_t **vnp);
+
+/* Auxilliary: */
+
+/* Unmounting (shutting down the VFS) is the primary reason for the
+ * existence of the following three routines (when unmounting an s5 fs,
+ * they are used in the order that they are listed here): */
+/*
+ * Checks to see if there are any actively-referenced vnodes
+ * belonging to the specified filesystem.
+ * Returns -EBUSY if there is at least one such actively-referenced
+ * vnode, and 0 otherwise.
+ *
+ */
+long vfs_is_in_use(struct fs *fs);
+
+/*
+ * Returns the number of vnodes from this filesystem that are in
+ * use.
+ */
+size_t vfs_count_active_vnodes(struct fs *fs);
+
+/* Diagnostic: */
+/*
+ * Prints the vnodes that are in use. Specifying a fs_t will restrict
+ * the vnodes to just that fs. Specifying NULL will print all vnodes
+ * in the entire system.
+ *
+ * Note that this is currently unimplemented.
+ */
+void vnode_print(struct fs *fs);
diff --git a/kernel/include/fs/vnode_specials.h b/kernel/include/fs/vnode_specials.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/kernel/include/fs/vnode_specials.h
diff --git a/kernel/include/globals.h b/kernel/include/globals.h
new file mode 100644
index 0000000..42d4275
--- /dev/null
+++ b/kernel/include/globals.h
@@ -0,0 +1,11 @@
+#pragma once
+
+#include "main/smp.h"
+#include "proc/kthread.h"
+#include "proc/proc.h"
+
+#define CORE_SPECIFIC_DATA __attribute__((section(".csd"))) = {0}
+
+extern core_t curcore;
+extern proc_t *curproc;
+extern kthread_t *curthr;
diff --git a/kernel/include/kernel.h b/kernel/include/kernel.h
new file mode 100644
index 0000000..c3f7827
--- /dev/null
+++ b/kernel/include/kernel.h
@@ -0,0 +1,79 @@
+#pragma once
+
+#include "types.h"
+
+/* The linker script will initialize these symbols. Note
+ * that the linker does not actually allocate any space
+ * for these variables (thus the void type) it only sets
+ * the address that the symbol points to. So for example
+ * the address where the kernel ends is &kernel_end,
+ * NOT kernel_end.
+ */
+extern void *setup_end;
+extern void *kernel_start;
+extern void *kernel_start_text;
+extern void *kernel_start_data;
+extern void *kernel_start_bss;
+extern void *kernel_end;
+extern void *kernel_end_text;
+extern void *kernel_end_data;
+extern void *kernel_end_bss;
+extern void *kernel_start_init;
+extern void *kernel_end_init;
+
+extern void *kernel_phys_base;
+extern void *kernel_phys_end;
+
+#define inline __attribute__((always_inline, used))
+#define noreturn __attribute__((noreturn))
+
+#define offsetof(type, member) \
+ ((uintptr_t)((char *)&((type *)(0))->member - (char *)0))
+
+#define NOT_YET_IMPLEMENTED(f) \
+ dbg(DBG_PRINT, "Not yet implemented: %s, file %s, line %d\n", f, __FILE__, \
+ __LINE__)
+
+#ifndef MIN
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#endif
+#ifndef MAX
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+#endif
+
+#define CONTAINER_OF(obj, type, member) \
+ ((type *)((char *)(obj)-offsetof(type, member)))
+
+/* This truly atrocious macro hack taken from the wikipedia article on the C
+ * preprocessor, use to "quote" the value (or name) of another macro:
+ * QUOTE_BY_NAME(NTERMS) -> "NTERMS"
+ * QUOTE(NTERMS) -> "3"
+ *
+ * These macros even made more atrocious by searching for "stringizing operator
+ * comma". The variable length macros account for comma separated symbols.
+ */
+#define QUOTE_BY_NAME(...) #__VA_ARGS__
+#define QUOTE_BY_VALUE(x) QUOTE_BY_NAME(x)
+/* By default, we quote by value */
+#define QUOTE(...) QUOTE_BY_NAME(__VA_ARGS__)
+
+#if 0
+#ifndef __DRIVERS__
+#define __DRIVERS__
+#endif
+#ifndef __VFS__
+#define __VFS__
+#endif
+#ifndef __S5FS__
+#define __S5FS__
+#endif
+#ifndef __VM__
+#define __VM__
+#endif
+#ifndef __NTERMS__
+#define __NTERMS__ 3
+#endif
+#ifndef __NDISKS__
+#define __NDISKS__ 1
+#endif
+#endif \ No newline at end of file
diff --git a/kernel/include/limits.h b/kernel/include/limits.h
new file mode 100644
index 0000000..6db9a7e
--- /dev/null
+++ b/kernel/include/limits.h
@@ -0,0 +1,18 @@
+#pragma once
+
+#define CHAR_BIT 8
+#define CHAR_MAX UCHAR_MAX
+#define UCHAR_MAX ((unsigned char)(~0U))
+#define SCHAR_MAX ((signed char)(UCHAR_MAX >> 1))
+#define SCHAR_MIN (-SCHAR_MAX - 1)
+#define USHRT_MAX ((unsigned short)(~0U))
+#define SHRT_MAX ((signed short)(USHRT_MAX >> 1))
+#define SHRT_MIN (-SHRT_MAX - 1)
+#define UINT_MAX ((unsigned int)(~0U))
+#define INT_MAX ((signed int)(UINT_MAX >> 1))
+#define INT_MIN (-INT_MAX - 1)
+#define ULONG_MAX ((unsigned long)(~0UL))
+#define LONG_MAX ((signed long)(ULONG_MAX >> 1))
+#define LONG_MIN (-LONG_MAX - 1)
+
+#define UPTR_MAX ULONG_MAX
diff --git a/kernel/include/main/acpi.h b/kernel/include/main/acpi.h
new file mode 100644
index 0000000..dc49805
--- /dev/null
+++ b/kernel/include/main/acpi.h
@@ -0,0 +1,20 @@
+#pragma once
+
+#include <types.h>
+
+typedef struct acpi_header
+{
+ uint32_t ah_sign;
+ uint32_t ah_size;
+ uint8_t ah_rev;
+ uint8_t ah_checksum;
+ uint8_t ah_oemid[6];
+ uint8_t ah_tableid[8];
+ uint32_t ah_oemrev;
+ uint32_t ah_creatorid;
+ uint32_t ah_creatorrev;
+} packed acpi_header_t;
+
+void acpi_init();
+
+void *acpi_table(uint32_t signature, int index);
diff --git a/kernel/include/main/apic.h b/kernel/include/main/apic.h
new file mode 100644
index 0000000..ca9c8f5
--- /dev/null
+++ b/kernel/include/main/apic.h
@@ -0,0 +1,73 @@
+#pragma once
+
+#include "main/interrupt.h"
+#include "types.h"
+
+typedef enum
+{
+ DESTINATION_MODE_FIXED = 0,
+ DESTINATION_MODE_LOWEST_PRIORITY = 1,
+ DESTINATION_MODE_SMI = 2,
+ DESTINATION_MODE_NMI = 4,
+ DESTINATION_MODE_INIT = 5,
+ DESTINATION_MODE_SIPI = 6
+} ipi_destination_mode;
+
+#define MAX_LAPICS 8
+
+/* Initializes the APIC using data from the ACPI tables.
+ * ACPI handlers must be initialized before calling this
+ * function. */
+void apic_init();
+
+/* Returns the APIC ID of the current processor */
+long apic_current_id();
+
+/* Returns the largest known APIC ID */
+long apic_max_id();
+
+/* Maps the given IRQ to the given interrupt number. */
+void apic_setredir(uint32_t irq, uint8_t intr);
+
+void apic_enable();
+
+// timer interrupts arrive at a rate of (freq / 16) interrupts per millisecond
+// (with an )
+/* Starts the APIC timer */
+void apic_enable_periodic_timer(uint32_t freq);
+
+/* Stops the APIC timer */
+void apic_disable_periodic_timer();
+
+/* Sets the interrupt to raise when a spurious
+ * interrupt occurs. */
+void apic_setspur(uint8_t intr);
+
+/* Sets the interrupt priority level. This function should
+ * be accessed via wrappers in the interrupt subsystem. */
+void apic_setipl(uint8_t ipl);
+
+/* Gets the interrupt priority level. This function should
+ * be accessed via wrappers in the interrupt subsystem. */
+uint8_t apic_getipl();
+
+long apic_initialized();
+
+/* Writes to the APIC's memory mapped end-of-interrupt
+ * register to indicate that the handling of an interrupt
+ * originating from the APIC has been finished. This function
+ * should only be called from the interrupt subsystem. */
+void apic_eoi();
+
+void apic_start_processor(uint8_t target, uint8_t execution_page);
+
+void apic_send_ipi(uint8_t target, ipi_destination_mode destination_mode,
+ uint8_t vector);
+
+void apic_broadcast_ipi(ipi_destination_mode mode, uint8_t vector,
+ long include_self);
+
+/**
+ * Wait for the last IPI sent to be acknowledged by the target processor.
+ */
+void apic_wait_ipi(); \ No newline at end of file
diff --git a/kernel/include/main/cpuid.h b/kernel/include/main/cpuid.h
new file mode 100644
index 0000000..5d4b5fa
--- /dev/null
+++ b/kernel/include/main/cpuid.h
@@ -0,0 +1,118 @@
+#pragma once
+
+#include <types.h>
+
+/* Vendor-strings. */
+#define CPUID_VENDOR_AMD "AuthenticAMD"
+#define CPUID_VENDOR_INTEL "GenuineIntel"
+#define CPUID_VENDOR_VIA "CentaurHauls"
+#define CPUID_VENDOR_OLDTRANSMETA "TransmetaCPU"
+#define CPUID_VENDOR_TRANSMETA "GenuineTMx86"
+#define CPUID_VENDOR_CYRIX "CyrixInstead"
+#define CPUID_VENDOR_CENTAUR "CentaurHauls"
+#define CPUID_VENDOR_NEXGEN "NexGenDriven"
+#define CPUID_VENDOR_UMC "UMC UMC UMC "
+#define CPUID_VENDOR_SIS "SiS SiS SiS "
+#define CPUID_VENDOR_NSC "Geode by NSC"
+#define CPUID_VENDOR_RISE "RiseRiseRise"
+
+enum
+{
+ CPUID_FEAT_ECX_SSE3 = 1 << 0,
+ CPUID_FEAT_ECX_PCLMUL = 1 << 1,
+ CPUID_FEAT_ECX_DTES64 = 1 << 2,
+ CPUID_FEAT_ECX_MONITOR = 1 << 3,
+ CPUID_FEAT_ECX_DS_CPL = 1 << 4,
+ CPUID_FEAT_ECX_VMX = 1 << 5,
+ CPUID_FEAT_ECX_SMX = 1 << 6,
+ CPUID_FEAT_ECX_EST = 1 << 7,
+ CPUID_FEAT_ECX_TM2 = 1 << 8,
+ CPUID_FEAT_ECX_SSSE3 = 1 << 9,
+ CPUID_FEAT_ECX_CID = 1 << 10,
+ CPUID_FEAT_ECX_FMA = 1 << 12,
+ CPUID_FEAT_ECX_CX16 = 1 << 13,
+ CPUID_FEAT_ECX_ETPRD = 1 << 14,
+ CPUID_FEAT_ECX_PDCM = 1 << 15,
+ CPUID_FEAT_ECX_DCA = 1 << 18,
+ CPUID_FEAT_ECX_SSE4_1 = 1 << 19,
+ CPUID_FEAT_ECX_SSE4_2 = 1 << 20,
+ CPUID_FEAT_ECX_x2APIC = 1 << 21,
+ CPUID_FEAT_ECX_MOVBE = 1 << 22,
+ CPUID_FEAT_ECX_POPCNT = 1 << 23,
+ CPUID_FEAT_ECX_XSAVE = 1 << 26,
+ CPUID_FEAT_ECX_OSXSAVE = 1 << 27,
+ CPUID_FEAT_ECX_AVX = 1 << 28,
+
+ CPUID_FEAT_EDX_FPU = 1 << 0,
+ CPUID_FEAT_EDX_VME = 1 << 1,
+ CPUID_FEAT_EDX_DE = 1 << 2,
+ CPUID_FEAT_EDX_PSE = 1 << 3,
+ CPUID_FEAT_EDX_TSC = 1 << 4,
+ CPUID_FEAT_EDX_MSR = 1 << 5,
+ CPUID_FEAT_EDX_PAE = 1 << 6,
+ CPUID_FEAT_EDX_MCE = 1 << 7,
+ CPUID_FEAT_EDX_CX8 = 1 << 8,
+ CPUID_FEAT_EDX_APIC = 1 << 9,
+ CPUID_FEAT_EDX_SEP = 1 << 11,
+ CPUID_FEAT_EDX_MTRR = 1 << 12,
+ CPUID_FEAT_EDX_PGE = 1 << 13,
+ CPUID_FEAT_EDX_MCA = 1 << 14,
+ CPUID_FEAT_EDX_CMOV = 1 << 15,
+ CPUID_FEAT_EDX_PAT = 1 << 16,
+ CPUID_FEAT_EDX_PSE36 = 1 << 17,
+ CPUID_FEAT_EDX_PSN = 1 << 18,
+ CPUID_FEAT_EDX_CLF = 1 << 19,
+ CPUID_FEAT_EDX_DTES = 1 << 21,
+ CPUID_FEAT_EDX_ACPI = 1 << 22,
+ CPUID_FEAT_EDX_MMX = 1 << 23,
+ CPUID_FEAT_EDX_FXSR = 1 << 24,
+ CPUID_FEAT_EDX_SSE = 1 << 25,
+ CPUID_FEAT_EDX_SSE2 = 1 << 26,
+ CPUID_FEAT_EDX_SS = 1 << 27,
+ CPUID_FEAT_EDX_HTT = 1 << 28,
+ CPUID_FEAT_EDX_TM1 = 1 << 29,
+ CPUID_FEAT_EDX_IA64 = 1 << 30,
+ CPUID_FEAT_EDX_PBE = 1 << 31
+};
+
+enum cpuid_requests
+{
+ CPUID_GETVENDORSTRING,
+ CPUID_GETFEATURES,
+ CPUID_GETTLB,
+ CPUID_GETSERIAL,
+
+ CPUID_INTELEXTENDED = 0x80000000,
+ CPUID_INTELFEATURES,
+ CPUID_INTELBRANDSTRING,
+ CPUID_INTELBRANDSTRINGMORE,
+ CPUID_INTELBRANDSTRINGEND,
+};
+
+static inline void cpuid(int request, uint32_t *a, uint32_t *b, uint32_t *c,
+ uint32_t *d)
+{
+ __asm__ volatile("cpuid"
+ : "=a"(*a), "=b"(*b), "=c"(*c), "=d"(*d)
+ : "0"(request));
+}
+
+static inline void cpuid_get_msr(uint32_t msr, uint32_t *lo, uint32_t *hi)
+{
+ __asm__ volatile("rdmsr"
+ : "=a"(*lo), "=d"(*hi)
+ : "c"(msr));
+}
+
+static inline void cpuid_set_msr(uint32_t msr, uint32_t lo, uint32_t hi)
+{
+ __asm__ volatile("wrmsr" ::"a"(lo), "d"(hi), "c"(msr));
+}
+
+static inline void io_wait(void)
+{
+ __asm__ volatile(
+ "jmp 1f\n\t"
+ "1:jmp 2f\n\t"
+ "2:");
+}
diff --git a/kernel/include/main/entry.h b/kernel/include/main/entry.h
new file mode 100644
index 0000000..64c0e96
--- /dev/null
+++ b/kernel/include/main/entry.h
@@ -0,0 +1,3 @@
+/* entry.h */
+
+void kmain(void);
diff --git a/kernel/include/main/gdt.h b/kernel/include/main/gdt.h
new file mode 100644
index 0000000..a991cbf
--- /dev/null
+++ b/kernel/include/main/gdt.h
@@ -0,0 +1,21 @@
+#pragma once
+
+#include "types.h"
+
+#define GDT_COUNT 16
+
+#define GDT_ZERO 0x00
+#define GDT_KERNEL_TEXT 0x08
+#define GDT_KERNEL_DATA 0x10
+#define GDT_USER_TEXT 0x18
+#define GDT_USER_DATA 0x20
+#define GDT_TSS 0x28
+
+void gdt_init(void);
+
+void gdt_set_kernel_stack(void *addr);
+
+void gdt_set_entry(uint32_t segment, uint32_t base, uint32_t limit,
+ uint8_t ring, int exec, int dir, int rw);
+
+void gdt_clear(uint32_t segment); \ No newline at end of file
diff --git a/kernel/include/main/inits.h b/kernel/include/main/inits.h
new file mode 100644
index 0000000..5013b07
--- /dev/null
+++ b/kernel/include/main/inits.h
@@ -0,0 +1,15 @@
+#pragma once
+
+extern void sched_init();
+
+extern void kshell_init();
+
+extern void file_init();
+
+extern void pipe_init();
+
+extern void vfs_init();
+
+extern void syscall_init();
+
+extern void elf64_init(void);
diff --git a/kernel/include/main/interrupt.h b/kernel/include/main/interrupt.h
new file mode 100644
index 0000000..6a9ae00
--- /dev/null
+++ b/kernel/include/main/interrupt.h
@@ -0,0 +1,117 @@
+#pragma once
+
+#include "kernel.h"
+#include "types.h"
+#include "util/debug.h"
+
+// intr_disk_priamry/seconday so that they are different task priority classes
+#define INTR_DIVIDE_BY_ZERO 0x00
+#define INTR_INVALID_OPCODE 0x06
+#define INTR_GPF 0x0d
+#define INTR_PAGE_FAULT 0x0e
+
+#define INTR_APICTIMER 0xf0
+#define INTR_KEYBOARD 0xe0
+
+#define INTR_DISK_PRIMARY 0xd0
+#define INTR_SPURIOUS 0xfe
+#define INTR_APICERR 0xff
+#define INTR_SHUTDOWN 0xfd
+
+/* NOTE: INTR_SYSCALL is not defined here, but is in syscall.h (it must be
+ * in a userland-accessible header) */
+
+// Intel Volume 3-A, 10.8.3.1 (10-29)
+#define IPL_LOW 0
+// we want to keep timer interrupts happening all the time to keep track of time
+// :)
+#define IPL_HIGH 0xe0
+#define IPL_HIGHEST 0xff
+
+typedef struct regs
+{
+ // all the regs
+ uint64_t r_r15;
+ uint64_t r_r14;
+ uint64_t r_r13;
+ uint64_t r_r12;
+ uint64_t r_rbp;
+ uint64_t r_rbx;
+ uint64_t r_r11;
+ uint64_t r_r10;
+ uint64_t r_r9;
+ uint64_t r_r8;
+ uint64_t r_rax;
+ uint64_t r_rcx;
+ uint64_t r_rdx;
+ uint64_t r_rsi;
+ uint64_t r_rdi;
+
+ // interrupt number
+ uint64_t r_intr;
+
+ // pushed by processor
+ uint64_t r_err;
+ uint64_t r_rip;
+ uint64_t r_cs;
+ uint64_t r_rflags;
+ uint64_t r_rsp;
+ uint64_t r_ss;
+} packed regs_t;
+
+void intr_init();
+
+/* The function pointer which should be implemented by functions
+ * which will handle interrupts. These handlers should be registered
+ * with the interrupt subsystem via the intr_register function.
+ * The regs structure contains the state of the registers saved when
+ * the interrupt occured. Return whether or not the handler has itself
+ * acknowledged the interrupt with a call to apic_eoi(). */
+typedef long (*intr_handler_t)(regs_t *regs);
+
+/* Registers an interrupt handler for the given interrupt handler.
+ * If another handler had been previously registered for this interrupt
+ * number it is returned, otherwise this function returns NULL. It
+ * is good practice to assert that this function returns NULL unless
+ * it is known that this will not be the case. */
+intr_handler_t intr_register(uint8_t intr, intr_handler_t handler);
+
+int32_t intr_map(uint16_t irq, uint8_t intr);
+
+static inline uint64_t intr_enabled()
+{
+ uint64_t flags;
+ __asm__ volatile("pushf; pop %0; and $0x200, %0;"
+ : "=r"(flags)::);
+ return flags;
+}
+
+static inline void intr_enable() { __asm__ volatile("sti"); }
+
+static inline void intr_disable() { __asm__ volatile("cli"); }
+
+/* Atomically enables interrupts using the sti
+ * instruction and puts the processor into a halted
+ * state, this function returns once an interrupt
+ * occurs. */
+static inline void intr_wait()
+{
+ /* the sti instruction enables interrupts, however
+ * interrupts are not checked for until the next
+ * instruction is executed, this means that the following
+ * code will not be succeptible to a bug where an
+ * interrupt occurs between the sti and hlt commands
+ * and does not wake us up from the hlt. */
+ __asm__ volatile("sti; hlt");
+}
+
+/* Sets the interrupt priority level for hardware interrupts.
+ * At initialization time devices should detect their individual
+ * IPLs and save them for use with this function. IPL_LOW allows
+ * all hardware interrupts. IPL_HIGH blocks all hardware interrupts */
+uint8_t intr_setipl(uint8_t ipl);
+
+/* Retreives the current interrupt priority level. */
+uint8_t intr_getipl();
+
+void dump_registers(regs_t *regs);
diff --git a/kernel/include/main/io.h b/kernel/include/main/io.h
new file mode 100644
index 0000000..19c6f86
--- /dev/null
+++ b/kernel/include/main/io.h
@@ -0,0 +1,46 @@
+#pragma once
+
+#include "kernel.h"
+#include "types.h"
+
+static inline void outb(uint16_t port, uint8_t val)
+{
+ __asm__ volatile("outb %0,%1" ::"a"(val), "Nd"(port));
+}
+
+static inline uint8_t inb(uint16_t port)
+{
+ uint8_t ret;
+ __asm__ volatile("inb %1,%0"
+ : "=a"(ret)
+ : "Nd"(port));
+ return ret;
+}
+
+static inline void outw(uint16_t port, uint16_t val)
+{
+ __asm__ volatile("outw %0,%1" ::"a"(val), "Nd"(port));
+}
+
+static inline uint16_t inw(uint16_t port)
+{
+ uint16_t ret;
+ __asm__ volatile("inw %1,%0"
+ : "=a"(ret)
+ : "Nd"(port));
+ return ret;
+}
+
+static inline void outl(uint16_t port, uint32_t val)
+{
+ __asm__ volatile("outl %0,%1" ::"a"(val), "Nd"(port));
+}
+
+static inline uint32_t inl(uint16_t port)
+{
+ uint32_t ret;
+ __asm__ volatile("inl %1,%0"
+ : "=a"(ret)
+ : "Nd"(port));
+ return ret;
+}
diff --git a/kernel/include/main/smp.h b/kernel/include/main/smp.h
new file mode 100644
index 0000000..bf05fff
--- /dev/null
+++ b/kernel/include/main/smp.h
@@ -0,0 +1,22 @@
+#include "boot/config.h"
+#include "mm/page.h"
+#include "proc/core.h"
+
+// For any given piece of global data, there are 4 cases we must protect
+// against: (SMP.1) our core's other threads, (mutex or mask interrupts) (SMP.2)
+// our core's interrupt handlers, and (mask interrupts) (SMP.3) other cores'
+// threads, (mutex or spinlock) (SMP.4) other cores' interrupt handlers
+// (spinlock) mask interrupts + spinlock covers all 4 cases!
+
+#define GET_CSD(core, type, name) \
+ ((type *)(csd_vaddr_table[(core)] + PAGE_OFFSET(&(name))))
+
+extern uintptr_t csd_vaddr_table[];
+
+void map_in_core_specific_data(pml4_t *pml4);
+
+void smp_init();
+
+void core_init();
+
+long is_core_specific_data(void *addr);
diff --git a/kernel/include/mm/kmalloc.h b/kernel/include/mm/kmalloc.h
new file mode 100644
index 0000000..f99e9df
--- /dev/null
+++ b/kernel/include/mm/kmalloc.h
@@ -0,0 +1,7 @@
+#pragma once
+
+#include "types.h"
+
+void *kmalloc(size_t size);
+
+void kfree(void *addr);
diff --git a/kernel/include/mm/mm.h b/kernel/include/mm/mm.h
new file mode 100644
index 0000000..c2989b4
--- /dev/null
+++ b/kernel/include/mm/mm.h
@@ -0,0 +1,8 @@
+#pragma once
+
+#define MM_POISON 1
+#define MM_POISON_ALLOC 0xBB
+#define MM_POISON_FREE 0xDD
+
+#define USER_MEM_LOW 0x00400000 /* inclusive */
+#define USER_MEM_HIGH (1UL << 47) /* exclusive */
diff --git a/kernel/include/mm/mman.h b/kernel/include/mm/mman.h
new file mode 100644
index 0000000..27f4d57
--- /dev/null
+++ b/kernel/include/mm/mman.h
@@ -0,0 +1,25 @@
+#pragma once
+
+/* Kernel and user header (via symlink) */
+
+/* Page protection flags.
+ */
+#define PROT_NONE 0x0 /* No access. */
+#define PROT_READ 0x1 /* Pages can be read. */
+#define PROT_WRITE 0x2 /* Pages can be written. */
+#define PROT_EXEC 0x4 /* Pages can be executed. */
+
+/* Return value for mmap() on failure.
+ */
+#define MAP_FAILED ((void *)-1)
+
+/* Mapping type - shared or private.
+ */
+#define MAP_SHARED 1
+#define MAP_PRIVATE 2
+#define MAP_TYPE 3 /* mask for above types */
+
+/* Mapping flags.
+ */
+#define MAP_FIXED 4
+#define MAP_ANON 8
diff --git a/kernel/include/mm/mobj.h b/kernel/include/mm/mobj.h
new file mode 100644
index 0000000..bca1b38
--- /dev/null
+++ b/kernel/include/mm/mobj.h
@@ -0,0 +1,75 @@
+#pragma once
+
+#include "proc/kmutex.h"
+#include "util/atomic.h"
+#include "util/list.h"
+#include "mm/pframe.h"
+
+struct pframe;
+
+struct mobj;
+
+typedef enum
+{
+ MOBJ_VNODE = 1,
+ MOBJ_SHADOW,
+ MOBJ_ANON,
+#ifdef OLD
+ MOBJ_BLOCKDEV,
+#else
+ MOBJ_FS,
+#endif
+} mobj_type_t;
+
+typedef struct mobj_ops
+{
+ long (*get_pframe)(struct mobj *o, uint64_t pagenum, long forwrite,
+ struct pframe **pfp);
+
+ long (*fill_pframe)(struct mobj *o, struct pframe *pf);
+
+ long (*flush_pframe)(struct mobj *o, struct pframe *pf);
+
+ void (*destructor)(struct mobj *o);
+} mobj_ops_t;
+
+typedef struct mobj
+{
+ long mo_type;
+ struct mobj_ops mo_ops;
+ atomic_t mo_refcount;
+ list_t mo_pframes;
+ kmutex_t mo_mutex;
+} mobj_t;
+
+void mobj_init(mobj_t *o, long type, mobj_ops_t *ops);
+
+void mobj_lock(mobj_t *o);
+
+void mobj_unlock(mobj_t *o);
+
+void mobj_ref(mobj_t *o);
+
+void mobj_put(mobj_t **op);
+
+void mobj_put_locked(mobj_t **op);
+
+long mobj_get_pframe(mobj_t *o, uint64_t pagenum, long forwrite,
+ struct pframe **pfp);
+
+void mobj_find_pframe(mobj_t *o, uint64_t pagenum, struct pframe **pfp);
+
+long mobj_flush_pframe(mobj_t *o, struct pframe *pf);
+
+long mobj_flush(mobj_t *o);
+
+long mobj_free_pframe(mobj_t *o, struct pframe **pfp);
+
+long mobj_default_get_pframe(mobj_t *o, uint64_t pagenum, long forwrite,
+ struct pframe **pfp);
+
+void mobj_default_destructor(mobj_t *o);
+
+#ifndef OLD
+void mobj_create_pframe(mobj_t *o, uint64_t pagenum, uint64_t loc, pframe_t **pfp);
+#endif \ No newline at end of file
diff --git a/kernel/include/mm/page.h b/kernel/include/mm/page.h
new file mode 100644
index 0000000..5230a85
--- /dev/null
+++ b/kernel/include/mm/page.h
@@ -0,0 +1,124 @@
+#pragma once
+
+#ifdef __KERNEL__
+#include "types.h"
+#else
+#include "sys/types.h"
+#endif
+
+/* This header file contains the functions for allocating
+ * and freeing page-aligned chunks of data which are a
+ * multiple of a page in size. These are the lowest level
+ * memory allocation functions. In general code should
+ * use the slab allocator functions in mm/slab.h unless
+ * they require page-aligned buffers. */
+
+#define PAGE_SHIFT 12
+#define PAGE_SIZE ((uintptr_t)(1UL << PAGE_SHIFT))
+#define PAGE_MASK (0xffffffffffffffff << PAGE_SHIFT)
+
+#define PAGE_ALIGN_DOWN(x) ((void *)(((uintptr_t)(x)&PAGE_MASK)))
+#define PAGE_ALIGN_UP(x) \
+ ((void *)((((uintptr_t)(x) + (PAGE_SIZE - 1)) & PAGE_MASK)))
+
+#define PAGE_OFFSET(x) (((uintptr_t)(x)) & ~PAGE_MASK)
+#define PAGE_ALIGNED(x) (!PAGE_OFFSET(x))
+
+#define PN_TO_ADDR(x) ((void *)(((uintptr_t)(x)) << PAGE_SHIFT))
+#define ADDR_TO_PN(x) (((uintptr_t)(x)) >> PAGE_SHIFT)
+
+#define PAGE_SAME(x, y) (PAGE_ALIGN_DOWN(x) == PAGE_ALIGN_DOWN(y))
+
+#define PAGE_NSIZES 8
+
+#define USE_2MB_PAGES 1
+#define USE_1GB_PAGES 1
+
+#define PAGE_SHIFT_2MB 21
+#define PAGE_SIZE_2MB ((uintptr_t)(1UL << PAGE_SHIFT_2MB))
+#define PAGE_MASK_2MB (0xffffffffffffffff << PAGE_SHIFT_2MB)
+#define PAGE_ALIGN_DOWN_2MB(x) (((uintptr_t)(x)) & PAGE_MASK_2MB)
+#define PAGE_ALIGN_UP_2MB(x) (PAGE_ALIGN_DOWN_2MB((x)-1) + PAGE_SIZE_2MB)
+#define PAGE_OFFSET_2MB(x) (((uintptr_t)(x)) & ~PAGE_MASK_2MB)
+#define PAGE_ALIGNED_2MB(x) ((x) == PAGE_ALIGN_DOWN_2MB(x))
+#define PAGE_SAME_2MB(x, y) (PAGE_ALIGN_DOWN_2MB(x) == PAGE_ALIGN_DOWN_2MB(y))
+
+#define PAGE_SHIFT_1GB 30
+#define PAGE_MASK_1GB (0xffffffffffffffff << PAGE_SHIFT_1GB)
+#define PAGE_SIZE_1GB ((uintptr_t)(1UL << PAGE_SHIFT_1GB))
+#define PAGE_ALIGN_DOWN_1GB(x) (((uintptr_t)(x)) & PAGE_MASK_1GB)
+#define PAGE_ALIGN_UP_1GB(x) (PAGE_ALIGN_DOWN_1GB((x)-1) + PAGE_SIZE_1GB)
+#define PAGE_OFFSET_1GB(x) (((uintptr_t)(x)) & ~PAGE_MASK_1GB)
+#define PAGE_ALIGNED_1GB(x) ((x) == PAGE_ALIGN_DOWN_1GB(x))
+#define PAGE_SAME_1GB(x, y) (PAGE_ALIGN_DOWN_1GB(x) == PAGE_ALIGN_DOWN_1GB(y))
+
+#define PAGE_SHIFT_512GB 39
+#define PAGE_SIZE_512GB ((uintptr_t)(1UL << PAGE_SHIFT_512GB))
+#define PAGE_MASK_512GB (0xffffffffffffffff << PAGE_SHIFT_512GB)
+#define PAGE_ALIGN_DOWN_512GB(x) (((uintptr_t)(x)) & PAGE_MASK_512GB)
+#define PAGE_ALIGN_UP_512GB(x) (PAGE_ALIGN_DOWN_512GB((x)-1) + PAGE_SIZE_512GB)
+
+#define PAGE_CONTROL_FLAGS(x) \
+ ((x) & (PT_PRESENT | PT_WRITE | PT_USER | PT_WRITE_THROUGH | \
+ PT_CACHE_DISABLED | PT_SIZE | PT_GLOBAL))
+#define PAGE_FLAGS(x) ((x) & (~PAGE_MASK))
+
+typedef enum page_size
+{
+ ps_4kb,
+ ps_2mb,
+ ps_1gb,
+ ps_512gb,
+} page_size_t;
+
+typedef struct page_status
+{
+ page_size_t size;
+ int mapped;
+} page_status_t;
+
+/* Performs all initialization necessary for the
+ * page allocation system. This should be called
+ * only once at boot time before any other functions
+ * in this header are called. */
+void page_init();
+
+void *physmap_start();
+
+void *physmap_end();
+
+/* These functions allocate and free one page-aligned,
+ * page-sized block of memory. Values passed to
+ * page_free MUST have been returned by page_alloc
+ * at some previous point. There should be only one
+ * call to page_free for each value returned by
+ * page_alloc. If the system is out of memory page_alloc
+ * will return NULL. */
+void *page_alloc(void);
+
+void *page_alloc_bounded(void *max_paddr);
+
+void page_free(void *addr);
+
+/* These functions allocate and free a page-aligned
+ * block of memory which are npages pages in length.
+ * A call to page_alloc_n will allocate a block, to free
+ * that block a call should be made to page_free_n with
+ * npages set to the same as it was when the block was
+ * allocated */
+void *page_alloc_n(size_t npages);
+
+void *page_alloc_n_bounded(size_t npages, void *max_paddr);
+
+void page_free_n(void *start, size_t npages);
+
+void page_add_range(void *start, void *end);
+
+void page_mark_reserved(void *paddr);
+
+void page_init_finish();
+
+/* Returns the number of free pages remaining in the
+ * system. Note that calls to page_alloc_n(npages) may
+ * fail even if page_free_count() >= npages. */
+size_t page_free_count();
diff --git a/kernel/include/mm/pagecache.h b/kernel/include/mm/pagecache.h
new file mode 100644
index 0000000..442e7b1
--- /dev/null
+++ b/kernel/include/mm/pagecache.h
@@ -0,0 +1,9 @@
+#pragma once
+
+#include "drivers/blockdev.h"
+#include "mm/pframe.h"
+
+long pagecache_get_page(pframe_t *pf);
+#ifdef NO
+void pagecache_newsource(pframe_t *pf, blockdev_t *dev, long loc);
+#endif \ No newline at end of file
diff --git a/kernel/include/mm/pagetable.h b/kernel/include/mm/pagetable.h
new file mode 100644
index 0000000..cc1fa3e
--- /dev/null
+++ b/kernel/include/mm/pagetable.h
@@ -0,0 +1,94 @@
+#pragma once
+
+#include "mm/page.h"
+#include "vm/vmmap.h"
+
+#define PT_PRESENT 0x001
+#define PT_WRITE 0x002
+#define PT_USER 0x004
+#define PT_WRITE_THROUGH 0x008
+#define PT_CACHE_DISABLED 0x010
+#define PT_ACCESSED 0x020
+#define PT_DIRTY 0x040
+#define PT_SIZE 0x080
+#define PT_GLOBAL 0x100
+
+#define PT_ENTRY_COUNT (PAGE_SIZE / sizeof(uintptr_t))
+
+typedef struct page
+{
+ uint8_t data[PAGE_SIZE];
+} page_t;
+
+// Generalized structure for all directory like entries
+typedef struct pt
+{
+ uintptr_t phys[PT_ENTRY_COUNT];
+} pt_t, pd_t, pdp_t, pml4_t;
+
+#define INDEX_MASK 0b111111111
+#define PML4E(x) ((((uintptr_t)(x)) >> 39) & INDEX_MASK)
+#define PDPE(x) ((((uintptr_t)(x)) >> 30) & INDEX_MASK)
+#define PDE(x) ((((uintptr_t)(x)) >> 21) & INDEX_MASK)
+#define PTE(x) ((((uintptr_t)(x)) >> 12) & INDEX_MASK)
+
+#define PT_ENTRY_COUNT (PAGE_SIZE / sizeof(uintptr_t))
+#define PT_VADDR_SIZE (PAGE_SIZE * PT_ENTRY_COUNT)
+#define PD_VADDR_SIZE (PAGE_SIZE * PT_ENTRY_COUNT * PT_ENTRY_COUNT)
+#define PDP_VADDR_SIZE \
+ (PAGE_SIZE * PT_ENTRY_COUNT * PT_ENTRY_COUNT * PT_ENTRY_COUNT)
+#define PML4_VADDR_SIZE \
+ (PAGE_SIZE * PT_ENTRY_COUNT * PT_ENTRY_COUNT * PT_ENTRY_COUNT * \
+ PT_ENTRY_COUNT)
+
+#define IS_PRESENT(n) ((n)&PT_PRESENT)
+#define IS_2MB_PAGE(n) ((n)&PT_SIZE)
+#define IS_1GB_PAGE IS_2MB_PAGE
+
+#define GDB_PT_PHYSADDR(pt, v) (pt->phys[PTE(v)] & PAGE_MASK)
+#define GDB_PD_PHYSADDR(pd, v) (pd->phys[PDE(v)] & PAGE_MASK)
+#define GDB_PDP_PHYSADDR(pdp, v) (pdp->phys[PDPE(v)] & PAGE_MASK)
+#define GDB_PML4_PHYSADDR(pml4, v) (pml4->phys[PML4E(v)] & PAGE_MASK)
+
+#define GDB_PHYSADDR(pml4, v) \
+ (GDB_PT_PHYSADDR( \
+ GDB_PD_PHYSADDR( \
+ GDB_PDP_PHYSADDR(GDB_PML4_PHYSADDR(pml4, (v)) + PHYS_OFFSET, \
+ (v)) + \
+ PHYS_OFFSET, \
+ (v)) + \
+ PHYS_OFFSET, \
+ (v)) + \
+ PHYS_OFFSET)
+#define GDB_CUR_PHYSADDR(v) GDB_PHYSADDR(curproc->p_pml4, (v))
+
+uintptr_t pt_virt_to_phys_helper(pml4_t *pml4, uintptr_t vaddr);
+
+uintptr_t pt_virt_to_phys(uintptr_t vaddr);
+
+void pt_init(void);
+
+/* Currently unused. */
+void pt_template_init(void);
+
+pml4_t *pt_get();
+
+void pt_set(pml4_t *pml4);
+
+pml4_t *clone_pml4(pml4_t *pml4, long include_user_mappings);
+
+pml4_t *pt_create();
+
+void pt_destroy(pml4_t *pml4);
+
+long pt_map(pml4_t *pml4, uintptr_t paddr, uintptr_t vaddr, uint32_t pdflags,
+ uint32_t ptflags);
+
+long pt_map_range(pml4_t *pml4, uintptr_t paddr, uintptr_t vaddr,
+ uintptr_t vmax, uint32_t pdflags, uint32_t ptflags);
+
+void pt_unmap(pml4_t *pml4, uintptr_t vaddr);
+
+void pt_unmap_range(pml4_t *pml4, uintptr_t vaddr, uintptr_t vmax);
+
+void check_invalid_mappings(pml4_t *pml4, vmmap_t *vmmap, char *prompt);
diff --git a/kernel/include/mm/pframe.h b/kernel/include/mm/pframe.h
new file mode 100644
index 0000000..bd2c3f7
--- /dev/null
+++ b/kernel/include/mm/pframe.h
@@ -0,0 +1,23 @@
+#pragma once
+
+//#include "mm/mobj.h"
+#include "proc/kmutex.h"
+#include "types.h"
+
+typedef struct pframe
+{
+ size_t pf_pagenum;
+ size_t pf_loc;
+ void *pf_addr;
+ long pf_dirty;
+ kmutex_t pf_mutex;
+ list_link_t pf_link;
+} pframe_t;
+
+void pframe_init();
+
+pframe_t *pframe_create();
+
+void pframe_release(pframe_t **pfp);
+
+void pframe_free(pframe_t **pfp);
diff --git a/kernel/include/mm/slab.h b/kernel/include/mm/slab.h
new file mode 100644
index 0000000..6ead5ae
--- /dev/null
+++ b/kernel/include/mm/slab.h
@@ -0,0 +1,96 @@
+#pragma once
+
+#include <types.h>
+
+/* Define SLAB_REDZONE to add top and bottom redzones to every object. */
+#define SLAB_REDZONE 0xdeadbeefdeadbeef
+
+/* Define SLAB_CHECK_FREE to add extra book keeping to make sure there
+ * are no double frees. */
+#define SLAB_CHECK_FREE
+
+/*
+ * The slab allocator. A "cache" is a store of objects; you create one by
+ * specifying a constructor, destructor, and the size of an object. The
+ * "alloc" function allocates one object, and the "free" function returns
+ * it to the free list *without calling the destructor*. This lets you save
+ * on destruction/construction calls; the idea is that every free object in
+ * the cache is in a known state.
+ */
+typedef struct slab_allocator slab_allocator_t;
+
+/* Initializes the slab allocator subsystem. This should be done
+ * only after the page subsystem has been initialized. Slab allocators
+ * and kmalloc will not work until this function has been called. */
+void slab_init();
+
+/*
+ * Example Usage
+ * See the below example for how to use a slab allocator to allocate objects
+ * of a given size. Note that you usually don't need to destroy most allocators,
+ * as they should last as long as the system is running (e.g. the process allocator).
+ *
+ * ```
+ * typedef struct {
+ * int x;
+ * int y;
+ * } point_t;
+ *
+ * // Create a new allocator for objects of type point_t. This only needs to
+ * // happen once, usually in an initialization routine.
+ * slab_allocator_t *point_allocator = slab_allocator_create("point", sizeof(point_t));
+ *
+ * // Allocate a new point_t from the slab allocator
+ * point_t *p = (point_t *)slab_obj_alloc(point_allocator);
+ *
+ * // ... Use p here ...
+ *
+ * // Deallocate the point_t
+ * slab_obj_free(point_allocator, p);
+ * ```
+ */
+
+/**
+ * Creates a slab allocator for allocating objects of a given size.
+ *
+ * @param name The name of the allocator (for debugging)
+ * @param size The size (bytes) of objects that will be allocated from this allocator
+ * @return slab_allocator_t* An allocator, or NULL on failure
+ */
+slab_allocator_t *slab_allocator_create(const char *name, size_t size);
+
+/**
+ * Destroys a slab allocator.
+ *
+ * @param allocator The allocator to destroy
+ */
+void slab_allocator_destroy(struct slab_allocator *allocator);
+
+/**
+ * Allocates an object from the given slab allocator. The object is a chunk of
+ * memory as big as the size that slab allocator was created with.
+ *
+ * @param allocator The allocator to allocate from
+ * @return void* A chunk of memory of the appropriate object size, or NULL
+ * on failure
+ */
+void *slab_obj_alloc(slab_allocator_t *allocator);
+
+/**
+ * Frees a given object that was allocated by a given slab allocator.
+ *
+ * @param allocator The allocator that allocated this object
+ * @param obj The object to be freed
+ */
+void slab_obj_free(slab_allocator_t *allocator, void *obj);
+
+/**
+ * Reclaims memory from unused slabs.
+ *
+ * NOTE: This is not currently implemented.
+ *
+ * @param target Target number of pages to reclaim. If negative, reclaim as many
+ * as possible
+ * @return long Number of pages freed
+ */
+long slab_allocators_reclaim(long target); \ No newline at end of file
diff --git a/kernel/include/mm/tlb.h b/kernel/include/mm/tlb.h
new file mode 100644
index 0000000..836be4e
--- /dev/null
+++ b/kernel/include/mm/tlb.h
@@ -0,0 +1,35 @@
+#pragma once
+
+#include "kernel.h"
+#include "types.h"
+
+#include "mm/page.h"
+
+/* Invalidates any entries from the TLB which contain
+ * mappings for the given virtual address. */
+static inline void tlb_flush(uintptr_t vaddr)
+{
+ __asm__ volatile("invlpg (%0)" ::"r"(vaddr));
+}
+
+/* Invalidates any entries for count pages starting at
+ * vaddr from the TLB. If this range is very large it may
+ * be more efficient to call tlb_flush_all to invalidate
+ * the entire TLB. */
+static inline void tlb_flush_range(uintptr_t vaddr, size_t count)
+{
+ for (size_t i = 0; i < count; i++, vaddr += PAGE_SIZE)
+ {
+ tlb_flush(vaddr);
+ }
+}
+
+/* Invalidates the entire TLB. */
+static inline void tlb_flush_all()
+{
+ uintptr_t pdir;
+ __asm__ volatile("movq %%cr3, %0"
+ : "=r"(pdir));
+ __asm__ volatile("movq %0, %%cr3" ::"r"(pdir)
+ : "memory");
+}
diff --git a/kernel/include/multiboot.h b/kernel/include/multiboot.h
new file mode 100644
index 0000000..55bb8a8
--- /dev/null
+++ b/kernel/include/multiboot.h
@@ -0,0 +1,417 @@
+/* multiboot.h - Multiboot header file. */
+/* Copyright (C) 1999,2003,2007,2008,2009,2010 Free Software Foundation, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ANY
+ * DEVELOPER OR DISTRIBUTOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef MULTIBOOT_HEADER
+#define MULTIBOOT_HEADER 1
+
+/* How many bytes from the start of the file we search for the header. */
+#define MULTIBOOT_SEARCH 32768
+#define MULTIBOOT_HEADER_ALIGN 8
+
+/* The magic field should contain this. */
+#define MULTIBOOT2_HEADER_MAGIC 0xe85250d6
+
+/* This should be in %eax. */
+#define MULTIBOOT2_BOOTLOADER_MAGIC 0x36d76289
+
+/* Alignment of multiboot modules. */
+#define MULTIBOOT_MOD_ALIGN 0x00001000
+
+/* Alignment of the multiboot info structure. */
+#define MULTIBOOT_INFO_ALIGN 0x00000008
+
+/* Flags set in the 'flags' member of the multiboot header. */
+
+#define MULTIBOOT_TAG_ALIGN 8
+#define MULTIBOOT_TAG_TYPE_END 0
+#define MULTIBOOT_TAG_TYPE_CMDLINE 1
+#define MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME 2
+#define MULTIBOOT_TAG_TYPE_MODULE 3
+#define MULTIBOOT_TAG_TYPE_BASIC_MEMINFO 4
+#define MULTIBOOT_TAG_TYPE_BOOTDEV 5
+#define MULTIBOOT_TAG_TYPE_MMAP 6
+#define MULTIBOOT_TAG_TYPE_VBE 7
+#define MULTIBOOT_TAG_TYPE_FRAMEBUFFER 8
+#define MULTIBOOT_TAG_TYPE_ELF_SECTIONS 9
+#define MULTIBOOT_TAG_TYPE_APM 10
+#define MULTIBOOT_TAG_TYPE_EFI32 11
+#define MULTIBOOT_TAG_TYPE_EFI64 12
+#define MULTIBOOT_TAG_TYPE_SMBIOS 13
+#define MULTIBOOT_TAG_TYPE_ACPI_OLD 14
+#define MULTIBOOT_TAG_TYPE_ACPI_NEW 15
+#define MULTIBOOT_TAG_TYPE_NETWORK 16
+#define MULTIBOOT_TAG_TYPE_EFI_MMAP 17
+#define MULTIBOOT_TAG_TYPE_EFI_BS 18
+#define MULTIBOOT_TAG_TYPE_EFI32_IH 19
+#define MULTIBOOT_TAG_TYPE_EFI64_IH 20
+#define MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR 21
+
+#define MULTIBOOT_HEADER_TAG_END 0
+#define MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST 1
+#define MULTIBOOT_HEADER_TAG_ADDRESS 2
+#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS 3
+#define MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS 4
+#define MULTIBOOT_HEADER_TAG_FRAMEBUFFER 5
+#define MULTIBOOT_HEADER_TAG_MODULE_ALIGN 6
+#define MULTIBOOT_HEADER_TAG_EFI_BS 7
+#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI32 8
+#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI64 9
+#define MULTIBOOT_HEADER_TAG_RELOCATABLE 10
+
+#define MULTIBOOT_ARCHITECTURE_I386 0
+#define MULTIBOOT_ARCHITECTURE_MIPS32 4
+#define MULTIBOOT_HEADER_TAG_OPTIONAL 1
+
+#define MULTIBOOT_LOAD_PREFERENCE_NONE 0
+#define MULTIBOOT_LOAD_PREFERENCE_LOW 1
+#define MULTIBOOT_LOAD_PREFERENCE_HIGH 2
+
+#define MULTIBOOT_CONSOLE_FLAGS_CONSOLE_REQUIRED 1
+#define MULTIBOOT_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED 2
+
+#ifndef ASM_FILE
+
+typedef unsigned char multiboot_uint8_t;
+typedef unsigned short multiboot_uint16_t;
+typedef unsigned int multiboot_uint32_t;
+typedef unsigned long long multiboot_uint64_t;
+
+struct multiboot_header
+{
+ /* Must be MULTIBOOT_MAGIC - see above. */
+ multiboot_uint32_t magic;
+
+ /* ISA */
+ multiboot_uint32_t architecture;
+
+ /* Total header length. */
+ multiboot_uint32_t header_length;
+
+ /* The above fields plus this one must equal 0 mod 2^32. */
+ multiboot_uint32_t checksum;
+};
+
+struct multiboot_header_tag
+{
+ multiboot_uint16_t type;
+ multiboot_uint16_t flags;
+ multiboot_uint32_t size;
+};
+
+struct multiboot_header_tag_information_request
+{
+ multiboot_uint16_t type;
+ multiboot_uint16_t flags;
+ multiboot_uint32_t size;
+ multiboot_uint32_t requests[0];
+};
+
+struct multiboot_header_tag_address
+{
+ multiboot_uint16_t type;
+ multiboot_uint16_t flags;
+ multiboot_uint32_t size;
+ multiboot_uint32_t header_addr;
+ multiboot_uint32_t load_addr;
+ multiboot_uint32_t load_end_addr;
+ multiboot_uint32_t bss_end_addr;
+};
+
+struct multiboot_header_tag_entry_address
+{
+ multiboot_uint16_t type;
+ multiboot_uint16_t flags;
+ multiboot_uint32_t size;
+ multiboot_uint32_t entry_addr;
+};
+
+struct multiboot_header_tag_console_flags
+{
+ multiboot_uint16_t type;
+ multiboot_uint16_t flags;
+ multiboot_uint32_t size;
+ multiboot_uint32_t console_flags;
+};
+
+struct multiboot_header_tag_framebuffer
+{
+ multiboot_uint16_t type;
+ multiboot_uint16_t flags;
+ multiboot_uint32_t size;
+ multiboot_uint32_t width;
+ multiboot_uint32_t height;
+ multiboot_uint32_t depth;
+};
+
+struct multiboot_header_tag_module_align
+{
+ multiboot_uint16_t type;
+ multiboot_uint16_t flags;
+ multiboot_uint32_t size;
+};
+
+struct multiboot_header_tag_relocatable
+{
+ multiboot_uint16_t type;
+ multiboot_uint16_t flags;
+ multiboot_uint32_t size;
+ multiboot_uint32_t min_addr;
+ multiboot_uint32_t max_addr;
+ multiboot_uint32_t align;
+ multiboot_uint32_t preference;
+};
+
+struct multiboot_color
+{
+ multiboot_uint8_t red;
+ multiboot_uint8_t green;
+ multiboot_uint8_t blue;
+};
+
+struct multiboot_mmap_entry
+{
+ multiboot_uint64_t addr;
+ multiboot_uint64_t len;
+#define MULTIBOOT_MEMORY_AVAILABLE 1
+#define MULTIBOOT_MEMORY_RESERVED 2
+#define MULTIBOOT_MEMORY_ACPI_RECLAIMABLE 3
+#define MULTIBOOT_MEMORY_NVS 4
+#define MULTIBOOT_MEMORY_BADRAM 5
+ multiboot_uint32_t type;
+ multiboot_uint32_t zero;
+};
+typedef struct multiboot_mmap_entry multiboot_memory_map_t;
+
+struct multiboot_tag
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+};
+
+struct multiboot_tag_string
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ char string[0];
+};
+
+struct multiboot_tag_module
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint32_t mod_start;
+ multiboot_uint32_t mod_end;
+ char cmdline[0];
+};
+
+struct multiboot_tag_basic_meminfo
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint32_t mem_lower;
+ multiboot_uint32_t mem_upper;
+};
+
+struct multiboot_tag_bootdev
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint32_t biosdev;
+ multiboot_uint32_t slice;
+ multiboot_uint32_t part;
+};
+
+struct multiboot_tag_mmap
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint32_t entry_size;
+ multiboot_uint32_t entry_version;
+ struct multiboot_mmap_entry entries[0];
+};
+
+struct multiboot_vbe_info_block
+{
+ multiboot_uint8_t external_specification[512];
+};
+
+struct multiboot_vbe_mode_info_block
+{
+ multiboot_uint8_t external_specification[256];
+};
+
+struct multiboot_tag_vbe
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+
+ multiboot_uint16_t vbe_mode;
+ multiboot_uint16_t vbe_interface_seg;
+ multiboot_uint16_t vbe_interface_off;
+ multiboot_uint16_t vbe_interface_len;
+
+ struct multiboot_vbe_info_block vbe_control_info;
+ struct multiboot_vbe_mode_info_block vbe_mode_info;
+};
+
+struct multiboot_tag_framebuffer_common
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+
+ multiboot_uint64_t framebuffer_addr;
+ multiboot_uint32_t framebuffer_pitch;
+ multiboot_uint32_t framebuffer_width;
+ multiboot_uint32_t framebuffer_height;
+ multiboot_uint8_t framebuffer_bpp;
+#define MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED 0
+#define MULTIBOOT_FRAMEBUFFER_TYPE_RGB 1
+#define MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT 2
+ multiboot_uint8_t framebuffer_type;
+ multiboot_uint16_t reserved;
+};
+
+struct multiboot_tag_framebuffer
+{
+ struct multiboot_tag_framebuffer_common common;
+
+ union {
+ struct
+ {
+ multiboot_uint16_t framebuffer_palette_num_colors;
+ struct multiboot_color framebuffer_palette[0];
+ };
+ struct
+ {
+ multiboot_uint8_t framebuffer_red_field_position;
+ multiboot_uint8_t framebuffer_red_mask_size;
+ multiboot_uint8_t framebuffer_green_field_position;
+ multiboot_uint8_t framebuffer_green_mask_size;
+ multiboot_uint8_t framebuffer_blue_field_position;
+ multiboot_uint8_t framebuffer_blue_mask_size;
+ };
+ };
+};
+
+struct multiboot_tag_elf_sections
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint32_t num;
+ multiboot_uint32_t entsize;
+ multiboot_uint32_t shndx;
+ char sections[0];
+};
+
+struct multiboot_tag_apm
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint16_t version;
+ multiboot_uint16_t cseg;
+ multiboot_uint32_t offset;
+ multiboot_uint16_t cseg_16;
+ multiboot_uint16_t dseg;
+ multiboot_uint16_t flags;
+ multiboot_uint16_t cseg_len;
+ multiboot_uint16_t cseg_16_len;
+ multiboot_uint16_t dseg_len;
+};
+
+struct multiboot_tag_efi32
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint32_t pointer;
+};
+
+struct multiboot_tag_efi64
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint64_t pointer;
+};
+
+struct multiboot_tag_smbios
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint8_t major;
+ multiboot_uint8_t minor;
+ multiboot_uint8_t reserved[6];
+ multiboot_uint8_t tables[0];
+};
+
+struct multiboot_tag_old_acpi
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint8_t rsdp[0];
+};
+
+struct multiboot_tag_new_acpi
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint8_t rsdp[0];
+};
+
+struct multiboot_tag_network
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint8_t dhcpack[0];
+};
+
+struct multiboot_tag_efi_mmap
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint32_t descr_size;
+ multiboot_uint32_t descr_vers;
+ multiboot_uint8_t efi_mmap[0];
+};
+
+struct multiboot_tag_efi32_ih
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint32_t pointer;
+};
+
+struct multiboot_tag_efi64_ih
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint64_t pointer;
+};
+
+struct multiboot_tag_load_base_addr
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint32_t load_base_addr;
+};
+
+#endif /* ! ASM_FILE */
+
+#endif /* ! MULTIBOOT_HEADER */ \ No newline at end of file
diff --git a/kernel/include/proc/context.h b/kernel/include/proc/context.h
new file mode 100644
index 0000000..63c692e
--- /dev/null
+++ b/kernel/include/proc/context.h
@@ -0,0 +1,62 @@
+#pragma once
+
+#include "types.h"
+
+#include "mm/pagetable.h"
+
+/*
+ * The function pointer to be implemented by functions which are entry
+ * points for new threads.
+ */
+typedef void *(*context_func_t)(long, void *);
+
+typedef struct context
+{
+ uintptr_t c_rip; /* instruction pointer (RIP) */
+ uintptr_t c_rsp; /* stack pointer (RSP) */
+ uintptr_t c_rbp; /* frame pointer (RBP) */
+
+ pml4_t
+ *c_pml4; /* pointer to the top level page table (PML4) for this proc.
+ It's the 'root' of the page table where virtual address -> physical address
+ lookup starts. */
+
+ uintptr_t c_kstack;
+ size_t c_kstacksz;
+} context_t;
+
+/**
+ * Initialize the given context such that when it begins execution it
+ * will execute func(arg1,arg2). A kernel stack and page directory
+ * exclusive to this context must also be provided.
+ *
+ * @param c the context to initialize
+ * @param func the function which will begin executing when this
+ * context is first made active
+ * @param arg1 the first argument to func
+ * @param arg2 the second argument to func
+ * @param kstack a pointer to the kernel stack this context will use
+ * @param kstacksz the size of the kernel stack
+ * @param pdptr the pagetable this context will use
+ */
+void context_setup(context_t *c, context_func_t func, long arg1, void *arg2,
+ void *kstack, size_t kstacksz, pml4_t *pml4);
+
+void context_setup_raw(context_t *c, void (*func)(), void *kstack,
+ size_t kstacksz, pml4_t *pml4);
+/**
+ * Makes the given context the one currently running on the CPU. Use
+ * this mainly for the initial context.
+ *
+ * @param c the context to make active
+ */
+void context_make_active(context_t *c);
+
+/**
+ * Save the current state of the machine into the old context, and begin
+ * executing the new context. Used primarily by the scheduler.
+ *
+ * @param oldc the context to switch from
+ * @param newc the context to switch to
+ */
+void context_switch(context_t *oldc, context_t *newc);
diff --git a/kernel/include/proc/core.h b/kernel/include/proc/core.h
new file mode 100644
index 0000000..9d6eb16
--- /dev/null
+++ b/kernel/include/proc/core.h
@@ -0,0 +1,15 @@
+#pragma once
+
+#include "proc/context.h"
+#include "proc/sched.h"
+#include "proc/spinlock.h"
+
+typedef struct core
+{
+ long kc_id;
+ context_t kc_ctx;
+
+ ktqueue_t *kc_queue;
+
+ uintptr_t kc_csdpaddr;
+} core_t;
diff --git a/kernel/include/proc/kmutex.h b/kernel/include/proc/kmutex.h
new file mode 100644
index 0000000..37d8ece
--- /dev/null
+++ b/kernel/include/proc/kmutex.h
@@ -0,0 +1,60 @@
+#pragma once
+
+#include "proc/sched.h"
+#include "proc/spinlock.h"
+
+/*===========
+ * Structures
+ *==========*/
+
+typedef struct kmutex
+{
+ ktqueue_t km_waitq; /* wait queue */
+ struct kthread *km_holder; /* current holder */
+ list_link_t km_link;
+} kmutex_t;
+
+#define KMUTEX_INITIALIZER(mtx) \
+ { \
+ .km_waitq = KTQUEUE_INITIALIZER((mtx).km_waitq), .km_holder = NULL, \
+ .km_link = LIST_LINK_INITIALIZER((mtx).km_link), \
+ }
+
+/*==========
+ * Functions
+ *=========*/
+
+/**
+ * Initializes a mutex.
+ *
+ * @param mtx the mutex
+ */
+void kmutex_init(kmutex_t *mtx);
+
+/**
+ * Locks the specified mutex.
+ *
+ * Note: This function may block.
+ *
+ * Note: These locks are not re-entrant
+ *
+ * @param mtx the mutex to lock
+ */
+void kmutex_lock(kmutex_t *mtx);
+
+/**
+ * Unlocks the specified mutex.
+ *
+ * @param mtx the mutex to unlock
+ */
+void kmutex_unlock(kmutex_t *mtx);
+
+/**
+ * Indicates if a mutex has waiters.
+ */
+long kmutex_has_waiters(kmutex_t *mtx);
+
+/**
+ * Indicates if curthr owns a mutex.
+ */
+long kmutex_owns_mutex(kmutex_t *mtx);
diff --git a/kernel/include/proc/kthread.h b/kernel/include/proc/kthread.h
new file mode 100644
index 0000000..6bc66be
--- /dev/null
+++ b/kernel/include/proc/kthread.h
@@ -0,0 +1,106 @@
+#pragma once
+
+#include <proc/context.h>
+#include <proc/sched.h>
+#include <proc/spinlock.h>
+#include <util/list.h>
+
+/*=====================
+ * Types and structures
+ *====================*/
+
+/*
+ * Alias for an entry point function of a new thread.
+ */
+typedef context_func_t kthread_func_t;
+
+/*
+ * Thread states.
+ */
+typedef enum
+{
+ KT_NO_STATE, /* Illegal state */
+ KT_ON_CPU, /* Currently running */
+ KT_RUNNABLE, /* On the run queue */
+ KT_SLEEP, /* Blocked indefinitely */
+ KT_SLEEP_CANCELLABLE, /* Blocked, but can be interrupted */
+ KT_EXITED /* Exited, waiting to be joined */
+} kthread_state_t;
+
+/*
+ * Thread descriptor.
+ */
+typedef struct kthread
+{
+ context_t kt_ctx; /* Thread context */
+ char *kt_kstack; /* Kernel stack */
+ void *kt_retval; /* Return value */
+ long kt_errno; /* Errno of most recent syscall */
+ struct proc *kt_proc; /* Corresponding process */
+
+ long kt_cancelled; /* Set if the thread has been cancelled */
+ ktqueue_t *kt_wchan; /* If blocking, the queue this thread is blocked on */
+ kthread_state_t kt_state;
+
+ list_link_t kt_plink; /* Link on the process's thread list, p_threads */
+ list_link_t
+ kt_qlink; /* Link on some ktqueue if the thread is not running */
+
+ list_t kt_mutexes; /* List of owned mutexes, for use in debugging */
+ long kt_recent_core; /* For SMP */
+
+ uint64_t kt_preemption_count;
+} kthread_t;
+
+/*==========
+ * Functions
+ *=========*/
+
+/**
+ * Initializes the kthread subsystem at system startup.
+ */
+void kthread_init(void);
+
+/**
+ * Allocates and initializes a kernel thread.
+ *
+ * @param proc the process in which the thread will run
+ * @param func the function that will be called when the newly created
+ * thread starts executing
+ * @param arg1 the first argument to func
+ * @param arg2 the second argument to func
+ * @return the newly created thread
+ *
+ */
+kthread_t *kthread_create(struct proc *proc, kthread_func_t func, long arg1,
+ void *arg2);
+
+/**
+ * Creates a clone of the specified thread
+ *
+ * @param thr the thread to clone
+ * @return a clone of thr
+ */
+kthread_t *kthread_clone(kthread_t *thr);
+
+/**
+ * Frees resources associated with a thread.
+ *
+ * @param thr the thread to free
+ */
+void kthread_destroy(kthread_t *thr);
+
+/**
+ * Cancels a thread.
+ *
+ * @param kthr the thread to be cancelled
+ * @param retval the return value for the thread
+ */
+void kthread_cancel(kthread_t *kthr, void *retval);
+
+/**
+ * Exits the current thread.
+ *
+ * @param retval the return value for the thread
+ */
+void kthread_exit(void *retval);
diff --git a/kernel/include/proc/proc.h b/kernel/include/proc/proc.h
new file mode 100644
index 0000000..bc608a0
--- /dev/null
+++ b/kernel/include/proc/proc.h
@@ -0,0 +1,200 @@
+#pragma once
+
+#include "config.h"
+#include "mm/pagetable.h"
+#include "proc/kthread.h"
+#include "types.h"
+#include "vm/vmmap.h"
+
+/*===========
+ * Structures
+ *==========*/
+
+/*
+ * Process resource information
+ */
+#define PROC_MAX_COUNT 65536
+#define PROC_NAME_LEN 256
+
+/* Process states */
+typedef enum
+{
+ PROC_RUNNING, /* Has running threads */
+ PROC_DEAD /* Exited, but not yet wait'ed */
+} proc_state_t;
+
+/* Process descriptor */
+typedef struct proc
+{
+ pid_t p_pid; /* Process ID */
+ char p_name[PROC_NAME_LEN]; /* Process name */
+
+ list_t p_threads; /* Threads list */
+ list_t p_children; /* Children list */
+ struct proc *p_pproc; /* Parent process */
+
+ list_link_t p_list_link; /* Link of list of all processes */
+ list_link_t p_child_link; /* Link on parent's list of children */
+
+ long p_status; /* Exit status */
+ proc_state_t p_state; /* Process state */
+
+ pml4_t *p_pml4; /* Page table. */
+
+ /*
+ * If a parent is waiting on a child, the parent puts itself on its own
+ * p_wait queue. When a child terminates, it broadcasts on its parent's
+ * p_wait to wake it up.
+ */
+ ktqueue_t p_wait;
+
+ /* VFS related */
+ struct file *p_files[NFILES]; /* Open files */
+ struct vnode *p_cwd; /* Current working directory */
+
+ /* VM related */
+ /*
+ * The current value of a process's break is maintained in the 'p_brk'.
+ *
+ * The 'p_brk' and 'p_start_brk' members of a proc_t struct are initialized
+ * by the loader. 'p_start_brk' is subsequently never modified; it always
+ * holds the initial value of the break.
+ *
+ * The loader sets 'p_start_brk' to be the end of the bss section (search
+ * online for memory layout diagrams of a running process for more
+ * details).
+ *
+ * These are both addresses.
+ */
+ void *p_brk; /* Process break; see brk(2) */
+ void *p_start_brk; /* Initial value of process break */
+ struct vmmap *p_vmmap; /* List of areas mapped into process's
+ user address space. */
+} proc_t;
+
+/*==========
+ * Functions
+ *=========*/
+
+/**
+ * Initializes the proc subsystem at system startup.
+ */
+void proc_init(void);
+
+/**
+ * Initializes the special idleproc at system startup.
+ */
+void proc_idleproc_init();
+
+/**
+ * Shuts down certain subsystems at system shutdown.
+ */
+void initproc_finish();
+
+/**
+ * Allocates and initializes a new process.
+ *
+ * @param name the name to give the newly created process
+ * @return the newly created process
+ */
+proc_t *proc_create(const char *name);
+
+/**
+ * Frees all the resources associated with a process.
+ *
+ * @param proc process to destroy
+ */
+void proc_destroy(proc_t *proc);
+
+/**
+ * Handles exiting the current process.
+ *
+ * @param retval exit code for the thread and process
+ */
+void proc_thread_exiting(void *retval);
+
+/**
+ * Stops another process from running again by cancelling all its
+ * threads.
+ *
+ * @param proc the process to kill
+ * @param status the status the process should exit with
+ */
+void proc_kill(proc_t *proc, long status);
+
+/**
+ * Kills every process except for the idle process and direct children
+ * of the idle process.
+ */
+void proc_kill_all(void);
+
+/*========================
+ * Functions: System calls
+ *=======================*/
+
+/**
+ * Implements the _exit(2) system call.
+ *
+ * @param status the exit status of the process
+ */
+void do_exit(long status);
+
+/**
+ * Implements the waitpid(2) system call.
+ *
+ * @param pid the pid to wait on, or -1 to wait on any child
+ * @param status used to return the exit status of the child
+ * @param options only 0 is supported (no options)
+ *
+ * @return the pid of the child process which was cleaned up, or
+ * - ENOTSUP invalid input
+ * - ECHILD valid child could not be found
+ */
+pid_t do_waitpid(pid_t pid, int *status, int options);
+
+/**
+ * This function implements the fork(2) system call.
+ *
+ * @param regs the register state at the time of the system call
+ */
+struct regs;
+long do_fork(struct regs *regs);
+
+/*===========
+ * Miscellany
+ *==========*/
+
+/*
+ * Special PIDs reserved for specific processes
+ */
+#define PID_IDLE 0
+#define PID_INIT 1
+
+/*
+ * Enable global use of idleproc
+ */
+extern proc_t idleproc;
+
+/*=====================
+ * Functions: Debugging
+ *====================*/
+
+/**
+ * Provides detailed debug information about a given process.
+ *
+ * @param arg a pointer to the process
+ * @param buf buffer to write to
+ * @param osize size of the buffer
+ * @return the remaining size of the buffer
+ */
+size_t proc_info(const void *arg, char *buf, size_t osize);
+
+/**
+ * Provides debug information overview of all processes.
+ *
+ * @param arg must be NULL
+ * @param buf buffer to write to
+ * @param osize size of the buffer
+ * @return the remaining size of the buffer
+ */
+size_t proc_list_info(const void *arg, char *buf, size_t osize); \ No newline at end of file
diff --git a/kernel/include/proc/sched.h b/kernel/include/proc/sched.h
new file mode 100644
index 0000000..343e8d5
--- /dev/null
+++ b/kernel/include/proc/sched.h
@@ -0,0 +1,126 @@
+#pragma once
+
+#include "proc/spinlock.h"
+#include "util/list.h"
+
+/*===========
+ * Structures
+ *==========*/
+
+/*
+ * Queue structure for kthreads
+ * Note that ktqueue functions are private - managing the queue
+ * should be done within sched.c, or using public functions
+ */
+typedef struct ktqueue
+{
+ list_t tq_list;
+ size_t tq_size;
+} ktqueue_t;
+
+/*
+ * Macro to initialize a ktqueue. See sched_queue_init for how the
+ * queue should be initialized in your code.
+ */
+#define KTQUEUE_INITIALIZER(ktqueue) \
+ { \
+ .tq_list = LIST_INITIALIZER((ktqueue).tq_list), \
+ }
+
+/*
+ * kthread declaration to make function signatures happy
+ */
+struct kthread;
+
+/*==========
+ * Functions
+ *=========*/
+
+/**
+ * Runs a new thread from the run queue.
+ *
+ * @param queue the queue to place curthr on
+ */
+void sched_switch(ktqueue_t *queue);
+
+/**
+ * Helps with context switching.
+ */
+void core_switch();
+
+/**
+ * Yields the CPU to another runnable thread.
+ */
+void sched_yield();
+
+/**
+ * Enables a thread to be selected by the scheduler to run.
+ *
+ * @param thr the thread to make runnable
+ */
+void sched_make_runnable(struct kthread *thr);
+
+/**
+ * Causes the current thread to enter into an uncancellable sleep on
+ * the given queue.
+ *
+ * @param q the queue to sleep on
+ * @param lock optional lock for release in another context
+ */
+void sched_sleep_on(ktqueue_t *q);
+
+/**
+ * Causes the current thread to enter into a cancellable sleep on the
+ * given queue.
+ *
+ * @param queue the queue to sleep on
+ * @param lock optional lock for release in another context
+ * @return -EINTR if the thread was cancelled and 0 otherwise
+ */
+long sched_cancellable_sleep_on(ktqueue_t *queue);
+
+/**
+ * Wakes up a thread from q.
+ *
+ * @param q queue
+ * @param thrp if an address is provided, *thrp is set to the woken up thread
+ *
+ */
+void sched_wakeup_on(ktqueue_t *q, struct kthread **thrp);
+
+/**
+ * Wake up all threads running on the queue.
+ *
+ * @param q the queue to wake up threads from
+ */
+void sched_broadcast_on(ktqueue_t *q);
+
+/**
+ * Cancel the given thread from the queue it sleeps on.
+ *
+ * @param the thread to cancel sleep from
+ */
+void sched_cancel(struct kthread *thr);
+
+/**
+ * Initializes a queue.
+ *
+ * @param queue the queue
+ */
+void sched_queue_init(ktqueue_t *queue);
+
+/**
+ * Returns true if the queue is empty.
+ *
+ * @param queue the queue
+ * @return true if the queue is empty
+ */
+long sched_queue_empty(ktqueue_t *queue);
+
+/**
+ * Functions for managing the current thread's preemption status.
+ */
+void preemption_disable();
+void preemption_enable();
+void preemption_reset();
+long preemption_enabled(); \ No newline at end of file
diff --git a/kernel/include/proc/spinlock.h b/kernel/include/proc/spinlock.h
new file mode 100644
index 0000000..4ce57c8
--- /dev/null
+++ b/kernel/include/proc/spinlock.h
@@ -0,0 +1,37 @@
+#pragma once
+
+typedef struct spinlock
+{
+ volatile char s_locked;
+} spinlock_t;
+
+#define SPINLOCK_INITIALIZER(lock) \
+ { \
+ .s_locked = 0 \
+ }
+
+/**
+ * Initializes the fields of the specified spinlock_t
+ * @param lock the spinlock to initialize
+ */
+void spinlock_init(spinlock_t *lock);
+
+/**
+ * Locks the specified spinlock.
+ *
+ * Note: this function may spin on the current core.
+ *
+ * Note: these locks are not re-entrant
+ *
+ * @param lock the spinlock to lock
+ */
+void spinlock_lock(spinlock_t *lock);
+
+/**
+ * Unlocks the specified spinlock.
+ *
+ * @param lock the spinlock to unlock
+ */
+void spinlock_unlock(spinlock_t *lock);
+
+long spinlock_ownslock(spinlock_t *lock);
diff --git a/kernel/include/stdarg.h b/kernel/include/stdarg.h
new file mode 100644
index 0000000..ea7b872
--- /dev/null
+++ b/kernel/include/stdarg.h
@@ -0,0 +1,7 @@
+#pragma once
+
+typedef __builtin_va_list va_list;
+
+#define va_start(v, l) __builtin_va_start(v, l)
+#define va_end(v) __builtin_va_end(v)
+#define va_arg(v, l) __builtin_va_arg(v, l)
diff --git a/kernel/include/test/driverstest.h b/kernel/include/test/driverstest.h
new file mode 100644
index 0000000..16e0bc5
--- /dev/null
+++ b/kernel/include/test/driverstest.h
@@ -0,0 +1,3 @@
+#pragma once
+
+long driverstest_main(long, void*); \ No newline at end of file
diff --git a/kernel/include/test/kshell/io.h b/kernel/include/test/kshell/io.h
new file mode 100644
index 0000000..72ac92a
--- /dev/null
+++ b/kernel/include/test/kshell/io.h
@@ -0,0 +1,61 @@
+#pragma once
+
+#include "test/kshell/kshell.h"
+
+/*
+ * When writing a kernel shell command, make sure to use the following
+ * I/O functions.
+ *
+ * Before VFS is not enabled, the kernel shell will use functions from
+ * chardev.h to get a pointer the the chardev_t struct for the TTY.
+ *
+ * When VFS is enabled, the kernel shell will use the functions from
+ * vfs_syscall.h to open and close the TTY and perform I/O operations
+ * on the TTY.
+ *
+ * If you use the functions below, this process will be completely
+ * transparent.
+ */
+
+/**
+ * Replacement for do_write.
+ *
+ * @param ksh the kshell to write to
+ * @param buf the buffer to write out to the kshell
+ * @param nbytes the maximum number of bytes to write
+ * @return number of bytes written on sucess and <0 on error
+ */
+long kshell_write(kshell_t *ksh, const void *buf, size_t nbytes);
+
+/**
+ * Replacement for do_read.
+ *
+ * @param ksh the kshell to read from
+ * @param buf the buffer to store data read from the kshell
+ * @param nbytes the maximum number of bytes to read
+ * @param number of bytes read on success and <0 on error
+ */
+long kshell_read(kshell_t *ksh, void *buf, size_t nbytes);
+
+/* Unless an error occurs, guarantees that all of buf will be
+ * written */
+/**
+ * Writes a specified number of bytes from a buffer to the
+ * kshell. Unlike kshell_write, this function guarantees it will write
+ * out the desired number of bytes.
+ *
+ * @param ksh the kshell to write to
+ * @param buf the buffer to write out to the kshell
+ * @param nbytes the number of bytes to write
+ * @return number of bytes written on success and <0 on error
+ */
+long kshell_write_all(kshell_t *ksh, void *buf, size_t nbytes);
+
+/* Replacement for printf */
+/**
+ * Write output to a kshell according to a format string.
+ *
+ * @param ksh the kshell to write to
+ * @param fmt the format string
+ */
+void kprintf(kshell_t *ksh, const char *fmt, ...);
diff --git a/kernel/include/test/kshell/kshell.h b/kernel/include/test/kshell/kshell.h
new file mode 100644
index 0000000..9baf4f5
--- /dev/null
+++ b/kernel/include/test/kshell/kshell.h
@@ -0,0 +1,52 @@
+#pragma once
+
+#include "types.h"
+
+typedef struct kshell kshell_t;
+
+typedef long (*kshell_cmd_func_t)(kshell_t *, size_t argc, char **argv);
+
+/**
+ * Process init function for a new kshell.
+ */
+void *kshell_proc_run(long tty, void *arg2);
+
+/**
+ * Adds a command to the global command table for kernel shells.
+ *
+ * Note: When writing commands for the kernel shell, you _MUST_ use
+ * the I/O functions from kshell_io.h instead of normal I/O
+ * functions. See comment in kshell_io.h for more information.
+ *
+ * @param name the name of the command. Typing this name into the
+ * shell will execute the command.
+ * @param command the command to add to the shell
+ * @param desc a description of the command. This is what will be
+ * printed by the command 'help <command>'
+ */
+void kshell_add_command(const char *name, kshell_cmd_func_t command,
+ const char *desc);
+
+/**
+ * Allocates and initializes a kshell.
+ *
+ * @param bd the byte device the kshell will read from and write to
+ * @return a kshell
+ */
+kshell_t *kshell_create(uint8_t ttyid);
+
+/**
+ * Destroys a kshell.
+ *
+ * @param ksh the kshell to destroy
+ */
+void kshell_destroy(kshell_t *ksh);
+
+/**
+ * Reads from the kshell's byte device and attempts to execute a
+ * command.
+ *
+ * @param ksh the kshell to execute commands with
+ * @return the number of bytes read
+ */
+long kshell_execute_next(kshell_t *ksh);
diff --git a/kernel/include/test/proctest.h b/kernel/include/test/proctest.h
new file mode 100644
index 0000000..94b3d9c
--- /dev/null
+++ b/kernel/include/test/proctest.h
@@ -0,0 +1,3 @@
+#pragma once
+
+long proctest_main(long, void *); \ No newline at end of file
diff --git a/kernel/include/test/s5fstest.h b/kernel/include/test/s5fstest.h
new file mode 100644
index 0000000..b6b5279
--- /dev/null
+++ b/kernel/include/test/s5fstest.h
@@ -0,0 +1,3 @@
+#pragma once
+
+long s5fstest_main(int, void *);
diff --git a/kernel/include/test/usertest.h b/kernel/include/test/usertest.h
new file mode 100644
index 0000000..3d2296f
--- /dev/null
+++ b/kernel/include/test/usertest.h
@@ -0,0 +1,51 @@
+#pragma once
+
+#ifndef __KERNEL__
+
+#include "sys/types.h"
+#include "unistd.h"
+
+#else
+#include "types.h"
+#endif
+
+#include <stdarg.h>
+
+#define test_assert(expr, fmt, args...) \
+ _test_assert(expr, __FILE__, __LINE__, #expr, fmt, ##args)
+
+#ifndef __KERNEL__
+#define test_fork_begin() \
+ do \
+ { \
+ pid_t __test_pid = fork(); \
+ if (0 == __test_pid) \
+ { \
+ do
+
+#define test_fork_end(status) \
+ while (0) \
+ ; \
+ exit(0); \
+ } /* if */ \
+ waitpid(__test_pid, status, 0); \
+ } \
+ while (0) \
+ ;
+#endif
+
+void test_init(void);
+
+void test_fini(void);
+
+const char *test_errstr(int err);
+
+typedef void (*test_pass_func_t)(int val, const char *file, int line,
+ const char *name, const char *fmt,
+ va_list args);
+
+typedef void (*test_fail_func_t)(const char *file, int line, const char *name,
+ const char *fmt, va_list args);
+
+int _test_assert(int val, const char *file, int line, const char *name,
+ const char *fmt, ...);
diff --git a/kernel/include/test/vfstest/vfstest.h b/kernel/include/test/vfstest/vfstest.h
new file mode 100644
index 0000000..4f86563
--- /dev/null
+++ b/kernel/include/test/vfstest/vfstest.h
@@ -0,0 +1,156 @@
+#pragma once
+
+/* "kernel" utility things */
+
+/* fprintf */
+#define fprintf(fd, fmt, args...) dbg(DBG_TEST, fmt, ##args)
+#define printf(fmt, args...) dbg(DBG_TEST, fmt, ##args)
+
+/* errno */
+#define errno (curthr->kt_errno)
+
+/* malloc/free */
+#define malloc kmalloc
+#define free kfree
+
+/* The "kernel" system calls */
+#define ksyscall(name, formal, actual) \
+ static long ksys_##name formal \
+ { \
+ long ret = do_##name actual; \
+ if (ret < 0) \
+ { \
+ errno = -ret; \
+ return -1; \
+ } \
+ return ret; \
+ }
+
+ksyscall(close, (int fd), (fd))
+
+ ksyscall(read, (int fd, void *buf, size_t nbytes), (fd, buf, nbytes))
+
+ ksyscall(write, (int fd, const void *buf, size_t nbytes),
+ (fd, buf, nbytes))
+
+ ksyscall(dup, (int fd), (fd))
+
+ ksyscall(dup2, (int ofd, int nfd), (ofd, nfd))
+
+ ksyscall(mkdir, (const char *path), (path))
+
+ ksyscall(rmdir, (const char *path), (path))
+
+ ksyscall(link, (const char *old, const char *new),
+ (old, new))
+
+ ksyscall(unlink, (const char *path), (path))
+
+ ksyscall(rename,
+ (const char *oldpath,
+ const char *newpath),
+ (oldpath, newpath))
+
+ ksyscall(chdir, (const char *path),
+ (path))
+
+ ksyscall(lseek,
+ (int fd, int offset,
+ int whence),
+ (fd, offset, whence))
+
+ ksyscall(getdent,
+ (int fd,
+ struct dirent *dirp),
+ (fd, dirp))
+
+ ksyscall(stat,
+ (const char *path,
+ struct stat *uf),
+ (path, uf))
+
+ ksyscall(open,
+ (const char
+ *filename,
+ int flags),
+ (filename,
+ flags))
+#define ksys_exit do_exit
+
+ long ksys_getdents(
+ int fd,
+ struct dirent
+ *dirp,
+ unsigned int
+ count)
+{
+ size_t numbytesread = 0;
+ int nbr = 0;
+ dirent_t tempdirent;
+
+ if (count < sizeof(dirent_t))
+ {
+ curthr->kt_errno = EINVAL;
+ return -1;
+ }
+
+ while (numbytesread < count)
+ {
+ if ((nbr = do_getdent(fd, &tempdirent)) < 0)
+ {
+ curthr->kt_errno = -nbr;
+ return -1;
+ }
+ if (nbr == 0)
+ {
+ return numbytesread;
+ }
+ memcpy(dirp, &tempdirent, sizeof(dirent_t));
+
+ KASSERT(nbr == sizeof(dirent_t));
+
+ dirp++;
+ numbytesread += nbr;
+ }
+ return numbytesread;
+}
+
+/*
+ * Redirect system calls to kernel system calls.
+ */
+#define mkdir(a, b) ksys_mkdir(a)
+#define rmdir ksys_rmdir
+#define mount ksys_mount
+#define umount ksys_umount
+#define open(a, b, c) ksys_open(a, b)
+#define close ksys_close
+#define link ksys_link
+#define rename ksys_rename
+#define unlink ksys_unlink
+#define read ksys_read
+#define write ksys_write
+#define lseek ksys_lseek
+#define dup ksys_dup
+#define dup2 ksys_dup2
+#define chdir ksys_chdir
+#define stat(a, b) ksys_stat(a, b)
+#define getdents(a, b, c) ksys_getdents(a, b, c)
+#define exit(a) ksys_exit(a)
+
+/* Random numbers */
+/* Random int between lo and hi inclusive */
+#define RAND_MAX INT_MAX
+#define RANDOM(lo, hi) \
+ ((lo) + \
+ (((hi) - (lo) + 1) * (randseed = (randseed * 4096 + 150889) % 714025)) / \
+ 714025)
+
+static unsigned long long randseed = 123456L;
+
+static unsigned long long rand(void)
+{
+ randseed = (randseed * 4096 + 150889) % RAND_MAX;
+ return randseed;
+}
+
+static void srand(unsigned int seed) { randseed = seed; }
diff --git a/kernel/include/types.h b/kernel/include/types.h
new file mode 100644
index 0000000..e159fc1
--- /dev/null
+++ b/kernel/include/types.h
@@ -0,0 +1,31 @@
+#pragma once
+
+/* Kernel and user header (via symlink) */
+
+#define NULL 0
+
+#define packed __attribute__((packed))
+
+typedef signed char int8_t;
+typedef unsigned char uint8_t;
+typedef signed short int16_t;
+typedef unsigned short uint16_t;
+typedef signed int int32_t;
+typedef unsigned int uint32_t;
+
+typedef signed long int64_t;
+typedef unsigned long uint64_t;
+typedef signed long intptr_t;
+typedef unsigned long uintptr_t;
+typedef uint64_t size_t;
+typedef int64_t ssize_t;
+typedef int64_t off_t;
+
+typedef int32_t pid_t;
+typedef uint16_t mode_t;
+typedef uint32_t blocknum_t;
+typedef uint32_t ino_t;
+typedef uint32_t devid_t;
+
+typedef uint64_t time_t;
+typedef uint64_t useconds_t; \ No newline at end of file
diff --git a/kernel/include/util/atomic.h b/kernel/include/util/atomic.h
new file mode 100644
index 0000000..2c67e38
--- /dev/null
+++ b/kernel/include/util/atomic.h
@@ -0,0 +1,31 @@
+#ifndef ATOMIC_H
+#define ATOMIC_H
+
+typedef int atomic_t;
+
+#define ATOMIC_INIT(i) (i)
+
+static inline int __atomic_add_unless(atomic_t *a, int v, int u)
+{
+ int c, old;
+ c = __sync_fetch_and_add(a, 0);
+ while (c != u && (old = __sync_val_compare_and_swap(a, c, c + v)) != c)
+ c = old;
+ return c;
+}
+
+static inline void atomic_set(atomic_t *a, int i) { *a = i; }
+
+static inline void atomic_inc(atomic_t *a) { __sync_add_and_fetch(a, 1); }
+
+static inline int atomic_dec_and_test(atomic_t *a)
+{
+ return __sync_sub_and_fetch(a, 1) == 0;
+}
+
+static inline int atomic_inc_not_zero(atomic_t *a)
+{
+ return __atomic_add_unless(a, 1, 0);
+}
+
+#endif \ No newline at end of file
diff --git a/kernel/include/util/bits.h b/kernel/include/util/bits.h
new file mode 100644
index 0000000..d328574
--- /dev/null
+++ b/kernel/include/util/bits.h
@@ -0,0 +1,27 @@
+#pragma once
+
+#include "kernel.h"
+#include "types.h"
+
+#define BIT(n) (1 << (n))
+
+static inline void bit_flip(void *addr, uintptr_t bit)
+{
+ uint32_t *map = (uint32_t *)addr;
+ map += (bit >> 5);
+ *map ^= (uint32_t)(1 << (bit & 0x1f));
+}
+
+static inline int bit_check(const void *addr, uintptr_t bit)
+{
+ const uint32_t *map = (const uint32_t *)addr;
+ map += (bit >> 5);
+ return (*map & (1 << (bit & 0x1f)));
+}
+
+#define MOD_POW_2(x, y) ((x) & ((y)-1))
+
+#define IS_POW_2(x) (!MOD_POW_2(x, x))
+
+#define SELECT(condition, trueval, falseval) \
+ (!!(condition) * (trueval) + !condition * (falseval))
diff --git a/kernel/include/util/debug.h b/kernel/include/util/debug.h
new file mode 100644
index 0000000..7e6eb91
--- /dev/null
+++ b/kernel/include/util/debug.h
@@ -0,0 +1,305 @@
+#pragma once
+
+#include "globals.h"
+#include "main/interrupt.h"
+#include "mm/page.h"
+#include "proc/spinlock.h"
+#include "types.h"
+#include <main/apic.h>
+
+/* How to create new dbg modes:
+ *
+ * 1) Add a new '#define DBG_NAME DBG_MODE(number)' down below. Make sure the
+ * number you choose is not already being used and is less than 64.
+ * 2) Add a new entry into the DBG_TAB below. Make sure it is above the entry
+ * for "all". The first entry should be the name you want to use to
+ * disable/enable it in the makefile, the second should be the #define'd
+ * name you gave it in step 1 and the third should be a color from the list
+ * directly below this comment. Make sure you include the '\' at the end of
+ * the line with the new entry.
+ *
+ */
+
+/*
+ * These color definitions are from the ANSI specs.
+ * Do a web search for ANSI color codes to find out
+ * more funky shit like this
+ */
+
+#define _NORMAL_ "\x1b[0m"
+#define _BLACK_ "\x1b[30;47m"
+#define _RED_ "\x1b[31;40m"
+#define _GREEN_ "\x1b[32;40m"
+#define _YELLOW_ "\x1b[33;40m"
+#define _BLUE_ "\x1b[34;40m"
+#define _MAGENTA_ "\x1b[35;40m"
+#define _CYAN_ "\x1b[36;40m"
+#define _WHITE_ "\x1b[37;40m"
+
+#define _BRED_ "\x1b[1;31;40m"
+#define _BGREEN_ "\x1b[1;32;40m"
+#define _BYELLOW_ "\x1b[1;33;40m"
+#define _BBLUE_ "\x1b[1;34;40m"
+#define _BMAGENTA_ "\x1b[1;35;40m"
+#define _BCYAN_ "\x1b[1;36;40m"
+#define _BWHITE_ "\x1b[1;37;40m"
+
+#define DBG_MODE(x) (1ULL << (x))
+
+/* These defines list all of the possible debugging
+ * types. They are flags, so make sure to use the
+ * DBG_MODE macro to declare new values. */
+#define DBG_ALL (~0ULL) /* umm, "verbose" */
+#define DBG_CORE DBG_MODE(0) /* core boot code */
+#define DBG_MM DBG_MODE(1) /* memory management */
+#define DBG_INIT DBG_MODE(2) /* boot/init code */
+#define DBG_SCHED DBG_MODE(3) /* swtch, scheduling */
+#define DBG_DISK DBG_MODE(4) /* disk driver */
+#define DBG_TEMP DBG_MODE(5) /* for resolving temporary problems */
+#define DBG_KMALLOC DBG_MODE(6) /* kmalloc, kmem_cache_alloc */
+#define DBG_PAGEALLOC DBG_MODE(7) /* page_alloc, etc. */
+#define DBG_INTR DBG_MODE(8) /* misc. trap/interrupt */
+#define DBG_TERM DBG_MODE(9) /* the terminal device */
+#define DBG_FORK DBG_MODE(10) /* fork(2) */
+#define DBG_PROC DBG_MODE(11) /* process stuff */
+#define DBG_VNREF DBG_MODE(12) /* vnode reference counts */
+#define DBG_PFRAME DBG_MODE(13) /* pframe subsys */
+#define DBG_ERROR DBG_MODE(14) /* error conditions */
+#define DBG_SYSCALL DBG_MODE(15) /* system calls */
+#define DBG_FREF DBG_MODE(16) /* file reference counts */
+#define DBG_PGTBL DBG_MODE(17) /* page table manipulation */
+#define DBG_BRK DBG_MODE(18) /* process break; user memory alloc */
+#define DBG_EXEC DBG_MODE(19) /* new process exec */
+#define DBG_VFS DBG_MODE(20) /* vfs */
+#define DBG_S5FS DBG_MODE(21) /* system V file system */
+#define DBG_KB DBG_MODE(22) /* keyboard */
+#define DBG_THR DBG_MODE(23) /* thread stuff */
+#define DBG_PRINT DBG_MODE(24) /* printdbg.c */
+#define DBG_OSYSCALL DBG_MODE(25) /* other system calls */
+#define DBG_VM DBG_MODE(28) /* VM */
+#define DBG_TEST DBG_MODE(30) /* for testing code */
+#define DBG_TESTPASS DBG_MODE(31) /* for testing code */
+#define DBG_TESTFAIL DBG_MODE(32) /* for testing code */
+
+#define DBG_MEMDEV DBG_MODE(33) /* For memory devices ("null" and "zero") */
+#define DBG_ANON DBG_MODE(34) /* anonymous vm objects */
+#define DBG_VMMAP DBG_MODE(35) /* vm area mappings */
+#define DBG_ELF DBG_MODE(37) /* elf loader */
+#define DBG_USER DBG_MODE(38) /* user land */
+#define DBG_DEFAULT DBG_ERROR /* default modes, 0 for none */
+
+/* This defines the name that is used in the
+ * environment variable to turn on the given
+ * debugging type, along with the color of the debug type */
+/* NOTE that there is an order to these objects - the color chosen for a
+ * debug statement with multiple DBG specifiers will be the first matching
+ * result in the table */
+/* Note that rearranging the table will affect results, and may be beneficial
+ * later */
+#define DBG_TAB \
+ /* General */ \
+ {"error", DBG_ERROR, _BWHITE_}, {"temp", DBG_TEMP, _NORMAL_}, \
+ {"print", DBG_PRINT, _NORMAL_}, {"test", DBG_TEST, _RED_}, \
+ {"testpass", DBG_TESTPASS, _GREEN_}, \
+ {"testfail", DBG_TESTFAIL, _RED_}, /* Kern 1 */ \
+ {"proc", DBG_PROC, _BLUE_}, {"thr", DBG_THR, _CYAN_}, \
+ {"sched", DBG_SCHED, _GREEN_}, \
+ {"init", DBG_INIT, _NORMAL_}, /* Kern 2 */ \
+ {"term", DBG_TERM, _BMAGENTA_}, {"disk", DBG_DISK, _YELLOW_}, \
+ {"memdev", DBG_MEMDEV, _BBLUE_}, /* VFS */ \
+ {"vfs", DBG_VFS, _WHITE_}, {"fref", DBG_FREF, _MAGENTA_}, \
+ {"vnref", DBG_VNREF, _CYAN_}, /* S5FS */ \
+ {"s5fs", DBG_S5FS, _BRED_}, \
+ {"pframe", DBG_PFRAME, _BMAGENTA_}, /* VM */ \
+ {"anon", DBG_ANON, _WHITE_}, {"vmmap", DBG_VMMAP, _BGREEN_}, \
+ {"fork", DBG_FORK, _BYELLOW_}, {"brk", DBG_BRK, _YELLOW_}, \
+ {"exec", DBG_EXEC, _BRED_}, {"elf", DBG_ELF, _BGREEN_}, \
+ {"pgtbl", DBG_PGTBL, _BBLUE_}, {"osyscall", DBG_OSYSCALL, _BMAGENTA_}, \
+ {"vm", DBG_VM, _RED_}, /* Syscalls (VFS - VM) */ \
+ {"syscall", DBG_SYSCALL, _RED_}, /* support code */ \
+ {"intr", DBG_INTR, _BRED_}, {"kmalloc", DBG_KMALLOC, _MAGENTA_}, \
+ {"pagealloc", DBG_PAGEALLOC, _WHITE_}, {"kb", DBG_KB, _BLUE_}, \
+ {"core", DBG_CORE, _GREEN_}, {"mm", DBG_MM, _RED_}, \
+ {"user", DBG_USER, _BYELLOW_}, \
+ /* Note this MUST be last or the color code will break */ /* Also note \
+ that the \
+ color \
+ specified \
+ here is \
+ effectively \
+ the \
+ "default" \
+ */ \
+ {"all", DBG_ALL, _NORMAL_}, \
+ { \
+ NULL, 0, NULL \
+ }
+
+extern uint64_t dbg_modes;
+
+/* A common interface for functions which provide human-readable information
+ * about some data structure. Functions implementing this interface should fill
+ * buf with up to size characters to describe the data passed in as data, then
+ * return the number of characters writen. If there is not enough space in buf
+ * to write all information then only size characters will be writen and size
+ * will be returned. The returned string will be null terminated regardless of
+ * its length. */
+typedef size_t (*dbg_infofunc_t)(const void *data, char *buf, size_t size);
+
+#define DBG_BUFFER_SIZE (PAGE_SIZE)
+
+void dbg_init(void);
+
+void dbg_print(char *fmt, ...) __attribute__((format(printf, 1, 2)));
+
+void dbg_printinfo(dbg_infofunc_t func, const void *data);
+
+const char *dbg_color(uint64_t d_mode);
+
+#if defined(__SMP__) || defined(__KPREEMPT__)
+#define DEBUG_ENTER \
+ uint8_t __ipl = apic_initialized() ? intr_setipl(IPL_HIGH) : IPL_LOW; \
+#define DEBUG_EXIT \
+ if (apic_initialized()) \
+ intr_setipl(__ipl);
+#else
+#define DEBUG_ENTER \
+ do \
+ { \
+ } while (0);
+#define DEBUG_EXIT \
+ do \
+ { \
+ } while (0);
+#endif
+
+#ifndef NDEBUG
+#define dbg(mode, ...) \
+ do \
+ { \
+ if (dbg_active(mode)) \
+ { \
+ DEBUG_ENTER \
+ dbg_print("%s", dbg_color(mode)); \
+ dbg_print("C%ld P%ld ", curcore.kc_id, \
+ curproc ? curproc->p_pid : -1L); \
+ dbg_print("%s:%d %s(): ", __FILE__, __LINE__, __func__); \
+ dbg_print(__VA_ARGS__); \
+ dbg_print("%s", _NORMAL_); \
+ DEBUG_EXIT \
+ } \
+ } while (0)
+
+#define dbg_force(mode, ...) \
+ do \
+ { \
+ DEBUG_ENTER \
+ dbg_print("%s", dbg_color(mode)); \
+ dbg_print("C%ld P%ld ", curcore.kc_id, \
+ curproc ? curproc->p_pid : -1L); \
+ dbg_print("%s:%d %s(): ", __FILE__, __LINE__, __func__); \
+ dbg_print(__VA_ARGS__); \
+ dbg_print("%s", _NORMAL_); \
+ DEBUG_EXIT \
+ } while (0)
+
+#define dbgq(mode, ...) \
+ do \
+ { \
+ if (dbg_active(mode)) \
+ { \
+ DEBUG_ENTER \
+ dbg_print("%s", dbg_color(mode)); \
+ dbg_print("C%ld P%ld ", curcore.kc_id, \
+ curproc ? curproc->p_pid : -1L); \
+ dbg_print(__VA_ARGS__); \
+ dbg_print("%s", _NORMAL_); \
+ DEBUG_EXIT \
+ } \
+ } while (0)
+
+#define dbginfo(mode, func, data) \
+ do \
+ { \
+ if (dbg_active(mode)) \
+ { \
+ DEBUG_ENTER \
+ dbg_print("%s", dbg_color(mode)); \
+ dbg_print("C%ld P%ld ", curcore.kc_id, \
+ curproc ? curproc->p_pid : -1L); \
+ dbg_printinfo(func, data); \
+ dbg_print("%s", _NORMAL_); \
+ DEBUG_EXIT \
+ } \
+ } while (0)
+
+#define dbg_active(mode) (dbg_modes & (mode))
+
+void dbg_add_mode(const char *mode);
+
+void dbg_add_modes(const char *modes);
+
+#else
+#define dbg(mode, ...)
+#define dbgq(mode, ...)
+#define dbginfo(mode, func, data)
+#define dbg_active(mode) 0
+#define dbg_add_mode(mode)
+#define dbg_add_modes(modes)
+#endif
+
+noreturn void dbg_panic(const char *file, int line, const char *func,
+ const char *fmt, ...)
+ __attribute__((format(printf, 4, 5)));
+
+#define panic(...) dbg_panic(__FILE__, __LINE__, __func__, __VA_ARGS__)
+
+#ifndef NDEBUG
+#define KASSERT(x) \
+ do \
+ { \
+ if (!(x)) \
+ panic("assertion failed: %s", #x); \
+ } while (0)
+
+#define KASSERT_GENERIC(left, right, comparator, comp_str) \
+ do \
+ { \
+ int __left = (int)(left); \
+ int __right = (int)(right); \
+ if (!comparator(__left, __right)) \
+ { \
+ panic("assertion failed: %s %s %s. Left: %d, Right: %d\n", #left, \
+ comp_str, #right, __left, __right); \
+ } \
+ } while (0)
+
+static long equals(long l, long r)
+{
+ return l == r;
+}
+
+static long notequals(long l, long r) { return l != r; }
+
+static long lessthan(long l, long r) { return l < r; }
+
+static long greaterthan(long l, long r) { return l > r; }
+
+static long lessthaneq(long l, long r) { return l <= r; }
+
+static long greaterthaneq(long l, long r) { return l >= r; }
+
+#define KASSERTEQ(l, r) KASSERT_GENERIC(l, r, equals, "==")
+#define KASSERTNEQ(l, r) KASSERT_GENERIC(l, r, notequals, "!=")
+#define KASSERT_GREATER(l, r) KASSERT_GENERIC(l, r, greaterthan, ">")
+#define KASSERT_LESS(l, r) KASSERT_GENERIC(l, r, lessthan, "<")
+#define KASSERT_GREQ(l, r) KASSERT_GENERIC(l, r, greaterthaneq, ">=")
+#define KASSERT_LESSEQ(l, r) KASSERT_GENERIC(l, r, lessthaneq, "<=")
+#else
+#define KASSERT(x)
+#define KASSERTEQ(l, r)
+#define KASSERT_GREATER(l, r)
+#define KASSERT_LESS(l, r)
+#define KASSERT_GREQ(l, r)
+#define KASSERT_LESSEQ(l, r)
+#endif
diff --git a/kernel/include/util/delay.h b/kernel/include/util/delay.h
new file mode 100644
index 0000000..29cf3b2
--- /dev/null
+++ b/kernel/include/util/delay.h
@@ -0,0 +1,73 @@
+#pragma once
+
+#include "types.h"
+#include "util/debug.h"
+
+/* Approximate numbers taken from various points in Linux kernel */
+#define LOOPS_PER_JIFFY (1 << 12)
+#define HZ 100 /* Found this in a random place in the kernel */
+
+/* From arch/x86/lib/delay.c in Linux kernel */
+/*
+ * Precise Delay Loops for i386
+ *
+ * Copyright (C) 1993 Linus Torvalds
+ * Copyright (C) 1997 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
+ * Copyright (C) 2008 Jiri Hladky <hladky _dot_ jiri _at_ gmail _dot_ com>
+ *
+ * The __delay function must _NOT_ be inlined as its execution time
+ * depends wildly on alignment on many x86 processors. The additional
+ * jump magic is needed to get the timing stable on all the CPU's
+ * we have to worry about.
+ */
+
+static void __delay(unsigned long loops)
+{
+ __asm__ volatile(
+ " test %0,%0 \n"
+ " jz 3f \n"
+ " jmp 1f \n"
+
+ ".align 16 \n"
+ "1: jmp 2f \n"
+
+ ".align 16 \n"
+ "2: dec %0 \n"
+ " jnz 2b \n"
+ "3: dec %0 \n"
+
+ : /* we don't need output */
+ : "a"(loops));
+}
+
+static inline void __const_udelay(unsigned long xloops)
+{
+ int d0;
+
+ xloops *= 4;
+ __asm__ volatile("mull %%edx"
+ : "=d"(xloops), "=&a"(d0)
+ : "1"(xloops), "0"(LOOPS_PER_JIFFY * (HZ / 4)));
+
+ __delay(++xloops);
+}
+
+static inline void __udelay(unsigned long usecs)
+{
+ __const_udelay(usecs * 4295); /* 2**32 / 1000000 */
+}
+
+static inline void __ndelay(unsigned long nsecs)
+{
+ __const_udelay(nsecs * 5); /* 2**32 / 1000000000 */
+}
+
+#define udelay(n) \
+ (__builtin_constant_p(n) ? ((n) > 20000 ? panic("Delay too large!") \
+ : __const_udelay((n)*4295)) \
+ : __udelay(n))
+
+#define ndelay(n) \
+ (__builtin_constant_p(n) \
+ ? ((n) > 20000 ? panic("Delay too large!") : __const_udelay((n)*5)) \
+ : __ndelay(n))
diff --git a/kernel/include/util/gdb.h b/kernel/include/util/gdb.h
new file mode 100644
index 0000000..cc28dbc
--- /dev/null
+++ b/kernel/include/util/gdb.h
@@ -0,0 +1,5 @@
+#pragma once
+
+#define GDB_DEFINE_HOOK(name, ...) \
+ void __py_hook_##name(__VA_ARGS__) {}
+#define GDB_CALL_HOOK(name, ...) __py_hook_##name(__VA_ARGS__)
diff --git a/kernel/include/util/init.h b/kernel/include/util/init.h
new file mode 100644
index 0000000..9be7e3c
--- /dev/null
+++ b/kernel/include/util/init.h
@@ -0,0 +1,21 @@
+#pragma once
+
+#define init_func(func) \
+ __asm__( \
+ ".pushsection .init\n\t" \
+ ".long " #func \
+ "\n\t" \
+ ".string \"" #func \
+ "\"\n\t" \
+ ".popsection\n\t");
+#define init_depends(name) \
+ __asm__( \
+ ".pushsection .init\n\t" \
+ ".long 0\n\t" \
+ ".string \"" #name \
+ "\"\n\t" \
+ ".popsection\n\t");
+
+typedef void (*init_func_t)();
+
+void init_call_all(void);
diff --git a/kernel/include/util/list.h b/kernel/include/util/list.h
new file mode 100644
index 0000000..5fd44c1
--- /dev/null
+++ b/kernel/include/util/list.h
@@ -0,0 +1,224 @@
+#pragma once
+
+#include "kernel.h"
+
+/*
+ * Generic circular doubly linked list implementation.
+ *
+ * list_t is the head of the list.
+ * list_link_t should be included in structures which want to be
+ * linked on a list_t.
+ *
+ * All of the list functions take pointers to list_t and list_link_t
+ * types, unless otherwise specified.
+ *
+ * list_init(list) initializes a list_t to an empty list.
+ *
+ * list_empty(list) returns 1 iff the list is empty.
+ *
+ * Insertion functions.
+ * list_insert_head(list, link) inserts link at the front of the list.
+ * list_insert_tail(list, link) inserts link at the end of the list.
+ * list_insert_before(olink, nlink) inserts nlink before olink in list.
+ *
+ * Removal functions.
+ * Head is list->l_next. Tail is list->l_prev.
+ * The following functions should only be called on non-empty lists.
+ * list_remove(link) removes a specific element from the list.
+ * list_remove_head(list) removes the first element of list.
+ * list_remove_tail(list) removes the last element of list.
+ *
+ * Item accessors.
+ * list_item(link, type, member)
+ *
+ * Given a list_link_t* and the name of the type of structure which contains
+ * the list_link_t and the name of the member corresponding to the list_link_t,
+ * returns a pointer (of type "type*") to the item.
+ *
+ * Example:
+ * struct my_struct { list_link_t my_link };
+ * struct my_struct a;
+ * list_link_init(&a.my_link);
+ *
+ * struct my_struct *b = list_item(&a.my_link, struct my_struct, my_link);
+ * // b should equal &a here
+ *
+ * To iterate over a list,
+ * list_link_t *link;
+ * for (link = list->l_next;
+ * link != list; link = link->l_next)
+ * ...
+ *
+ * Or, use the macros, which will work even if you list_remove() the
+ * current link:
+ * list_iterate(list, iterator, type, member) {
+ * ... use iterator ...
+ * }
+ * (see also list_iterate_reverse for iterating in reverse)
+ *
+ * Where:
+ * - list is a pointer to the list_t to iterate over,
+ * - iterator is a name for the loop variable which will take on the value
+ * of each item in the list,
+ * - type is the type of items in the list,
+ * - member is the name of the field in the item type that is the list_link_t
+ *
+ * Example (from kernel/drivers/chardev.c)
+ * // chardevs is a list_t
+ * // chardev_t has a cd_link member which is a list_link_t
+ * list_iterate(&chardevs, cd, chardev_t, cd_link)
+ * {
+ * if (dev->cd_id == cd->cd_id)
+ * {
+ * return -1;
+ * }
+ * }
+ */
+
+/**
+ * Initialize a list_t.
+ */
+#define LIST_INITIALIZER(list) \
+ { \
+ .l_next = &(list), .l_prev = &(list) \
+ }
+
+/**
+ * Initialize a list link.
+ */
+#define LIST_LINK_INITIALIZER(list_link) \
+ { \
+ .l_next = NULL, .l_prev = NULL \
+ }
+
+typedef struct list
+{
+ struct list *l_next;
+ struct list *l_prev;
+} list_t, list_link_t;
+
+/**
+ * Initialize a list link.
+ */
+void list_link_init(list_link_t *link);
+
+/**
+ * Initialize a list_t.
+ */
+void list_init(list_t *list);
+
+/**
+ * Check if a link is linked to some list.
+ *
+ * @param link The link to check.
+ * @return long 1 if linked, 0 otherwise.
+ */
+long list_link_is_linked(const list_link_t *link);
+
+/**
+ * Check if a list is empty.
+ *
+ * @param list The list to check.
+ * @return long 1 if empty, 0 otherwise.
+ */
+long list_empty(const list_t *list);
+
+/**
+ * Assert that the internal state of a list is sane, and
+ * panic if it is not.
+ *
+ * @param list The list to check for sanity.
+ */
+void list_assert_sanity(const list_t *list);
+
+/**
+ * Insert a new link onto a list before another link.
+ *
+ * @param link The link before which the new link should be inserted.
+ * @param to_insert The new link to be inserted.
+ */
+void list_insert_before(list_link_t *link, list_link_t *to_insert);
+
+/**
+ * Insert a new link at the head (beginning) of a given list.
+ *
+ * @param list The list to insert on.
+ * @param link The new link to insert.
+ */
+void list_insert_head(list_t *list, list_link_t *link);
+
+/**
+ * Insert a new link at the tail (end) of a given list.
+ *
+ * @param list The list to insert on.
+ * @param link The new link to insert.
+ */
+void list_insert_tail(list_t *list, list_link_t *link);
+
+/**
+ * Remove a particular link from the list it's on.
+ *
+ * @param link The link to be removed from its list.
+ */
+void list_remove(list_link_t *link);
+
+/**
+ * Get a pointer to the item that contains the given link.
+ *
+ * For instance, given a list_link_t contained within a proc_t, get a reference
+ * to the proc_t itself.
+ *
+ * @param link The link contained within the item to access.
+ * @param type The type of the outer item struct (e.g., proc_t)
+ * @param member The name of the struct member which is the list_link_t (e.g. p_list_link)
+ *
+ */
+#define list_item(link, type, member) \
+ (type *)((char *)(link)-offsetof(type, member))
+
+/**
+ * Get the item at the head of the list. See list_item for explanation
+ * of type and member.
+ */
+#define list_head(list, type, member) list_item((list)->l_next, type, member)
+
+/**
+ * Get the item at the tail of the list. See list_item for explanation
+ * of type and member.
+ */
+#define list_tail(list, type, member) list_item((list)->l_prev, type, member)
+
+/**
+ * Get the next item in a list that occurs after the given item.
+ *
+ * @param current An item from the list (e.g. a proc_t)
+ * See list_item for explanation of type and member.
+ */
+#define list_next(current, type, member) \
+ list_head(&(current)->member, type, member)
+
+/**
+ * Get the previous item in a list given an item. See list_next for explanation.
+ */
+#define list_prev(current, type, member) \
+ list_tail(&(current)->member, type, member)
+
+/**
+ * Iterate over elements in in a list. See comment at top of list.h for
+ * detailed description.
+ */
+#define list_iterate(list, var, type, member) \
+ for (type *var = list_head(list, type, member), \
+ *__next_##var = list_next(var, type, member); \
+ &var->member != (list); \
+ var = __next_##var, __next_##var = list_next(var, type, member))
+
+/**
+ * Iterate over the elements of a list in reverse. See comment at top of list.h for
+ * detailed description.
+ */
+#define list_iterate_reverse(list, var, type, member) \
+ for (type *var = list_tail(list, type, member), \
+ *__next_##var = list_prev(var, type, member); \
+ &var->member != (list); \
+ var = __next_##var, __next_##var = list_prev(var, type, member))
diff --git a/kernel/include/util/printf.h b/kernel/include/util/printf.h
new file mode 100644
index 0000000..430b156
--- /dev/null
+++ b/kernel/include/util/printf.h
@@ -0,0 +1,87 @@
+/* -*- Mode:C; c-basic-offset:4; tab-width:4 -*-
+ ****************************************************************************
+ * (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
+ ****************************************************************************
+ *
+ * File: lib.h
+ * Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk)
+ * Changes:
+ *
+ * Date: Aug 2003
+ *
+ * Environment: Xen Minimal OS
+ * Description: Random useful library functions, contains some freebsd stuff
+ *
+ ****************************************************************************
+ * $Id: h-insert.h,v 1.4 2002/11/08 16:03:55 rn Exp $
+ ****************************************************************************
+ *
+ *-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)stdarg.h 8.1 (Berkeley) 6/10/93
+ * $FreeBSD: src/sys/i386/include/stdarg.h,v 1.10 1999/08/28 00:44:26 peter Exp
+ *$
+ */
+
+#pragma once
+
+#include "stdarg.h"
+#include <types.h>
+
+/* printing */
+int vsnprintf(char *buf, size_t size, const char *fmt, va_list args);
+
+int vscnprintf(char *buf, size_t size, const char *fmt, va_list args);
+
+int snprintf(char *buf, size_t size, const char *fmt, ...);
+
+int scnprintf(char *buf, size_t size, const char *fmt, ...);
+
+// a pretty simple way to avoid kernel buffer overflow attacks, no?
+// int vsprintf(char *buf, const char *fmt, va_list args);
+// int sprintf(char *buf, const char *fmt, ...);
+
+/* A variation on printf designed to be used in debug info functions.
+ * The function takes in a pointer to the address of a string buffer
+ * and a pointer to the size of the buffer. The buffer address pointed
+ * by str is incremented to point to the null character writen at the
+ * end of the new string. The size is decremented by the number of
+ * characters writen, not including the null character. The function
+ * returns the number of characters left in the buffer (after taking
+ * in to account the null character). */
+int iprintf(char **str, size_t *size, char *fmt, ...)
+ __attribute__((format(printf, 3, 4)));
+
+int vsscanf(const char *buf, const char *fmt, va_list args);
+
+int sscanf(const char *buf, const char *fmt, ...);
diff --git a/kernel/include/util/string.h b/kernel/include/util/string.h
new file mode 100644
index 0000000..04dc0f7
--- /dev/null
+++ b/kernel/include/util/string.h
@@ -0,0 +1,93 @@
+/* -*- Mode:C; c-basic-offset:4; tab-width:4 -*-
+ ****************************************************************************
+ * (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
+ ****************************************************************************
+ *
+ * File: lib.h
+ * Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk)
+ * Changes:
+ *
+ * Date: Aug 2003
+ *
+ * Environment: Xen Minimal OS
+ * Description: Random useful library functions, contains some freebsd stuff
+ *
+ ****************************************************************************
+ * $Id: h-insert.h,v 1.4 2002/11/08 16:03:55 rn Exp $
+ ****************************************************************************
+ *
+ *-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)stdarg.h 8.1 (Berkeley) 6/10/93
+ * $FreeBSD: src/sys/i386/include/stdarg.h,v 1.10 1999/08/28 00:44:26 peter Exp
+ *$
+ */
+
+#pragma once
+
+#include "stdarg.h"
+#include "types.h"
+
+/* string and memory manipulation */
+int memcmp(const void *cs, const void *ct, size_t count);
+
+void *memcpy(void *dest, const void *src, size_t count);
+
+int strncmp(const char *cs, const char *ct, size_t count);
+
+int strcmp(const char *cs, const char *ct);
+
+char *strcpy(char *dest, const char *src);
+
+char *strncpy(char *dest, const char *src, size_t count);
+
+void *memset(void *s, int c, size_t count);
+
+size_t strnlen(const char *s, size_t count);
+
+size_t strlen(const char *s);
+
+char *strchr(const char *s, int c);
+
+char *strrchr(const char *s, int c);
+
+char *strstr(const char *s1, const char *s2);
+
+char *strcat(char *dest, const char *src);
+
+char *strdup(const char *s);
+
+char *strtok(char *s, const char *d);
+
+/* return string-representation of an errno */
+char *strerror(int errnum);
diff --git a/kernel/include/util/time.h b/kernel/include/util/time.h
new file mode 100644
index 0000000..fe3df18
--- /dev/null
+++ b/kernel/include/util/time.h
@@ -0,0 +1,25 @@
+#pragma once
+
+#include "types.h"
+#include "util/debug.h"
+
+extern uint64_t timer_tickcount;
+extern uint64_t kernel_preempted_count;
+extern uint64_t user_preempted_count;
+extern uint64_t not_preempted_count;
+extern uint64_t idle_count;
+extern volatile uint64_t jiffies;
+
+void time_init();
+
+void time_spin(time_t ms);
+
+void time_sleep(time_t ms);
+
+long do_usleep(useconds_t usec);
+
+time_t core_uptime();
+
+time_t do_time();
+
+size_t time_stats(char *buf, size_t len);
diff --git a/kernel/include/util/timer.h b/kernel/include/util/timer.h
new file mode 100644
index 0000000..57889f9
--- /dev/null
+++ b/kernel/include/util/timer.h
@@ -0,0 +1,28 @@
+#ifndef TIMER_H
+#define TIMER_H
+
+#include "util/list.h"
+
+typedef struct timer
+{
+ void (*function)(uint64_t data);
+ uint64_t data;
+ uint64_t expires;
+ list_link_t link;
+} timer_t;
+
+void timer_init(timer_t *timer);
+
+void timer_add(timer_t *timer);
+
+int timer_del(timer_t *timer);
+
+int timer_mod(timer_t *timer, int expires);
+
+int timer_pending(timer_t *timer);
+
+int timer_del_sync(timer_t *timer);
+
+void __timers_fire();
+
+#endif \ No newline at end of file
diff --git a/kernel/include/vm/anon.h b/kernel/include/vm/anon.h
new file mode 100644
index 0000000..a116853
--- /dev/null
+++ b/kernel/include/vm/anon.h
@@ -0,0 +1,9 @@
+#pragma once
+
+struct mobj;
+
+void anon_init();
+
+struct mobj *anon_create(void);
+
+extern int anon_count;
diff --git a/kernel/include/vm/brk.h b/kernel/include/vm/brk.h
new file mode 100644
index 0000000..1612b5f
--- /dev/null
+++ b/kernel/include/vm/brk.h
@@ -0,0 +1,3 @@
+#pragma once
+
+long do_brk(void *addr, void **ret);
diff --git a/kernel/include/vm/mmap.h b/kernel/include/vm/mmap.h
new file mode 100644
index 0000000..8c5638c
--- /dev/null
+++ b/kernel/include/vm/mmap.h
@@ -0,0 +1,8 @@
+#include "types.h"
+
+struct proc;
+
+long do_munmap(void *addr, size_t len);
+
+long do_mmap(void *addr, size_t len, int prot, int flags, int fd, off_t off,
+ void **ret);
diff --git a/kernel/include/vm/pagefault.h b/kernel/include/vm/pagefault.h
new file mode 100644
index 0000000..7850727
--- /dev/null
+++ b/kernel/include/vm/pagefault.h
@@ -0,0 +1,11 @@
+#pragma once
+
+#include "types.h"
+
+#define FAULT_PRESENT 0x01
+#define FAULT_WRITE 0x02
+#define FAULT_USER 0x04
+#define FAULT_RESERVED 0x08
+#define FAULT_EXEC 0x10
+
+void handle_pagefault(uintptr_t vaddr, uintptr_t cause);
diff --git a/kernel/include/vm/shadow.h b/kernel/include/vm/shadow.h
new file mode 100644
index 0000000..57893d5
--- /dev/null
+++ b/kernel/include/vm/shadow.h
@@ -0,0 +1,11 @@
+#pragma once
+
+#include "mm/mobj.h"
+
+void shadow_init();
+
+mobj_t *shadow_create(mobj_t *shadowed);
+
+void shadow_collapse(mobj_t *o);
+
+extern int shadow_count;
diff --git a/kernel/include/vm/vmmap.h b/kernel/include/vm/vmmap.h
new file mode 100644
index 0000000..e5efba6
--- /dev/null
+++ b/kernel/include/vm/vmmap.h
@@ -0,0 +1,71 @@
+#pragma once
+
+#include "types.h"
+
+#include "util/list.h"
+
+#define VMMAP_DIR_LOHI 1
+#define VMMAP_DIR_HILO 2
+
+struct mobj;
+struct proc;
+struct vnode;
+
+typedef struct vmmap
+{
+ list_t vmm_list; /* list of virtual memory areas */
+ struct proc *vmm_proc; /* the process that corresponds to this vmmap */
+} vmmap_t;
+
+/* Make sure you understand why mapping boundaries are in terms of frame
+ * numbers (page numbers) and not addresses */
+typedef struct vmarea
+{
+ size_t vma_start; /* [starting vfn, */
+ size_t vma_end; /* ending vfn) */
+ size_t vma_off; /* offset from beginning of vma_obj in pages */
+ /* the reason this field is necessary is that
+ when files are mmap'ed, it doesn't have
+ to start from location 0. You could, for instance,
+ map pages 10-15 of a file, and vma_off would be 10. */
+
+ int vma_prot; /* permissions (protections) on mapping, see mman.h */
+ int vma_flags; /* either MAP_SHARED or MAP_PRIVATE. It can also specify
+ MAP_ANON and MAP_FIXED */
+
+ struct vmmap *vma_vmmap; /* address space that this area belongs to */
+ struct mobj *vma_obj; /* the memory object that corresponds to this address region */
+ list_link_t vma_plink; /* link on process vmmap maps list */
+} vmarea_t;
+
+void vmmap_init(void);
+
+vmmap_t *vmmap_create(void);
+
+void vmmap_destroy(vmmap_t **mapp);
+
+void vmmap_collapse(vmmap_t *map);
+
+vmarea_t *vmmap_lookup(vmmap_t *map, size_t vfn);
+
+long vmmap_map(vmmap_t *map, struct vnode *file, size_t lopage, size_t npages,
+ int prot, int flags, off_t off, int dir, vmarea_t **new_vma);
+
+long vmmap_remove(vmmap_t *map, size_t lopage, size_t npages);
+
+long vmmap_is_range_empty(vmmap_t *map, size_t startvfn, size_t npages);
+
+ssize_t vmmap_find_range(vmmap_t *map, size_t npages, int dir);
+
+long vmmap_read(vmmap_t *map, const void *vaddr, void *buf, size_t count);
+
+long vmmap_write(vmmap_t *map, void *vaddr, const void *buf, size_t count);
+
+vmmap_t *vmmap_clone(vmmap_t *map);
+
+size_t vmmap_mapping_info_helper(const void *map, char *buf, size_t size,
+ char *prompt);
+
+size_t vmmap_mapping_info(const void *map, char *buf, size_t size);
+
+void vmmap_insert(vmmap_t *map, vmarea_t *new_vma); \ No newline at end of file