diff options
Diffstat (limited to 'kernel/include')
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 |