Full Code of sos-os/kernel for AI

master 641b83fb0785 cached
125 files
487.0 KB
131.1k tokens
942 symbols
1 requests
Download .txt
Showing preview only (520K chars total). Download the full file or copy to clipboard to get everything.
Repository: sos-os/kernel
Branch: master
Commit: 641b83fb0785
Files: 125
Total size: 487.0 KB

Directory structure:
gitextract_7fg8ki17/

├── .editorconfig
├── .gitignore
├── .gitmodules
├── .travis.yml
├── BUILDING.md
├── Brewfile
├── CHANGES.md
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── Cargo.toml
├── LICENSE-APACHE
├── LICENSE-MIT
├── Makefile
├── Notes.md
├── README.md
├── Vagrantfile
├── Xargo.toml
├── boot/
│   ├── Cargo.toml
│   ├── README.md
│   └── src/
│       └── lib.rs
├── build.rs
├── cpu/
│   ├── Cargo.toml
│   └── src/
│       ├── armv7/
│       │   └── mod.rs
│       ├── lib.rs
│       ├── x86/
│       │   ├── cpu.rs
│       │   └── mod.rs
│       ├── x86_64/
│       │   ├── context.rs
│       │   ├── mod.rs
│       │   ├── msr.rs
│       │   └── task.rs
│       └── x86_all/
│           ├── control_regs/
│           │   ├── cr0.rs
│           │   ├── cr4.rs
│           │   └── mod.rs
│           ├── dtable.rs
│           ├── flags.rs
│           ├── interrupts/
│           │   ├── idt/
│           │   │   ├── gate32.rs
│           │   │   ├── gate64.rs
│           │   │   ├── mod.rs
│           │   │   └── tests.rs
│           │   ├── mod.rs
│           │   └── pics.rs
│           ├── mod.rs
│           ├── segment.rs
│           └── timer.rs
├── elf/
│   ├── Cargo.toml
│   ├── README.md
│   └── src/
│       ├── file.rs
│       ├── lib.rs
│       ├── program.rs
│       └── section.rs
├── memory/
│   ├── Cargo.toml
│   └── src/
│       ├── arch/
│       │   ├── mod.rs
│       │   ├── x86/
│       │   │   └── mod.rs
│       │   └── x86_64/
│       │       └── mod.rs
│       ├── lib.rs
│       └── macros.rs
├── paging/
│   ├── Cargo.toml
│   └── src/
│       ├── arch/
│       │   ├── mod.rs
│       │   └── x86_64/
│       │       ├── cr3.rs
│       │       ├── mod.rs
│       │       ├── table.rs
│       │       ├── temp.rs
│       │       └── tlb.rs
│       ├── lib.rs
│       └── stack.rs
├── params/
│   ├── Cargo.toml
│   └── src/
│       ├── lib.rs
│       └── mem.rs
├── rustfmt.toml
├── scripts/
│   ├── README.md
│   ├── install-env-linux.sh
│   ├── install-env-mac.sh
│   └── install-env.sh
├── sos_alloc/
│   ├── Cargo.toml
│   └── src/
│       ├── borrow.rs
│       ├── buddy/
│       │   ├── math.rs
│       │   ├── mod.rs
│       │   ├── system.rs
│       │   └── test.rs
│       ├── bump_ptr.rs
│       ├── first_fit.rs
│       ├── frame/
│       │   ├── mem_map.rs
│       │   └── mod.rs
│       ├── free.rs
│       ├── lib.rs
│       ├── place.rs
│       └── system.rs
├── sos_intrusive/
│   ├── Cargo.toml
│   └── src/
│       ├── lib.rs
│       ├── list/
│       │   ├── mod.rs
│       │   └── test.rs
│       ├── rawlink.rs
│       └── stack/
│           ├── mod.rs
│           └── test.rs
├── src/
│   ├── arch/
│   │   ├── README.md
│   │   ├── mod.rs
│   │   ├── x86_64/
│   │   │   ├── boot.asm
│   │   │   ├── drivers/
│   │   │   │   ├── mod.rs
│   │   │   │   ├── serial.rs
│   │   │   │   └── vga.rs
│   │   │   ├── grub.cfg
│   │   │   ├── interrupts.rs
│   │   │   ├── linker.ld
│   │   │   └── mod.rs
│   │   └── x86_all/
│   │       ├── bda.rs
│   │       └── multiboot2.rs
│   ├── heap.rs
│   ├── io/
│   │   ├── keyboard.rs
│   │   ├── mod.rs
│   │   └── term.rs
│   ├── logger.rs
│   └── main.rs
├── targets/
│   ├── x86_32-sos-bootstrap-gnu.json
│   └── x86_64-sos-kernel-gnu.json
├── tokamak.toml
├── util/
│   ├── Cargo.toml
│   └── src/
│       ├── io.rs
│       ├── lib.rs
│       └── macros/
│           ├── mod.rs
│           └── newtype_impl.rs
└── vga/
    ├── Cargo.toml
    └── src/
        ├── kinfo.rs
        ├── lib.rs
        ├── panic.rs
        └── status.rs

================================================
FILE CONTENTS
================================================

================================================
FILE: .editorconfig
================================================
# EditorConfig helps developers define and maintain consistent
# coding styles between different editors and IDEs
# editorconfig.org
root = true

### Makefiles #######################################################
[Makefile]
indent_style = tab # Makefiles must be indented with tabs.

### Rust source code files ##########################################
# Based on @xtian's .editorconfig file at
# https://gist.github.com/xtian/339112af8a11d0583d81
# and on the Rust style guidelines at
# https://github.com/rust-lang/rust/tree/master/src/doc/style/style/
[*.rs]
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
indent_style = space
indent_size = 4

### Assembly language files #########################################
[*.asm]
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
indent_style = space
indent_size = 4


================================================
FILE: .gitignore
================================================

# Created by https://www.gitignore.io/api/assembler,rust,emacs,osx,sublimetext,tags,vagrant,vim,linux

### Kernel binaries ###
*.iso
*.bin
*.elf

# serial output
serial-*.log

### Assembler ###
*.[sS]
*.bc


### Rust ###
# Compiled files
*.o
*.so
*.rlib
*.dll

# Executables
*.exe

# Generated by Cargo
/target/
**/target/

# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock
Cargo.lock


### Emacs ###
# -*- mode: gitignore; -*-
*~
\#*\#
/.emacs.desktop
/.emacs.desktop.lock
*.elc
auto-save-list
tramp
.\#*

# Org-mode
.org-id-locations
*_archive

# flymake-mode
*_flymake.*

# eshell files
/eshell/history
/eshell/lastdir

# elpa packages
/elpa/

# reftex files
*.rel

# AUCTeX auto folder
/auto/

# cask packages
.cask/

# Flycheck
flycheck_*.el

# server auth directory
/server/


### OSX ###
.DS_Store
.AppleDouble
.LSOverride

# Icon must end with two \r
Icon


# Thumbnails
._*

# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns

# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk


### SublimeText ###
# cache files for sublime text
*.tmlanguage.cache
*.tmPreferences.cache
*.stTheme.cache

# workspace files are user-specific
*.sublime-workspace

# project files should be checked into the repository, unless a significant
# proportion of contributors will probably not be using SublimeText
# *.sublime-project

# sftp configuration file
sftp-config.json


### Tags ###
# Ignore tags created by etags, ctags, gtags (GNU global) and cscope
TAGS
.TAGS
!TAGS/
tags
.tags
!tags/
gtags.files
GTAGS
GRTAGS
GPATH
cscope.files
cscope.out
cscope.in.out
cscope.po.out



### Vagrant ###
.vagrant/


### Vim ###
# swap
[._]*.s[a-w][a-z]
[._]s[a-w][a-z]
# session
Session.vim
# temporary
.netrwhist
*~
# auto-generated tag files
tags
.tags1

### GDB ###
.gdb_history

### Linux ###
*~

# temporary files which can be created if a process still has a handle open of a deleted file
.fuse_hidden*

# KDE directory preferences
.directory

# Linux trash folder which might appear on any partition or disk
.Trash-*
.idea/markdown-navigator.xml
.idea/markdown-navigator/profiles_settings.xml
.idea/modules.xml
.idea/misc.xml
.idea/sos-kernel.iml
.idea/vcs.xml
.idea/workspace.xml
.vscode/tasks.json


================================================
FILE: .gitmodules
================================================


================================================
FILE: .travis.yml
================================================
language: rust
rust: nightly

# matrix:
#   allow_failures:
#     - os: osx
#   fast_finish: true

cache:
  cargo: true
  directories:
    - /usr/local/bin/x86_64-pc-elf-*
    - /usr/local/bin/grub*

notifications:
  webhooks:
    urls:
    - https://webhooks.gitter.im/e/59a4cbad9f4177de9a91
    on_success: change
    on_failure: always
    on_start: never
  email:
    on_success: never
    on_failure: change
  slack:
    secure: CTfCGsKzNyb7SqEGeXYCnwE0jZLcANMjgdZpnpDMHtyBzOb0EJ1VXe5FpCVZ74jPD0De/eWwxT3aVnxZGnIn24gIB4K+3km4s+mSiecfhtP6lhHKaxy25NNKqcVJMt+52GgBYRvF9lPDdQR/I+YPznKeKkGCI8KMK8Y61RTMF1gWHezqsDirVemS+qp4YP8MrtcUk8W0yw+K522MuCLBFBy/LX1LrkZjkM1yyDIWmS7UerU1A0mWmDgiwfO33jJPtJKj64HrVwbOjl9ZH9SkEMeHumBsocxZ+3EPx8qygzJfEAMbWV6nu816e5Jg58UBsKrm5rPKdHmSshrvme7L79mGgfaROKF94OzIL67HFs+3vFXG5GspQz6myA+HtQMCO03dS7VydB6//Tpr9okWHsCBGgRgDnuvXWk/HG2kSP1uSDhrxqmBya/kTSaOa+QRqUnF6XxknxX5DCbGKIVY9fN5+IxDBVnigVYAlHe+NreT3xNeLd7E3p1TL865SYpU4szJ1KLtq+JX+DAAYF94UoIt4fD/kQ0tYhwKSJtUNfFRs5MubqewNpkw/Pt2d9gPIw9+hP7c6w/4gd3lDuVfMwhZwsXfRX9OvEemFET4dK+VHy5DqH00DJ/3tQaJ2dDeIHUtFMq1V93aVjspMDj+dwVctQ5DhIXHaYKmrc4yQkA=

addons:
  apt:
    packages:
    - nasm
    - build-essential
    - xorriso
    # - libssh2-1

before_install: |
  objcopy=$(which objcopy) &&
  strip=$(which strip) &&
  mkdir -p $HOME/bin &&
  ln -s $objcopy $HOME/bin/x86_64-elf-objcopy &&
  ln -s $strip $HOME/bin/x86_64-elf-strip

install:
  ### install the "rust-src" rustup component ###############################
  # xargo uses this for building sysroots
  # before installing rust-src we need to get `rustup`
  - curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain nightly
  - source ~/.cargo/env
  # add the rust-src component
  - rustup component add rust-src
  ### install `xargo` ######################################################
  - cargo install xargo --force
  - export PATH="$PATH:$(rustc --print sysroot)/cargo/bin:$HOME/.cargo/bin"

script: make test

jobs:
  include:
    - stage: build
      script: make kernel
      deploy:
        provider: releases
        api_key:
          secure: DQ6EChkuPdDbCkPQIOVmq7SBxTG04GeoUXeguCb3RcX+lT5FqTG/2bAnElAxE+KHkLpxBav+CIaHyPQzT93LN70PSV0Vny8Oo3OCOprSn3gph12ZXPeebFk+EFArju3N/Du/cxlNK6zQ71Sw1Jr+nmutjpCGkN2ki04A6iY5f0cLmgsUXZxVBzMY4mb2tihAvH+0HgR96mmQ6xEvWU3mXnHvgpJhSwSHJlZao7C51vq0sr5bKPNVVHfwN7OlqG3uJYWcnFIlrkGbZyVtNZ//CjtGPhKufn+l1JOdQo47/Lh+iHPUNrWGsvNiy7yXrBdsVKI0oJwfssHrMPrXyWphk9wrD8ID1wpKXPxDikVB3uSU1OfQbSSsH+aF7i3mNwJSG4ORTjZeuBQpC4F9ZUAr2uS6RR+bW9tnb6/ZRQA0vqQVS1oi5miIHLe9FbMccOZLWYyHM6Lts3cd4zEldZTvPUmO7M5oP4Woo0DPRWvq48f7QW9x0ewjVRjfUkPZ8+H5BfFfqXQXZYtDRfTruVaYtS/We3QggvLaNZJOmq+jJQqrSARK5tB/HD8YZvu9Z1XU8UTcm6ORvlEsAMIk7+orUU1L4ibO/Tr1wEU9fgS2k9rCDPhfMljgn2EqBRfULnwqbzSwPrZmKyJlVZ6GsJtCAC1XQQCbZIMVShVbvL6JEKU=
        file: build/os-x86_64.iso
        skip_cleanup: true
        on:
          tags: true
          repo: hawkw/sos-kernel
    - stage: docs
      install: skip
      script: cargo doc
      deploy:
        provider:  pages
        skip_cleanup: true
        github_token: $GH_TOKEN # Set in travis-ci.org dashboard
        target_branch: gh-pages
        local_dir: target/doc
        on:
          branch: master
          repo: hawkw/sos-kernel

env:
  global:
    # override the default `--features unstable` used for the nightly branch (optional)
    - TRAVIS_CARGO_NIGHTLY_FEATURE=""
    - PATH="$PATH:$HOME/bin"
    - secure: Vv4bFCkxM3o7FpKjcxTzQRWdkp5aSfrkmFcxSRLYFhm8tyeh+TRiC2+ucNfscFeOzPTC/hTwatbbpdTIaAZKpyrD/gB4hNiGFdKV1x1pw23KQkiPmQdFKxAHtIS20jeIa44q6kPltTQtZXXuM8s0xc6r+C14Q6igd4HkD0nLhAlKIQpcS/srXoeMheL3vNIroasHUwFgpv1LLJnMqYhCHzNk2Y6CaxYygg5Cy2gS9G1nfxdNVfF4iaUXYZKgU0s3C1GL0ApTtUxW0uT/NS0UBZwttsq9NvwmZSZQIXpfTnn0wHd4cl8MhokUQNEumFouU5rlEIcFS9ulohxaHnn50cqfos+seblKs2E+MJoX8rBO5Kz3dNE3+otZw9CpImskO4EKA2MYwtTC3Ds4uVoleS9PskCMz32jKXqp6WqZkJgpimHrdv0jNBy2ucTMdw91XjRXLA557GPRa/28TPpKkMYrSB02c2IadftexWKDP5Q9uMsfTEgIpXzx/XRQvPoxtJo+rOn9hTbyHWexKEMAuic12FBoYFOMSbRKtpT8kjtd8WeBzc1RmXZYpg5td5EN3v/2fmvM6F6Sz/db4HgNZIccC/j/fWvXN7njRl8bgMC002/tkQs0Ugl1aE5onaK9DTMHquqCLnd9CADwXdQf1YsfxryjhhBfd1WIfuqe1Ww=


================================================
FILE: BUILDING.md
================================================
setting up a build environment
============================

Unfortunately, one of the unescapable truths of OS development is that building a kernel is a pain. Even though Rust's toolchain makes building SOS much _less_ of a pain than if the kernel were written in C, setting up a build environment to build SOS is still a fairly complex process.

In order to make this a bit easier, I've written some shell scripts to help install and configure SOS's build dependencies. You can run these scripts with the following `make` target:
```
$ make env
```
Once you've run `make env`, you should have a correctly configured build environment, and you should be ready to build SOS.

If you'd rather install and configure everything yourself, or your system isn't supported by the automatic install scripts,  you can follow these instructions to set up a suitable environment for building SOS:

installing Rust
---------------

In order to build SOS, you need an up-to-date version of the Rust compiler. SOS uses several gated features that can only be built on the nightly Rust release channel.

The suggested way to install Rust is using [Rustup](https://www.rustup.rs), a tool for managing multiple versions of Rust. If you don't have Rustup installed, you can install it by running this command in your terminal:
```
$ curl https://sh.rustup.rs -sSf | sh
```

Once Rustup is installed, run
```
$ rustup update nightly
```

to ensure the nightly release branch is up to date.

If you've set the stable or beta Rust release channels as the global default, you should run
```
$ rustup override nightly
```
in the SOS root directory, to set the nightly release channel as the default for SOS.

installing build dependencies
-----------------------------

Once you have Rust installed, you will need the following additional dependencies:
+ `ld`
+ `grub-mkrescue` & `xorriso`
+ `qemu` for running the kernel under emulation
+ `mtools`

Depending on your OS, you'll want to install these dependencies somewhat differently.

### linux

On Debian you can install them with

```
$ sudo apt-get install xorriso qemu mtools build-essential
```
On Arch Linux you can install them with
```
$ sudo pacman -S --needed binutils grub libisoburn qemu mtools
```
And on Fedora with
```
$ sudo dnf instal xorriso qemu
```
On Gentoo it's
```
$ sudo emerge app-emulation/qemu dev-libs/libisoburn sys-boot/grub
```

You will also need `x86_64-elf-objcopy` and `x86_64-elf-strip` executables.
On x86_64 Linux you can simply symlink them to your regular `objcopy` and `strip`.

If you are using Gentoo but on another architecture you can build a cross-compiled version of `binutils` (which contains `objcopy` and `strip`) with
```
$ sudo emerge sys-devel/crossdev
$ sudo crossdev -s0 --target x86_64-elf
```

### macOS

Installing dev dependencies on macOS is slightly trickier, as you will also need a cross-compiled version of GNU `binutils` to build SOS. Cross-compiling `binutils` will require some additional dependencies.

You can install a majority of dependencies using the [Homebrew](https://github.com/Homebrew/brew) package manager. I've included a `Brewfile` for automatically installing these dependencies. To use the `Brewfile`, run the following sequence of commands:

```
$ brew update
$ brew tap Homebrew/bundle
$ brew bundle
```

Once you've installed the `Brewfile`, you'll need to cross-compile `binutils`.

I've included a script to automatically download and cross-compile `binutils`, which you can run by typing:
```
$ ./scripts/install-mac.sh
```

Alternatively, if you want to do it manually, Phil Oppermann has a tutorial [here](http://os.phil-opp.com/cross-compile-binutils.html).

### windows
Seriously?
Windows isn't supported; I can't possibly advise it.

installing `xargo`
-----------------

Once you've installed Rust and the dev dependencies, you'll need to install [`xargo`](https://github.com/japaric/xargo), a tool for cross-compiling Rust programs. You can install `xargo` quite easily by running
```
$ cargo install xargo
```


================================================
FILE: Brewfile
================================================
# for making a bootable ISO
brew 'xorriso'

# for running the OS
brew 'qemu'

# x86_64-pc-elf cross-compile toolchain
tap 'hawkw/x86_64-pc-elf'
brew 'x86_64-pc-elf-gcc'

# GRUB
tap 'hawkw/grub'
brew 'grub', args: ['with-x86_64-pc-elf', 'HEAD']


================================================
FILE: CHANGES.md
================================================
<a name="elf-v0-0-2"></a>
## elf v0.0.2 (2017-03-15)


#### Bug Fixes

* **elf:**
  *  add assertion that extract_from_slice offset is T-aligned ([e7df6620](e7df6620))
  *  fix arbitrary lifetime in elf::extract_from_slice ([60ed6a15](60ed6a15))
  *  fix a typo in elf::file::Class ([99332049](99332049))
  *  fix validation of elf section word size ([15eb3664](15eb3664))
  *  make section header name offset a Word ([1583b718](1583b718))
  *  fix a typo in elf::file::Class ([cbb9ca9d](cbb9ca9d))
  *  fix validation of elf section word size ([cec0a13b](cec0a13b))
  *  make section header name offset a Word ([89c4edd3](89c4edd3))
* **x86_64:**  make kernel_init use re-written section headers ([19f75fe9](19f75fe9))

#### Features

* **elf:**
  *  rewrite SectionHeader to be trait-based ([9d2eb03c](9d2eb03c), closes [#93](93))
  *  add default type parameters for Image, default word type ([4c09e7ad](4c09e7ad))
  *  changed extract_from_slice() to return a Result ([5e359b01](5e359b01))
  *  start on convert::TryFrom<&'a [u8]> for elf image ([34fba817](34fba817))
  *  add program headers slice ref to elf image ([caaf3245](caaf3245))
  *  add struct representing 32-bit program header ([cc3f38af](cc3f38af))
  *  add struct representation of 64-bit program header ([ee718532](ee718532))
  *  begin implementing elf program header ([00d49e41](00d49e41))
  *  add getters for more file header fields ([888d99fa](888d99fa))
  *  add getters for returning file header fields as usize ([e2cf28dc](e2cf28dc))
  *  add function to get the section header string table ([48036533](48036533))
  *  ELF String Table made indexable ([c03e36f0](c03e36f0))
  *  first pass on parsing ELF string tables ([5c266f0f](5c266f0f), closes [#83](83))
  *  nicer handling of ELF sections with invalid type fields ([9083e9ba](9083e9ba))
  *  add fmt::Display implementation for ELF sections ([4eb34a3a](4eb34a3a))
  *  add getters for more file header fields ([ae29fe71](ae29fe71))
  *  add getters for returning file header fields as usize ([3b6078fd](3b6078fd))
  *  add function to get the section header string table ([a8002040](a8002040))
  *  ELF String Table made indexable ([966d683b](966d683b))
  *  first pass on parsing ELF string tables ([9e5b195d](9e5b195d), closes [#83](83))
  *  nicer handling of ELF sections with invalid type fields ([8c07e373](8c07e373))
  *  add fmt::Display implementation for ELF sections ([50c04cea](50c04cea))
* **multiboot2:**  add IntoIter implementations for tags ([4a546e7a](4a546e7a))
* **x86_all:**
  *  multiboot2 mem areas iterator doesn't skip ACPI areas ([3310f1fc](3310f1fc))
  *  multiboot2 mem areas iterator doesn't skip ACPI areas ([2487f494](2487f494))


================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Contributor Covenant Code of Conduct

## Our Pledge

In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, gender identity and expression, level of experience,
nationality, personal appearance, race, religion, or sexual identity and
orientation.

## Our Standards

Examples of behavior that contributes to creating a positive environment
include:

* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members

Examples of unacceptable behavior by participants include:

* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
  address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
  professional setting

## Our Responsibilities

Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.

Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.

## Scope

This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.

## Enforcement

Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at [eliza@elizas.website]. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.

Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.

## Attribution

This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at [http://contributor-covenant.org/version/1/4][version]

[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/


================================================
FILE: CONTRIBUTING.md
================================================
Contributing to SOS
===================

**Looking for a first issue?** You might want to start out by looking at [issues tagged "easy"](https://github.com/hawkw/sos-kernel/issues?q=is%3Aissue+is%3Aopen+label%3Aeasy). These are issues that, while important, will probably require less knowledge of Rust, systems programming in general, or SOS, and might make good jumping-off points for potential contibutors.

### Table of Contents

+ [What do I need to know before contributing?](#what-do-i-need-to-know-before-contributing)
    - [Code of Conduct](#code-of-conduct)
    - [Licensing](#licensing)
    - [Setting Up a Dev Environment](#setting-up-a-dev-environment)
+ [Project Goals & Objectives](#project-goals--objectives)
+ [Conventions & Style Guides](#conventions--style-guides)
    - [Git Conventions](#git-conventions)
        * [Pull Requests](#pull-requests)
        * [Commit Messages](#commit-messages)
    - [Coding Style](#coding-style)
        * [Tools to assist with coding style](#tools-to-assist-with-coding-style)

What do I need to know before contributing?
===========================================

### Code of Conduct

This project adheres to the Contributor Covenant [code of conduct](CODE_OF_CONDUCT.md).
By participating, you are expected to uphold this code.
Please report unacceptable behavior to [eliza@elizas.website](mailto:eliza@elizas.website).

### Licensing

SOS is dual-licensed under the [MIT](LICENSE-MIT) and [Apache 2](LICENSE-APACHE) open-source licenses. By contributing code to SOS, you agree to waive all copyright claims on your contribution and allow it to be distributed under these licenses.

### Setting Up a Dev Environment

Building an OS is often a fairly difficult process, and can require a number of specific tools, libraries, and other dependencies installed and configured on the host system. In order to make contributing to SOS as easy as possible, we've tried to streamline the development environment setup process as much as possible, but there are still a few steps required before you can build SOS. Please see [BUILDING.md](BUILDING.md) for detailed instructions on how to build SOS.

In addition, the [tools to assist with coding style](#tools-to-assist-with-coding-style) section in this document provides information on optional tools that can be used to ensure your contributions conform to SOS' preferred coding style.

Project Goals & Objectives
==========================

+ Minimise assembly language code
    + Ideally, files ending in `.asm` should be used ONLY for the boot sequence
    + When platform-specific assembly code is required after the boot sequence, it should be placed in [inline assembly](https://doc.rust-lang.org/book/inline-assembly.html) in Rust functions, not in `.asm` files.
    + This has the following advantages:
        + It requires less linker configuration and makes building SOS much less of a pain.
        + It makes it much easier for Rust code to call code written in assembly language without mucking around with FFI.
        + It encourages us to write as much code as possible in a safe, high-level language, and write assembly only when it is strictly required.
+ Eventually, be able to boot on x86, x86_64, and ARMv7 machines.
+ Move as much out of kernel space as seems reasonable.


Conventions & Style Guides
==========================

Git Conventions
---------------

### Pull requests

In order to be accepted and merged, a pull request must meet the following conditions.

##### Pull requests MUST

+ Build successfully on [Travis](https://travis-ci.org/hawkw/sos-kernel)
+ Include RustDoc comments for any public-facing API functions or types
+ Include tests for any added features
+ Reference any closed issues with the text "Closes #XX" or "Fixes #XX" in the pull request description

##### Pull requests MUST NOT

+ Include any failing tests
+ Decrease overall project test coverage
+ Have any outstanding changes requested by a reviewer.

### Commit messages

Commit messages should follow the [Angular.js Commit Message Conventions](https://github.com/conventional-changelog/conventional-changelog/blob/a5505865ff3dd710cf757f50530e73ef0ca641da/conventions/angular.md). We use [`clog`](https://github.com/clog-tool/clog-cli) for automatically generating changelogs, and commit messages must be in a format that `clog` can parse.

It is recommended that contributors read the linked documentation for the Angular commit message convention in full –– it's not that long. For the impatient, here are some of the most important guidelines:

##### Commit messages MUST

+ Be in present tense
+ Follow the form `<type>(<scope>): <subject>`
    + where `<type>` is one of:
        * **feat**: A new feature
        * **fix**: A bug fix
        * **docs**: Documentation only changes
        * **style**: Changes that do not affect the meaning of the code (white-space, formatting, missing
        semi-colons, etc)
        * **refactor**: A code change that neither fixes a bug or adds a feature
        * **perf**: A code change that improves performance
        * **test**: Adding missing tests
        * **chore**: Changes to the build process or auxiliary tools and libraries such as documentation
        generation
    + and `<scope>` (optionally) specifies the specific element or component of the project that was changed.

##### Commit messages MUST NOT

+ Include lines exceeding 100 characters

##### Commit messages MAY

+ Include the text `[skip ci]` if changing non-Rustdoc documentation.
    + This will cause Travis CI to skip building that commit.
    + Commits which change RustDoc documentation in `.rs` source code files should still be built on CI -- `[skip ci]` should only be used for commits which change external documentation files such as `README.md`
    + Commits which change configuration files for tools not used by Travis may also skip the CI build, at the discretion of the committer.


Code Style
----------

Rust code should:
+ Follow the [Rust style guidelines](https://github.com/rust-lang/rust/tree/master/src/doc/style/style) and the guidelines in the ["Effective Rust" section](https://doc.rust-lang.org/book/effective-rust.html) of the Rust Book,  except when contradicted by this document.
    + In particular, it should...
        + ...be indented with 4 spaces
        + ...not end files with trailing whitespace
        + ...follow the [Rust naming conventions](https://github.com/rust-lang/rust/tree/master/src/doc/style/style/)
    + An `.editorconfig` file is available for [compatible text editors](http://editorconfig.org/#download).
+ Use [comma-first style](https://gist.github.com/isaacs/357981) for all comma-delimited constructs.
+ Not exceed 80 characters per line.

The following deviations from the style guide are permitted:
+ [Comma-first style](https://gist.github.com/isaacs/357981) _may_ be used for all comma-delimited constructs. For example:

    ```rust
    let a_list = [ a
                 , b
                 , c
                 ];
    ```

    and

    ```rust
    let a_list = [ a, b, c, d
                 , e, f, g, h
                 ];
    ```
    are considered good style.

+ When wrapping `where` clauses, place them at the same indentation level as the corresponding `fn` or `impl` statement. For example:
    ```rust
    // Considered good style
    fn foo<A>(a: A) where A: Something {
        ...
    }
    ```
    and
    ```rust
    // Considered good style
    fn bar<A, B>(a: A) -> B
    where A: Something
        , B: Something + SomethingElse {
        ...
    }
    ```
    are considered good style, while
    ```rust
    // NOT considered good style
    fn baz<A, B>(a: A) -> B
        where A: Something
            , B: SomethingElse {
                ...
            }
    ```
    is not.


### Tools to Assist With Coding Style

#### EditorConfig

An [`.editorconfig` file](.editorconfig) is available for [compatible text editors](http://editorconfig.org/#download). If the EditorConfig plugin is installed in your text editor, it will use this file to automatically configure certain formatting settings for the `an-editor` repository.

#### rustfmt

[`rustfmt`](https://github.com/rust-lang-nursery/rustfmt) is a tool for automatically formatting Rust source code according to style guidelines. This repository provides a [`rustfmt.toml`](rustfmt.toml) file for automatically configuring `rustfmt` to use our style guidelines.

`rustfmt` may be installed by running

```bash
$ cargo install rustfmt
```

and invoked on a crate by running

```bash
$ cargo fmt
```

Additionally, there are `rustfmt` plugins [available](https://github.com/rust-lang-nursery/rustfmt#running-rustfmt-from-your-editor) for many popular editors and IDEs.

`rustfmt` may also be added as a [git pre-commit hook](https://git-scm.com/book/uz/v2/Customizing-Git-Git-Hooks) to ensure that all commits conform to the style guidelines.


================================================
FILE: Cargo.toml
================================================
[package]
name = "sos_kernel"
version = "0.1.0"
authors = [ # hacked around by
            "Eliza Weisman <eliza@elizas.website>"
          , # based on code by
            "Philipp Oppermann <dev@phil-opp.com>"
          ]

build = "build.rs"
# build = false
# [[bin]]
# name = "sos_kernel_full"

# [lib]
# crate-type = ["staticlib"]
#

[profile.dev]
opt-level = 3
debug = true
rpath = false
lto = false
debug-assertions = true
codegen-units = 1
panic = "abort"

[profile.release]
opt-level = 3
debug = true
rpath = false
lto = false
panic = "abort"

[features]
default = []
trace = []

[dependencies]
rlibc = "0.1.4"
spin = "0.4.6"
once = "0.3.2"
bitflags = "0.7"
cpu = { path = "cpu" }
memory = { path = "memory" }
util = { path = "util" }
elf = { path = "elf" }
paging = { path = "paging" }
params = { path = "params" }

[dependencies.log]
version = "0.3.6"
default-features = false
features = ["release_max_level_info"]

[dependencies.lazy_static]
version = "0.2.11"
features = ["spin_no_std"]

[dependencies.vga]
path = "vga"
features = ["kinfo", "system_term"]

[dependencies.sos_alloc]
path = "sos_alloc"
features = ["buddy", "system", "borrow", "buddy_as_system"]

[dependencies.clippy]
version = "0.0.60"
optional = true


================================================
FILE: LICENSE-APACHE
================================================
                              Apache License
                        Version 2.0, January 2004
                     http://www.apache.org/licenses/

TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

1. Definitions.

   "License" shall mean the terms and conditions for use, reproduction,
   and distribution as defined by Sections 1 through 9 of this document.

   "Licensor" shall mean the copyright owner or entity authorized by
   the copyright owner that is granting the License.

   "Legal Entity" shall mean the union of the acting entity and all
   other entities that control, are controlled by, or are under common
   control with that entity. For the purposes of this definition,
   "control" means (i) the power, direct or indirect, to cause the
   direction or management of such entity, whether by contract or
   otherwise, or (ii) ownership of fifty percent (50%) or more of the
   outstanding shares, or (iii) beneficial ownership of such entity.

   "You" (or "Your") shall mean an individual or Legal Entity
   exercising permissions granted by this License.

   "Source" form shall mean the preferred form for making modifications,
   including but not limited to software source code, documentation
   source, and configuration files.

   "Object" form shall mean any form resulting from mechanical
   transformation or translation of a Source form, including but
   not limited to compiled object code, generated documentation,
   and conversions to other media types.

   "Work" shall mean the work of authorship, whether in Source or
   Object form, made available under the License, as indicated by a
   copyright notice that is included in or attached to the work
   (an example is provided in the Appendix below).

   "Derivative Works" shall mean any work, whether in Source or Object
   form, that is based on (or derived from) the Work and for which the
   editorial revisions, annotations, elaborations, or other modifications
   represent, as a whole, an original work of authorship. For the purposes
   of this License, Derivative Works shall not include works that remain
   separable from, or merely link (or bind by name) to the interfaces of,
   the Work and Derivative Works thereof.

   "Contribution" shall mean any work of authorship, including
   the original version of the Work and any modifications or additions
   to that Work or Derivative Works thereof, that is intentionally
   submitted to Licensor for inclusion in the Work by the copyright owner
   or by an individual or Legal Entity authorized to submit on behalf of
   the copyright owner. For the purposes of this definition, "submitted"
   means any form of electronic, verbal, or written communication sent
   to the Licensor or its representatives, including but not limited to
   communication on electronic mailing lists, source code control systems,
   and issue tracking systems that are managed by, or on behalf of, the
   Licensor for the purpose of discussing and improving the Work, but
   excluding communication that is conspicuously marked or otherwise
   designated in writing by the copyright owner as "Not a Contribution."

   "Contributor" shall mean Licensor and any individual or Legal Entity
   on behalf of whom a Contribution has been received by Licensor and
   subsequently incorporated within the Work.

2. Grant of Copyright License. Subject to the terms and conditions of
   this License, each Contributor hereby grants to You a perpetual,
   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
   copyright license to reproduce, prepare Derivative Works of,
   publicly display, publicly perform, sublicense, and distribute the
   Work and such Derivative Works in Source or Object form.

3. Grant of Patent License. Subject to the terms and conditions of
   this License, each Contributor hereby grants to You a perpetual,
   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
   (except as stated in this section) patent license to make, have made,
   use, offer to sell, sell, import, and otherwise transfer the Work,
   where such license applies only to those patent claims licensable
   by such Contributor that are necessarily infringed by their
   Contribution(s) alone or by combination of their Contribution(s)
   with the Work to which such Contribution(s) was submitted. If You
   institute patent litigation against any entity (including a
   cross-claim or counterclaim in a lawsuit) alleging that the Work
   or a Contribution incorporated within the Work constitutes direct
   or contributory patent infringement, then any patent licenses
   granted to You under this License for that Work shall terminate
   as of the date such litigation is filed.

4. Redistribution. You may reproduce and distribute copies of the
   Work or Derivative Works thereof in any medium, with or without
   modifications, and in Source or Object form, provided that You
   meet the following conditions:

   (a) You must give any other recipients of the Work or
       Derivative Works a copy of this License; and

   (b) You must cause any modified files to carry prominent notices
       stating that You changed the files; and

   (c) You must retain, in the Source form of any Derivative Works
       that You distribute, all copyright, patent, trademark, and
       attribution notices from the Source form of the Work,
       excluding those notices that do not pertain to any part of
       the Derivative Works; and

   (d) If the Work includes a "NOTICE" text file as part of its
       distribution, then any Derivative Works that You distribute must
       include a readable copy of the attribution notices contained
       within such NOTICE file, excluding those notices that do not
       pertain to any part of the Derivative Works, in at least one
       of the following places: within a NOTICE text file distributed
       as part of the Derivative Works; within the Source form or
       documentation, if provided along with the Derivative Works; or,
       within a display generated by the Derivative Works, if and
       wherever such third-party notices normally appear. The contents
       of the NOTICE file are for informational purposes only and
       do not modify the License. You may add Your own attribution
       notices within Derivative Works that You distribute, alongside
       or as an addendum to the NOTICE text from the Work, provided
       that such additional attribution notices cannot be construed
       as modifying the License.

   You may add Your own copyright statement to Your modifications and
   may provide additional or different license terms and conditions
   for use, reproduction, or distribution of Your modifications, or
   for any such Derivative Works as a whole, provided Your use,
   reproduction, and distribution of the Work otherwise complies with
   the conditions stated in this License.

5. Submission of Contributions. Unless You explicitly state otherwise,
   any Contribution intentionally submitted for inclusion in the Work
   by You to the Licensor shall be under the terms and conditions of
   this License, without any additional terms or conditions.
   Notwithstanding the above, nothing herein shall supersede or modify
   the terms of any separate license agreement you may have executed
   with Licensor regarding such Contributions.

6. Trademarks. This License does not grant permission to use the trade
   names, trademarks, service marks, or product names of the Licensor,
   except as required for reasonable and customary use in describing the
   origin of the Work and reproducing the content of the NOTICE file.

7. Disclaimer of Warranty. Unless required by applicable law or
   agreed to in writing, Licensor provides the Work (and each
   Contributor provides its Contributions) on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
   implied, including, without limitation, any warranties or conditions
   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
   PARTICULAR PURPOSE. You are solely responsible for determining the
   appropriateness of using or redistributing the Work and assume any
   risks associated with Your exercise of permissions under this License.

8. Limitation of Liability. In no event and under no legal theory,
   whether in tort (including negligence), contract, or otherwise,
   unless required by applicable law (such as deliberate and grossly
   negligent acts) or agreed to in writing, shall any Contributor be
   liable to You for damages, including any direct, indirect, special,
   incidental, or consequential damages of any character arising as a
   result of this License or out of the use or inability to use the
   Work (including but not limited to damages for loss of goodwill,
   work stoppage, computer failure or malfunction, or any and all
   other commercial damages or losses), even if such Contributor
   has been advised of the possibility of such damages.

9. Accepting Warranty or Additional Liability. While redistributing
   the Work or Derivative Works thereof, You may choose to offer,
   and charge a fee for, acceptance of support, warranty, indemnity,
   or other liability obligations and/or rights consistent with this
   License. However, in accepting such obligations, You may act only
   on Your own behalf and on Your sole responsibility, not on behalf
   of any other Contributor, and only if You agree to indemnify,
   defend, and hold each Contributor harmless for any liability
   incurred by, or claims asserted against, such Contributor by reason
   of your accepting any such warranty or additional liability.

END OF TERMS AND CONDITIONS

APPENDIX: How to apply the Apache License to your work.

   To apply the Apache License to your work, attach the following
   boilerplate notice, with the fields enclosed by brackets "[]"
   replaced with your own identifying information. (Don't include
   the brackets!)  The text should be enclosed in the appropriate
   comment syntax for the file format. We also recommend that a
   file or class name and description of purpose be included on the
   same "printed page" as the copyright notice for easier
   identification within third-party archives.

Copyright [yyyy] [name of copyright owner]

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.


================================================
FILE: LICENSE-MIT
================================================
Copyright (c) 2015 The SOS Developers

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 THE
AUTHORS OR COPYRIGHT HOLDERS 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.


================================================
FILE: Makefile
================================================
arch ?= x86_64
target ?= $(arch)-sos-kernel-gnu

boot_target := x86_32-sos-bootstrap-gnu
boot_outdir := boot/target/$(boot_target)

iso := target/$(target)/debug/sos-$(arch).iso
kernel := target/$(target)/debug/sos_kernel
isofiles := target/$(target)/debug/isofiles
boot := $(boot_outdir)/debug/libboot.a


release_iso := target/$(target)/release/sos-$(arch).iso
release_kernel := target/$(target)/release/sos_kernel
release_isofiles := target/$(target)/release/isofiles
release_boot := $(boot_outdir)/release/libboot.a

grub_cfg := src/arch/$(arch)/grub.cfg

TIMESTAMP := $(shell /bin/date "+%Y-%m-%d-%H:%M:%S")

# wildcard paths
wild_iso := target/$(target)/%/sos-$(arch).iso
wild_kernel := target/$(target)/%/sos_kernel
wild_isofiles := target/$(target)/%/isofiles

#COLORS
GREEN  := $(shell tput -Txterm setaf 2)
WHITE  := $(shell tput -Txterm setaf 7)
YELLOW := $(shell tput -Txterm setaf 3)
RESET  := $(shell tput -Txterm sgr0)

# Add the following 'help' target to your Makefile
# And add help text after each target name starting with '\#\#'
# A category can be added with @category
HELP_FUN = \
    %help; \
    while(<>) { push @{$$help{$$2 // 'options'}}, [$$1, $$3] if /^([a-zA-Z\-]+)\s*:.*\#\#(?:@([a-zA-Z\-]+))?\s(.*)$$/ }; \
    print "usage: make [target]\n\n"; \
    for (sort keys %help) { \
    print "${WHITE}$$_:${RESET}\n"; \
    for (@{$$help{$$_}}) { \
    $$sep = " " x (20 - length $$_->[0]); \
    print "  ${YELLOW}$$_->[0]${RESET}$$sep${GREEN}$$_->[1]${RESET}\n"; \
    }; \
    print "\n"; }

.PHONY: all clean kernel run iso cargo help gdb test doc release-iso release-run release-kernel

exception: $(iso) ##@build Run the kernel, dumping the state from QEMU if an exception occurs
	@qemu-system-x86_64 -s -hda $(iso) -d int -no-reboot -serial file:$(CURDIR)/target/$(target)/serial-$(TIMESTAMP).log

cargo:

doc: ##@utilities Make RustDoc documentation
	@xargo doc

help: ##@miscellaneous Show this help.
	@perl -e '$(HELP_FUN)' $(MAKEFILE_LIST)

all: help

env: ##@utilities Install dev environment dependencies
	./scripts/install-env.sh

clean: ##@utilities Delete all build artefacts.
	@xargo clean
	@cd boot && xargo clean

kernel: $(kernel).bin ##@build Compile the debug kernel binary

iso: $(iso) ##@build Compile the kernel binary and make an ISO image

run: run-debug ##@build Make the kernel ISO image and boot QEMU from it.

release-kernel: $(release_kernel).bin ##@release Compile the release kernel binary

release-iso: $(release_iso) ##@release Compile the release kernel binary and make an ISO image

release-run: run-release ##@release Make the release kernel ISO image and boot QEMU from it.

debug: $(iso) ##@build Run the kernel, redirecting serial output to a logfile.
	@qemu-system-x86_64 -s -S -hda $(iso) -serial file:$(CURDIR)/target/$(target)/serial-$(TIMESTAMP).log

test: ##@build Test crate dependencies
	@cargo test -p sos_intrusive
	# @xargo test -p alloc
	@cd alloc && cargo test

run-%: $(wild_iso)
	@qemu-system-x86_64 -s -hda $<

$(wild_iso): $(wild_kernel).bin $(wild_isofiles) $(grub_cfg)
	@cp $< $(word 2,$^)/boot/
	@cp $(grub_cfg) $(word 2,$^)/boot/grub
	grub-mkrescue -o $@ $(word 2,$^)/
	@rm -r $(word 2,$^)

$(wild_isofiles):
	@mkdir -p $@/boot/grub

$(boot):
	@cd boot && RUST_TARGET_PATH="$(PWD)/targets" xargo rustc \
		--target $(boot_target) \
		-- --crate-type=staticlib
	# Place 32-bit bootstrap code into a 64-bit ELF
	@x86_64-pc-elf-objcopy -O elf64-x86-64 \
		$(boot_outdir)/debug/libboot32.a \
		$(boot_outdir)/debug/libboot.a
	@x86_64-pc-elf-objcopy --strip-debug -G _start \
		$(boot_outdir)/debug/libboot.a
	# @cd $(boot_outdir)/debug && ar -crus libboot.a boot.o

$(release_boot):
	@cd boot && RUST_TARGET_PATH="$(PWD)/targets" xargo rustc \
		--target $(boot_target) \
		-- --release \
		--crate-type=staticlib
	# Place 32-bit bootstrap code into a 64-bit ELF
	@x86_64-pc-elf-objcopy -O elf64-x86-64 \
		$(boot_outdir)/release/libboot32.a \
		$(boot_outdir)/release/libboot.a
	@x86_64-pc-elf-objcopy --strip-debug -G _start \
		$(boot_outdir)/release/libboot.a

$(release_kernel): $(release_boot)
	@RUST_TARGET_PATH="$(PWD)/targets" xargo build --target $(target) --release

$(release_kernel).bin: $(release_kernel)
	@cp $(release_kernel) $(release_kernel).bin

$(release_iso): $(release_kernel).bin $(grub_cfg)
	@mkdir -p $(release_isofiles)/boot/grub
	@cp $(release_kernel).bin $(release_isofiles)/boot/
	@cp $(grub_cfg) $(release_isofiles)/boot/grub
	@grub-mkrescue -o $(release_iso) $(release_isofiles)/
	@rm -r $(release_isofiles)

$(kernel): $(boot)
	@RUST_TARGET_PATH="$(PWD)/targets" xargo build --target $(target)

$(kernel).debug: $(kernel)
	@x86_64-elf-objcopy --only-keep-debug $(kernel) $(kernel).debug

$(kernel).bin: $(kernel) $(kernel).debug
	@x86_64-elf-strip -g -o $(kernel).bin $(kernel)
	@x86_64-elf-objcopy --add-gnu-debuglink=$(kernel).debug $(kernel)

gdb: $(kernel).bin $(kernel).debug ##@utilities Connect to a running QEMU instance with gdb.
	@rust-os-gdb -ex "target remote tcp:127.0.0.1:1234" $(kernel)


================================================
FILE: Notes.md
================================================
Notes
=====

On designing a userland
-----------------------

+ provide user code written in Rust with a fluent Rust API
+ [capability-based security](https://en.wikipedia.org/wiki/Capability-based_security)

#### prior art
+ `ioctl` is a great example of _exactly what not to do_ - every system call should be its own call. requiring the programmer to keep track of both syscalls and values to pass to `ioctl` is a pain.
+ `kqueue` is good


================================================
FILE: README.md
================================================
# Stupid Operating System 
[![Build Status](https://travis-ci.org/hawkw/sos-kernel.svg?branch=master)](https://travis-ci.org/hawkw/kernel) 
[![MIT License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat)](https://github.com/sos-os/kernel/LICENSE-MIT) [![Latest RustDoc](https://img.shields.io/badge/rustdoc-latest-orange.svg)](http://www.elizas.website/sos-kernel/sos_kernel/index.html) 
[![Gitter](https://img.shields.io/gitter/room/sos-os/kernel.svg)](https://gitter.im/sos-os)

SOS is a simple, tiny toy OS implemented in Rust.

I'm writing this mostly for fun, to learn more about OS design and kernel hacking, so don't expect anything new or exciting out of this project.

Inspiration, and a reasonable amount of code, taken from @phil-opp's great [series of blog posts](http://os.phil-opp.com) on the subject, Charlie Somerville's [rustboot](https://github.com/charliesome/rustboot), and Samy Pessé's [_How to Make an Operating System_](https://www.gitbook.com/book/samypesse/how-to-create-an-operating-system/details).

design goals
------------

 + **POSIX compliance is not a goal** (though it would be cool)
 + **Hybrid/loosely microkernel** (i.e., move code to user space *when convenient/practical*)
 + Possibly provide the **Rust stdlib** at the OS level.
 + **JVM-style** memory allocation?
 + Possibly experiment with a **[Plan 9-esque](https://en.wikipedia.org/wiki/9P_(protocol)) networking stack** eventually?


building & running
------------------

I've included a simple [`Makefile`](Makefile) to automate building and running SOS. This README lists most of the important make targets, but there's also a `$ make help` command, which will print a list of all available targets.

### setting up your build environment
In order to build SOS, you'll need to properly configure your build environment. Since this process is fairly complex, I've provided some automatic installation shell scripts to make it a bit more painless.

+ `$ make env` will install and configure build dependencies

If you don't trust the scripts, or if you're curious to know what they're doing, you can also follow the manual install instructions in [`BUILDING.md`](BUILDING.md).

### building & running the OS
  + `$ make kernel` compiles & links the kernel binary
  + `$ make iso` makes the kernel and builds a bootable ISO image
  + `$ make run` compiles the kernel, makes the ISO, and boots QEMU from the ISO


================================================
FILE: Vagrantfile
================================================
# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure(2) do |config|
  config.vm.box = "hashicorp/precise64"

  config.vm.provision "shell", inline: <<-SHELL
    sudo apt-get update
    sudo apt-get install -y build-essential
    sudo apt-get install -y curl
    sudo apt-get install nasm -y
    sudo apt-get install xorriso -y
    sudo apt-get install git -y
    sudo apt-get install vim -y
    sudo apt-get install -y qemu
    su - vagrant -c 'curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain nightly'
    ex +'$s@$@\rexport PATH=~/.cargo/bin/:$PATH@' -cwq /etc/bash.bashrc
  SHELL

  config.ssh.forward_x11 = true
end


================================================
FILE: Xargo.toml
================================================
[target.x86_64-sos-kernel-gnu.dependencies]
alloc = {}
# std = {}


================================================
FILE: boot/Cargo.toml
================================================
[package]
name = "boot32"
version = "0.1.0"
authors = ["Eliza Weisman <eliza@elizas.website>"]

[lib]
crate-type = ["staticlib"]

# [[bin]]
# name = "libboot32.a"

[features]
default = ["log"]
log = []

[profile.dev]
opt-level = 3
debug = true
rpath = false
lto = false
debug-assertions = true
codegen-units = 1
panic = "abort"

[profile.release]
opt-level = 3
debug = true
rpath = false
lto = false
panic = "abort"

[dependencies]
rlibc = "0.1.4"


================================================
FILE: boot/README.md
================================================
# SOS x86_64 bootstrap

this crate contains code for the 32-bit protected mode boot routine for x86_64 CPUs. when we boot up an x86_64 system using GRUB & multiboot, we end up with the CPU running in 32-bit 'protected mode', rather than 64-bit 'long mode'. before we can jump into long mode, we have to perform a handful of setup tasks in protected mode.

this boot routine lives in a separate crate, with a 32-bit `target.json`. when building SOS for x86_64, we have to compile this crate separately and then link the resulting 32-bit object with the rest of the 64-bit kernel object.

this boot crate is only necessary for x86_64. for other architectures, all boot code can live in the main kernel crate.


================================================
FILE: boot/src/lib.rs
================================================
//
//  SOS: the Stupid Operating System
//  by Eliza Weisman (eliza@elizas.website)
//
//  Copyright (c) 2016-2017 Eliza Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! # SOS x86_64 bootstrap
//!
//! This crate contains code for the 32-bit protected mode boot routine for
//! x86_64 CPUs. When we boot up an x86_64 system using GRUB & multiboot, we
//! end up with the CPU running in 32-bit 'protected mode', rather than 64-bit
//! 'long mode'. Before we can jump into long mode, we have to perform a
//! handful of setup tasks in protected mode.
//!
//! This boot routine lives in a separate crate, with a 32-bit `target.json`.
//! When building SOS for x86_64, we have to compile this crate separately and
//! then link the resulting 32-bit object with the rest of the 64-bit kernel
//! object.
//!
//! This boot crate is only necessary for x86_64. For other architectures, all
//! boot code can live in the main kernel crate.
//!
//! For more information, refer to:
//! + the [intermezzOS book]
//! + the [OSDev Wiki] article on long mode
//! + Philipp Oppermann's [blog post]
//!
//! [intermezzOS book]: http://intermezzos.github.io/book/transitioning-to-long-mode.html
//! [OSDev Wiki]: http://wiki.osdev.org/Long_Mode#Long_Mode
//! [blog post]: http://os.phil-opp.com/entering-longmode.html

#![crate_name = "boot32"]
#![feature(asm)]
#![feature(lang_items)]
#![feature(naked_functions)]
#![feature(linkage)]
#![feature(struct_field_attributes)]
#![feature(stmt_expr_attributes)]
#![no_std]

extern crate rlibc;

const TABLE_LENGTH: usize = 512;
/// The size of a "huge" page
const HUGE_PAGE_SIZE: u64 = 2 * 1024 * 1024; // 2 MiB
/// Page table entry flags for a page that is present and writable.
const ENTRY_FLAGS_PW: u64 = 0b11;

/// A page table is an array of page table entries.
type Table = [TableEntry; TABLE_LENGTH];

trait PageTable: Sized {
    /// Install this page table as the top-level page table.
    #[inline(always)]
    unsafe fn set_top_level(&'static self) {
        asm!("mov cr3, $0" :: "r"(self) :: "intel");
    }
}

impl PageTable for Table { }

/// A page table entry is a 64-bit unsigned integer.
///
/// We represent this as a [newtype] rather than a type alias, because we want
/// to implement specific functionality on it.
///
/// [newtype]: https://aturon.github.io/features/types/newtype.html
#[repr(C)]
struct TableEntry(u64);

impl TableEntry {
    /// Set this table entry to map to a lower-level page table.
    // TODO: use a marker type to ensure this always maps to a _lower-level_
    //       table?
    #[inline(always)]
    unsafe fn map_to_table(&mut self, to: &'static Table) {
        *self = TableEntry(to as *const _ as u64 | ENTRY_FLAGS_PW);
    }

    /// Set this table entry to map to a huge page with the given number.
    #[inline(always)]
    unsafe fn map_to_page(&mut self, number: usize) {
        // Page table entry flags for a page that is huge, present, and writable.
        const ENTRY_FLAGS_HUGE: u64 = 0b10000011;
        // the start address is the page number times the page's size
        let addr = number as u64 * HUGE_PAGE_SIZE;
        *self = TableEntry(addr | ENTRY_FLAGS_HUGE);
    }

}

use core::convert;

macro_rules! set_flags {
    (%$register:ident $( |= $body:expr);+ ) => {
        let mut $register: usize;
        asm!( concat!("mov $0, ", stringify!($register))
            : "=r"($register)
            ::: "intel");
        $($register |= $body;)+
        asm!( concat!("mov ", stringify!($register), ", $0")
            :: "r"($register)
            :: "intel");
    }
}

#[repr(C, packed)]
pub struct Gdt { _null: u64
               , code: u64
               }

#[repr(C, packed)]
pub struct GdtPointer { /// the length of the GDT
                        pub limit: u16
                      , /// pointer to the GDT
                        pub base: &'static Gdt
                      }

impl GdtPointer {
    #[cold] #[inline(always)]
    unsafe fn load (&self) {
        asm!("lgdt ($0)" :: "r"(self) : "memory");
    }
}

impl convert::From<&'static Gdt> for GdtPointer {
    #[cold] #[inline(always)]
    fn from(gdt: &'static Gdt) -> Self {
        use core::mem::size_of_val;
        GdtPointer { limit: size_of_val(gdt) as u16 - 1
                   , base: gdt }
    }
}

#[link_name = ".gdt64"]
#[link_section = ".gdt"]
#[no_mangle]
pub static GDT: Gdt
    = Gdt { _null: 0
          , code: (1<<44) | (1<<47) | (1<<41) | (1<<43) | (1<<53)
          };

#[inline(always)]
fn boot_write(s: &[u8]) {
    unsafe {
        use core::ptr::write_volatile;
        let vga_buf = 0xb8000 as *mut u16;
    	for (n, c) in s.iter().enumerate() {
    		write_volatile(vga_buf.offset(n as isize), 0x0200 + *c as u16);
    	}

    }

}

extern "C" {
    static mut pml4_table: Table;
    static mut pdp_table: Table;
    static mut pd_table: Table;
}

#[cold]
#[inline(always)]
#[naked]
unsafe fn create_page_tables() {
    //-- map the PML4 and PDP tables -----------------------------------------
    // recursive map last PML4 entry
    pml4_table[511].map_to_table(&pml4_table);
    // map first PML4 entry to PDP table
    pml4_table[0].map_to_table(&pdp_table);
    // map first PDPT entry to PD table
    pdp_table[0].map_to_table(&pd_table);

    boot_write(b"3.1");

    //-- map the PD table ----------------------------------------------------
    for (page_number, entry) in pd_table.iter_mut().enumerate() {
        entry.map_to_page(page_number);
    }

    boot_write(b"3.2");
}

#[cold]
#[inline(always)]
unsafe fn set_long_mode() {
    // load PML4 addr to cr3
    &pml4_table.set_top_level();
    boot_write(b"3.3");

    // // enable PAE flag in cr4
    // set_flags!(%cr4 |= 1 << 5 );
    asm!("mov eax, cr4
          or eax, 1 << 5
          mov cr4, eax" ::: "memory" : "intel", "volatile");
    boot_write(b"3.4");

    // set the long mode bit in EFER MSR (model specific register)
    asm!( "mov   ecx, 0xC0000080
           rdmsr
           or    eax, 1 << 8
           wrmsr"
        :::"memory": "intel", "volatile");
    boot_write(b"3.5");

    // enable paging in cr0
    // set_flags!(%cr0 |= 1 << 31;
    //                 |= 1 << 16 );

    asm!("mov eax, cr0
          or eax, 0x80000000
          mov cr0, eax" :::"memory": "intel", "volatile");
    boot_write(b"3.6")
}

/// Test whether or not this system supports Multiboot 2
#[cold]
#[inline(always)]
unsafe fn is_multiboot_supported() -> bool {
    const MULTIBOOT_MAGIC: usize = 0x36d76289;
    let eax: usize;
    asm!("mov eax, $0" : "=r"(eax) ::: "intel");
    eax == MULTIBOOT_MAGIC
}


#[cold]
#[no_mangle]
#[naked]
pub unsafe extern "C" fn _start() {
    boot_write(b"0");
    asm!("cli");


    // 1. Move Multiboot info pointer to edi
    asm!("mov edi, ebx" :::: "intel");
    boot_write(b"1");

    // 2. make sure the system supports SOS
    // TODO: port this from boot.asm
    if !is_multiboot_supported() {
        loop { boot_write(b"ERROR: multiboot not supported!"); }
    }
    boot_write(b"2");

    // 3. if everything is okay, create the page tables and start long mode
    create_page_tables();
    set_long_mode();

    // 4. load the 64-bit GDT
    GdtPointer::from(&GDT).load();
    boot_write(b"4");

    // 6. jump to the 64-bit boot subroutine.
    asm!("ljmpl $$8, $$long_mode_init");

}

#[cold]
#[lang = "panic_fmt"]
fn panic_fmt() -> ! {
    loop {
        boot_write(b"panic! panic! panic!");
    }
}

================================================
FILE: build.rs
================================================
use std::env;

fn main() {
    let profile = env::var("PROFILE").unwrap();
    if profile != "test" {
        // target triple
        let target
            = env::var("TARGET").unwrap();
        // extract the architecture name from the target triple
        let arch_name
            = target.split("-").next()
                    .expect("Couldn't parse target triple!");


        let boot_path = if arch_name == "x86_64" {
            format!("boot/target/x86_32-sos-bootstrap-gnu/{}/", profile)
        } else {
            panic!("target arch {} not yet supported, sorry!", arch_name);
        };
        println!("cargo:rustc-link-search=native={}", boot_path);
        println!("cargo:rustc-link-lib=static=boot");
    }


}


================================================
FILE: cpu/Cargo.toml
================================================
[package]
name = "cpu"
version = "0.0.1"
authors = [ "Eliza Weisman <eliza@elizas.website>" ]

[profile.dev]
opt-level = 3
debug = true
rpath = false
lto = false
debug-assertions = true
codegen-units = 1
panic = "abort"

[profile.release]
opt-level = 3
debug = true
rpath = false
lto = false
panic = "abort"

[dependencies]
util = { path = "../util" }
bitflags = "0.7"
spin = "0.4.6"

[dependencies.vga]
path = "../vga"
features = ["kinfo", "system_term"]

[dependencies.memory]
path = "../memory"

[dependencies.log]
version = "0.3.6"
default-features = false
features = ["release_max_level_info"]

[dependencies.lazy_static]
version = "0.2.11"
features = ["spin_no_std"]


================================================
FILE: cpu/src/armv7/mod.rs
================================================
//
//  SOS: the Stupid Operating System
//  by Eliza Weisman (eliza@elizas.website)
//
//  Copyright (c) 2015-2017 Eliza Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//!  ARM v7 architecture-specific implementation
//  TODO: NYI

pub const ARCH_BITS: u8 = 64;


================================================
FILE: cpu/src/lib.rs
================================================
//
//  SOS: the Stupid Operating System
//  by Eliza Weisman (eliza@elizas.website)
//
//  Copyright (c) 2016 Eliza eisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
#![crate_name = "cpu"]
#![crate_type = "lib"]
#![feature(const_fn)]
#![feature(asm)]
#![feature(naked_functions)]
#![feature(slice_patterns)]
#![feature(linkage)]
#![feature(stmt_expr_attributes)]
#![cfg_attr(target_arch = "x86_64", feature(abi_x86_interrupt))]
#![no_std]

//-- non-SOS dependencies ----------------------------------------------------
extern crate spin;
#[macro_use] extern crate log;
#[macro_use] extern crate bitflags;

//-- SOS dependencies --------------------------------------------------------
extern crate util;
extern crate memory;
#[macro_use] extern crate vga;

use core::marker::PhantomData;

//-- re-exports --------------------------------------------------------------
// 64-bit x86_64 (long mode)
#[cfg(target_arch="x86_64")] mod x86_64;
#[cfg(target_arch="x86_64")] pub use self::x86_64::*;

// 32-bit x86 (protected mode)
// TODO: NYI
#[cfg(target_arch = "x86")] mod x86;
#[cfg(target_arch = "x86")] pub use self::x86::*;

// ARM v7
// TODO: NYI
#[cfg(target_arch = "armv7")] mod armv7;
#[cfg(target_arch = "armv7")] pub use self::x86::*;

/// A CPU I/O port.
///
/// This is a typed wrapper around an [`UnsafePort`](struct.UnsafePort.html).
/// Unlike an `UnsafePort`, this
pub struct Port<T> { raw_port: UnsafePort
                   , typ: PhantomData<T>
                   }

macro_rules! make_ports {
    ( $( $t:ty, $read:ident, $out:ident ),+ ) => {
        $(
            impl Port<$t> {
                #[inline]
                pub const fn new(number: u16) -> Self {
                    // TODO: can we check if the port number is valid
                    unsafe {
                        Port { raw_port: UnsafePort::new(number)
                             , typ: PhantomData::<$t>
                             }
                    }
                }

                #[inline]
                pub fn read(&self) -> $t {
                    unsafe { self.raw_port.$read() }
                }

                #[inline]
                pub fn write(&self, data: $t) {
                    unsafe { self.raw_port.$out(data) }
                }
            }
        )+
    }
}

make_ports! { u8, in8, out8
            , u16, in16, out16
            , u32, in32, out32
            }

#[cfg(arch="x86_64")]
make_ports! { u64, in64, out64 }


================================================
FILE: cpu/src/x86/cpu.rs
================================================
//
//  SOS: the Stupid Operating System
//  by Eliza Weisman (eliza@elizas.website)
//
//  Copyright (c) 2015-2017 Eliza Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! Code for interacting with the `x86` CPU.
//!
//! Currently this module contains a quick implementation of CPU port
//! input and output, and little else.

#[path = "../x86_all/cpu/mod.rs"] mod cpu_all;
pub use self::cpu_all::*;

#[path = "../x86_all/interrupts/mod.rs"]
pub mod interrupts;


================================================
FILE: cpu/src/x86/mod.rs
================================================
//
//  SOS: the Stupid Operating System
//  by Eliza Weisman (eliza@elizas.website)
//
//  Copyright (c) 2015-2017 Eliza Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! `x86` architecture-specific implementation.
//!
//! This module contains code for `x86` 32-bit protected-mode systems.
pub mod cpu;
pub mod memory;
// pub mod keyboard;

pub const ARCH_BITS: u8 = 32;


================================================
FILE: cpu/src/x86_64/context.rs
================================================
//
//  SOS: the Stupid Operating System
//  by Eliza Weisman (eliza@elizas.website)
//
//  Copyright (c) 2015-2017 Eliza Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! `x86_64` execution contexts.
//!
//! This is inteded to be general-purpose and composable, so that the same
//! code can be reused for interrupts and for multithreading.

use core::mem;
use core::fmt;
use super::flags::{Flags as RFlags};
use super::segment;

/// Registers pushed to the stack when handling an interrupt or context switch.
#[repr(C, packed)]
#[derive(Copy, Clone)]
pub struct Registers { pub rsi: u64
                     , pub rdi: u64
                     , pub r11: u64
                     , pub r10: u64
                     , pub r9:  u64
                     , pub r8:  u64
                     , pub rdx: u64
                     , pub rcx: u64
                     , pub rax: u64
                     }

 impl Registers {
     /// Transform this struct into an array of `u64`s
     /// (if you would ever want to do this)
     /// TODO: rewrite this to be a `convert::Into` implementation.
     //         - eliza, 03/09/2017
     pub unsafe fn to_array(&self) -> [u64; 9] {
        //  [ self.rsi, self.rdi, self.r11
        //  , self.r10, self.r9, self.r8
        //  , self.rdx, self.rcx, self.rax
        //  ]
        // using transmute is probably faster and we're already unsafe...
        mem::transmute(*self)
     }

     /// Create a new empty set of Registers
     pub const fn empty() -> Self {
         Registers { rsi: 0, rdi: 0, r11: 0
                   , r10: 0, r9:  0, r8:  0
                   , rdx: 0, rcx: 0, rax: 0
                   }
     }

     /// Push the caller-saved registers to the stack
     /// (such as when handling a context switch or interrupt).
     ///
     /// THIS FUNCTION IS NAKED. DO NOT CALL IT NORMALLY.
     #[naked]
     #[inline(always)]
     pub unsafe fn push() {
         asm!( "push rax
                push rcx
                push rdx
                push r8
                push r9
                push r10
                push r11
                push rdi
                push rsi"
             :::: "intel"
                , "volatile");
     }

     /// Push the caller-saved registers off the stack
     /// (such as when handling a context switch or interrupt).
     ///
     /// THIS FUNCTION IS NAKED. DO NOT CALL IT NORMALLY.
     #[naked]
     #[inline(always)]
     pub unsafe fn pop() {
         asm!( "pop rsi
                pop rdi
                pop r11
                pop r10
                pop r9
                pop r8
                pop rdx
                pop rcx
                pop rax"
             :::: "intel"
                , "volatile");
     }
 }

impl fmt::Debug for Registers {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!( f
               , "    RSI: {:#018x} RDI: {:#018x} R11: {:#018x}\n    \
                      R10: {:#018x} R9:  {:#018x} R8:  {:#018x}\n    \
                      RDX: {:#018x} RCX: {:#018x} RAX: {:#018x}"
              , self.rsi, self.rdi, self.r11
              , self.r10, self.r9,  self.r8
              , self.rdx, self.rcx, self.rax)
     }
}



#[repr(C, packed)]
pub struct InterruptFrame {
    //  this is the actual value of the interrupt stack frame context,
    //  not the old one (which is wrong). note that the old one seems to cause
    //  stack misalignment.
    //          -- eliza, october 4th, 2016
    /// Value of the instruction pointer (`$rip`) register
    pub rip: *const u8
  , /// Value of the code segment (`$cs`) register
    pub cs: segment::Selector
  , __pad_1: u32
  , __pad_2: u16
  , /// Value of the CPU flags (`$rflags`) register
    pub rflags: RFlags
  , /// Value of the stack pointer (`$rsp`) register
    //  TODO: should this actually be a pointer?
    pub rsp: *const u8
  , /// Value of the stack segment (`$ss`) register
    pub ss: segment::Selector
  , __pad_3: u32
  , __pad_4: u16
}

#[cfg(test)]
mod test {
    #[test]
    fn test_interrupt_frame_correct_size() {
        use core::mem::size_of;
        use super::InterruptFrame;

        assert_eq!(size_of::<InterruptFrame>(), 32);
    }
}

impl fmt::Debug for InterruptFrame {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!( f
              , "Interrupt Frame: \
                \n   instruction pointer: {:p} \
                \n   code segment:        {} \
                \n   rflags:              {:?} \
                \n   stack pointer:       {:p} \
                \n   stack segment:       {}"
             , self.rip
            //  , self.__pad_1, self.__pad_2
             , self.cs
             , self.rflags
             , self.rsp
            //  , self.__pad_3, self.__pad_4
             , self.ss)
    }
}

/// Thread execution context
#[repr(C, packed)]
pub struct Context { /// Value of the stack pointer (`rsp`) register
                     pub rsp: *mut u8
                   , /// Value of the caller-saved registers
                     pub registers: Registers
                   , /// Value of the instruction pointer (`rip`) register
                     pub rip: *mut u8
                 //, pub stack: [u8] // TODO: should be box
                   }

impl Context {
    pub fn empty() -> Self {
        unsafe {
            Context { rsp: mem::transmute(0u64)
                    , registers: Registers::empty()
                    , rip: mem::transmute(0u64)
                  //, stack: [0u8; 8]
                    }
        }
    }
}


================================================
FILE: cpu/src/x86_64/mod.rs
================================================
//
//  SOS: the Stupid Operating System
//  by Eliza Weisman (eliza@elizas.website)
//
//  Copyright (c) 2016 Eliza Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! Code for interacting with the `x86_64` CPU.
//!
//! This module contains code for interrupts, paging, context switches,
//! CPU I/O (from `x86_all`), and reading/writing the x86 control registers.
//!

#[path = "../x86_all/mod.rs"] mod cpu_all;

pub mod context;
pub mod task;
pub mod msr;

pub use self::context::Registers;
pub use self::cpu_all::*;


================================================
FILE: cpu/src/x86_64/msr.rs
================================================
//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! Code for interacting with the Model-Specific Registers (MSRs).

/// Extended Feature Enable Register (EFER) on IA-32
pub const IA32_EFER: u32 = 0xc0000080;

/// Write `value` to the specified `msr`
///
/// # Arguments
/// + `msr`: which MSR to write to
/// + `value`: the  bits to write
pub unsafe fn write(msr: u32, value: u64) {
    let low = value as u32;
    let high = (value >> 32) as u32;
    asm!(   "wrmsr"
         :: "{ecx}" (msr), "{eax}" (low), "{edx}" (high)
         :  "memory"
         : "volatile" );
}

/// Read 64 bits from the specified `msr`
pub unsafe fn read(msr: u32) -> u64 {
    let low: u32;
    let high: u32;
    asm!( "rdmsr"
        : "={eax}" (low), "={edx}" (high)
        : "{ecx}" (msr)
        : "memory"
        : "volatile" );
    ((high as u64) << 32) | (low as u64)
}


/// Enable the NXE (No Execute) in the IA-32 EFER register.
///
/// This allows us to set the NXE bit on pages.
pub unsafe fn enable_nxe() {
    let nxe_bit = 1 << 11;
    let efer = read(IA32_EFER) | nxe_bit;
    write(IA32_EFER, efer);
}


================================================
FILE: cpu/src/x86_64/task.rs
================================================
//
//  SOS: the Stupid Operating System
//  by Eliza Weisman (eliza@elizas.website)
//
//  Copyright (c) 2015-2017 Eliza Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! Tasking
use ::segment;
use memory::VAddr;

/// A 64-bit Task State Descriptor
#[repr(packed)]
pub struct StateDescriptor { pub upper: segment::Descriptor
                           , pub lower: u64
                           }


/// A 64-bit Task State Segment
#[repr(C, packed)]
#[derive(Debug)]
pub struct StateSegment {
    _reserved_1: u32
  , /// 64-bit values of the stack pointers (`%rsp`) for privilege rings 0-2
    //  TODO: should this be an array or just three u64s?
    pub rsp: [VAddr; 3]
  , _reserved_2: u32
  , /// 64-bit values of the interrupt stack table registers
    pub ist: [VAddr; 7]
  , _reserved_3: u64
  , _reserved_4: u16
  , /// the base offset of the IO map
    pub iomap_base_offset: u16
}

impl StateSegment {

    /// Returns a new, empty TSS
    pub const fn new() -> Self {
        StateSegment { _reserved_1: 0
                     , rsp: [ VAddr::new(0); 3]
                     , _reserved_2: 0
                     , ist: [ VAddr::new(0); 7 ]
                     , _reserved_3: 0
                     , _reserved_4: 0
                     , iomap_base_offset: 0
                     }
    }
}


================================================
FILE: cpu/src/x86_all/control_regs/cr0.rs
================================================
use core::fmt;

bitflags! {
    /// Flag present in `%cr0`.
    ///
    /// See [the OS Dev Wiki](http://wiki.osdev.org/CR0#CR0) for more
    /// information.
    pub flags Flags: usize {
        /// Protected Mode Enable
        ///
        /// If 1, system is in protected mode. Otherwise, the system is in real
        /// mode.
        const PE = 1 << 0
      , /// Monitor co-processor
        ///
        /// Controls interaction of `WAIT`/`FWAIT` instructions with `TS` flag
        /// in `%cr0`.
        const MP = 1 << 1
      , /// FPU Emulation
        ///
        /// If set, no x87 floating point unit present, if clear, x87 FPU
        /// present.
        const EM = 1 << 2
      , /// Task Switched
        ///
        /// Allows saving x87 task context upon a task switch only after x87
        /// instruction used.
        const TS = 1 << 3
      , /// Extension Type
        ///
        /// On a 386 CPU, indicated whether the math coprocessor was an 80287
        /// or an 80387.
        const ET = 1 << 4
      , /// Numeric Error
        ///
        /// Enable internal x87 floating point error reporting when set, else
        /// enables PC style x87 error detection.
        const NE = 1 << 5
      , /// Write Protect
        ///
        /// When set, the CPU can't write to read-only pages when privilege
        /// level is 0.
        const WP = 1 << 16
      , /// Alignment Mask
        ///
        /// Alignment check enabled if `AM` set, `AC` flag (in `%eflags`
        /// register) set, and privilege level is 3
        const AM = 1 << 18
      , /// Not Write-Through
        ///
        /// Globally enables/disable write-through caching
        const NW = 1 << 29
      , /// Cache Disable
        ///
        /// Globally enables/disable the memory cache
        const CD = 1 << 30
      , /// Paging
        ///
        /// If 1, enable paging and use the `%cr3` register, else disable
        /// paging.
        const PG = 1 << 31
    }
}

cpu_flag! {
    doc="If set, enable paging; if unset, disable paging.",
    PG, is_paging_enabled, enable_paging
}
cpu_flag! {
    doc="If set, enable the write protect bit; if unset, disable write \
        protect.",
    WP, is_write_protected, enable_write_protect
}

///// Set the write protect bit in `%cr0`.
//pub fn enable_write_protect() {
//    let mut flags: Flags = read();
//    if !flags.contains(WP) {
//        flags.insert(WP);
//        unsafe { write(flags) }
//    }
//}
//
///// Unset the write protect bit in `%cr0`.
//pub fn disable_write_protect() {
//    let mut flags: Flags = read();
//    if flags.contains(WP) {
//        flags.remove(WP);
//        unsafe { write(flags) }
//    }
//}
//
///// Set the paging bit in `%cr0`.
//pub fn enable_paging() {
//    let mut flags: Flags = read();
//    if !flags.contains(WP) {
//        flags.insert(WP);
//        unsafe { write(flags) }
//    }
//}
//
///// Unset the paging bit in `%cr0`.
//pub fn disable_paging() {
//    let mut flags: Flags = read();
//    if flags.contains(PG) {
//        flags.remove(PG);
//        unsafe { write(flags) }
//    }
//}

/// Read the current value from `%cr0`.
///
/// # Safety
/// + Reading from control registers while not in kernel mode will cause
///   a general protection fault.
pub unsafe fn read() -> Flags {
    let result: usize;
    asm!(   "mov $0, cr0"
        :   "=r"(result)
        ::: "intel" );
    Flags { bits: result }
}

/// Write a value to `%cr0`.
///
/// # Safety
/// + Control registers should generally not be modified during normal
///   operation.
pub unsafe fn write(flags: Flags) {
    asm!(  "mov cr0, $0"
        :: "r"(flags.bits)
        :: "intel");
}

impl fmt::LowerHex for Flags {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:#08x}", self.bits)
    }
}


================================================
FILE: cpu/src/x86_all/control_regs/cr4.rs
================================================
use core::fmt;

/// Read the current value from `$cr4`.
///
/// # Safety
/// + Reading from control registers while not in kernel mode will cause
///   a general protection fault.
pub unsafe fn read() -> Flags {
    let result: usize;
    asm!(   "mov $0, cr4"
        :   "=r"(result)
        ::: "intel" );
    Flags { bits: result }
}

/// Write a value to `$cr4`.
///
/// # Safety
/// + Control registers should generally not be modified during normal
///   operation.
pub unsafe fn write(flags: Flags) {
    asm!(  "mov cr4, $0"
        :: "r"(flags.bits)
        :: "intel");
}


bitflags! {
    /// Bitflags present in `$cr4`
    ///
    /// Documentation taken from
    /// [wikipedia](https://en.wikipedia.org/wiki/Control_register#CR4).
    pub flags Flags: usize {
        /// Virtual 8086 Mode Extensions
        ///
        /// If set, enables support for the virtual interrupt flag (VIF) in
        /// virtual-8086 mode.
        const VME = 1 << 0
      , /// Protected-mode Virtual Interrupts
        ///
        /// If set, enables support for the virtual interrupt flag (VIF) in
        /// protected mode.
        const PVI = 1 << 1
      , /// Time Stamp Disable
        ///
        /// If 1, the `RTDSC` instruction can only be executed in Ring 0
        const TSD = 1 << 2
      , /// Debugging Extensions
        ///
        /// If set, enables debug register based breaks on I/O space access
        const DE = 1 << 3
      , /// Page Size Extension
        ///
        /// If unset, page size is 4 KiB, else page size is increased to 4 MiB
        /// (if PAE is enabled or the processor is in Long Mode this bit is
        /// ignored).
        const PSE = 1 << 4
      , /// Physical Address Extension
        ///
        /// If set, changes page table layout to translate 32-bit virtual
        /// addresses into extended 36-bit physical addresses.
        const PAE = 1 << 5
      , /// Machine Check Exception
        ///
        /// If set, Machine Check exceptions are enabled.
        const MCE = 1 << 6
      , /// Page Global Enabled
        ///
        /// If set, address translations (PDE or PTE records) may be shared
        /// between address spaces.
        const PGE = 1 << 7
      , /// Performance-Monitoring Counter enable
        ///
        /// If set, the `RDPMC` instruction can be executed at any privilege
        /// level, else `RDPMC` can only be used in ring 0.
        const PCE = 1 << 8
      , /// Operating system support for `FXSAVE` and `FXRSTOR` instructions
        ///
        /// If set, enables SSE instructions and fast FPU save and restore.
        const OSFXSR = 1 << 9
      , /// Operating System Support for Unmasked SIMD Floating-Point Exceptions
        ///
        /// If set, enables unmasked SSE exceptions.
        const OSXMMEXCPT = 1 << 10
      , /// Virtual Machine Extensions Enable
        const VMXE = 1 << 13
      , /// Safer Mode Extensions Enable
        const SMXE = 1 << 14
      , /// Enables the instructions RDFSBASE, RDGSBASE, WRFSBASE, and WRGSBASE.
        const FSGSBASE = 1 << 16
      , /// PCID Enable
        ///
        /// If set, enables process-context identifiers (PCIDs).
        const PCIDE = 1 << 17
      , /// `XSAVE` and Processor Extended States Enable
        const OSXSAVE = 1 << 18
      , /// Supervisor Mode Execution Protection Enable
        ///
        /// If set, execution of code in a higher ring generates a fault
        const SMEP = 1 << 20
      , /// Supervisor Mode Access Protection Enable
        ///
        /// If set, access of data in a higher ring generates a faul
        const SMAP = 1 << 21
      , /// Protection Key Enable
        const PKE = 1 << 22
    }
}

impl fmt::LowerHex for Flags {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:#08x}", self.bits)
    }
}

cpu_flag! {
    doc="If disabled, the `RTDSC` instruction can only be executed in Ring 0.",
    TSD, is_timestamp_disabled, disable_timestamp
}


================================================
FILE: cpu/src/x86_all/control_regs/mod.rs
================================================
//
//  SOS: the Stupid Operating System
//  by Eliza Weisman (eliza@elizas.website)
//
//  Copyright (c) 2015-2017 Eliza Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! `x86` and `x86_64` control registers
#![warn(missing_docs)]
use core::fmt;

/// `%cr0` contains flags that modify basic processor operation.
pub mod cr0;

/// `%cr4` contains flags that control protected mode execution.
pub mod cr4;

/// A struct bundling together a snapshot of the control registers state.
#[derive(Copy,Clone,Debug)]
pub struct CrState { /// `%cr0` contains flags that control the CPU's operations
                     pub cr0: cr0::Flags
                   , /// `%cr2` contains the page fault linear address
                     pub cr2: usize
                   , /// `%cr3` contains the page table root pointer
                     ///
                     /// TODO: can this be rewritten as a pointer?
                     pub cr3: usize
                   , /// `%cr4` contains flags that control operations in
                     ///  protected mode
                     pub cr4: cr4::Flags
                   }

impl fmt::Display for CrState {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!( f, "CR0: {:#08x} CR2: {:#08x} CR3: {:#08x} CR4: {:#08x}"
                , self.cr0, self.cr2, self.cr3, self.cr4)
    }
}

/// Dump the current contents of the control registers to a `CrState`.
pub fn dump() -> CrState {
    let cr0_: usize; let cr2_: usize;
    let cr3_: usize; let cr4_: usize;
    unsafe {
        asm!(  "mov $0, cr0
                mov $1, cr2
                mov $2, cr3
                mov $3, cr4"
            :   "=r"(cr0_)
              , "=r"(cr2_)
              , "=r"(cr3_)
              , "=r"(cr4_)
            ::: "intel"
              , "volatile");
    }
    CrState { cr0: cr0::Flags::from_bits_truncate(cr0_)
            , cr2: cr2_, cr3: cr3_
            , cr4: cr4::Flags::from_bits_truncate(cr4_)
            }

}

/// `$cr2` contains the page fault linear address
pub mod cr2 {

    /// Read the current value from `$cr2`.
    ///
    /// # Safety
    /// + Reading from control registers while not in kernel mode will cause
    ///   a general protection fault.
    pub unsafe fn read() -> usize {
        let result: usize;
        asm!(   "mov $0, cr2"
            :   "=r"(result)
            ::: "intel" );
        result
    }

    /// Write a value to `$cr2`.
    ///
    /// # Safety
    /// + Control registers should generally not be modified during normal
    ///   operation.
    pub unsafe fn write(value: usize) {
        asm!(  "mov cr2, $0"
            :: "r"(value)
            :: "intel");
    }
}

/// `%cr3` contains the page table root pointer
pub mod cr3 {
    use memory::{PAddr, PhysicalPage};

    // #[cfg(target_arch = "x86_64")]
    // use paging::table::{Table, PML4Level};

    /// Read the current value from `$cr3`.
    ///
    /// # Safety
    /// + Reading from control registers while not in kernel mode will cause
    ///   a general protection fault.
    #[cfg(target_arch = "x86_64")]
    pub unsafe fn read() -> PAddr {
        let result: u64;
        asm!(   "mov $0, cr3"
            :   "=r"(result)
            ::: "intel" );
        PAddr::from(result)
    }

    /// Read the current value from `$cr3`.
    ///
    /// # Safety
    /// + Reading from control registers while not in kernel mode will cause
    ///   a general protection fault.
    #[cfg(target_arch = "x86")]
    pub unsafe fn read() -> PAddr {
        let result: u32;
        asm!(   "mov $0, cr3"
            :   "=r"(result)
            ::: "intel" );
        PAddr::from(result)
    }

    /// Write a value to `$cr3`.
    ///
    /// # Safety
    /// + Control registers should generally not be modified during normal
    ///   operation.
    #[cfg(target_arch = "x86_64")]
    pub unsafe fn write(addr: PAddr) {
        let value: u64 = addr.into();
        asm!(  "mov cr3, $0"
            :: "r"(value)
            :  "memory"
            :  "intel");
    }

    /// Write a value to `$cr3`.
    ///
    /// # Safety
    /// + Control registers should generally not be modified during normal
    ///   operation.
    #[cfg(target_arch = "x86")]
    pub unsafe fn write(addr: PAddr) {
        let value: u32 = addr.into();
        asm!(  "mov cr3, $0"
            :: "r"(value)
            :: "intel");
    }

    /// Returns the current Page Directory base frame.
    ///
    /// # Safety
    /// + Reading from control registers while not in kernel mode will cause
    ///   a general protection fault.
    pub unsafe fn current_pagetable_frame() -> PhysicalPage {
        PhysicalPage::containing_addr(read())
    }

    /// Returns the current Page Directory base frame.
    ///
    /// # Safety
    /// + Reading from control registers while not in kernel mode will cause
    ///   a general protection fault.
    #[inline]
    pub unsafe fn set_pagetable_frame(frame: PhysicalPage) {
        write(frame.base_addr())
    }
}


================================================
FILE: cpu/src/x86_all/dtable.rs
================================================
//
//  SOS: the Stupid Operating System
//  by Eliza Weisman (eliza@elizas.website)
//
//  Copyright (c) 2015-2017 Eliza Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//! `x86` and `x86_64` descriptor tables (IDT, GDT, or LDT)
//!
//! For more information, refer to the _Intel® 64 and IA-32 Architectures
//! Software Developer’s Manual_, Vol. 3A, section 3.2, "Using Segments", and
//! section 6.10, "Interrupt Descriptor Table (IDT)".

#![deny(missing_docs)]
// use memory::PAddr;
use core::mem::size_of;

/// A pointer to a descriptor table.
/// This is a format suitable
#[repr(C, packed)]
pub struct Pointer<T: DTable> { /// the length of the descriptor table
                     pub limit: u16
                   , /// pointer to the region in memory
                     /// containing the descriptor table.
                     pub base: *const T
                   }
unsafe impl<T: DTable> Sync for Pointer<T> { }
/// A descriptor table (IDT or GDT).
///
/// The IA32 architecture uses two descriptor table structures, the GDT
/// (Global Descriptor Table), which is used for configuring segmentation,
/// and the IDT (Interrupt Descriptor Table), which tells the CPU where
/// interrupt service routines are located.
///
/// As SOS relies on paging rather than segmentation for memory protection on
/// both 32-bit and 64-bit systems, we use the GDT only minimally. However, the
/// CPU still requires a correctly configured GDT to run in protected mode, even
/// if it is not actually used.
///
/// This trait specifies base functionality common to both types of descriptor
/// table.
pub trait DTable: Sized {
    /// The type of an entry in this descriptor table.
    ///
    /// For an IDT, these are
    /// interrupt [`Gate`](../interrupts/idt/gate/struct.Gate.html)s,
    /// while for a GDT or LDT, they are segment
    /// [`Descriptor`](../segment/struct.Descriptor.html)s.
    //  TODO: can there be a trait for DTable entries?
    //      - eliza, 10/06/2016
    type Entry: Sized;

    /// Get the IDT pointer struct to pass to `lidt` or `lgdt`
    ///
    /// This expects that the object implementing `DTable` not contain
    /// additional data before or after the actual `DTable`, if you wish
    /// to attach information to a descriptor table besides the array of
    /// entries that it consists of, it will be necessary to encose the
    /// descriptor table in another `struct` or `enum` type.
    //  TODO: can we have an associated `Entry` type + a function to get the
    //        number of entries in the DTable, instead? that way, we could
    //        calculate the limit using that information, allowing Rust code
    //        to place more variables after the array in the DTable structure.
    //
    //        If we wanted to be really clever, we could probably also have a
    //        method to get a pointer to a first entry (or enforce that the
    //        DTable supports indexing?) and then we could get a pointer only
    //        to the array segment of the DTable, while still allowing variables
    //        to be placed before/after the array.
    //
    //        I'm not sure if we actually want to support this – is there really
    //        a use-case for it? I suppose it would also make our size calc.
    //        more correct in case Rust ever puts additional data around a
    //        DTable rray, but I imagine it will probably never do that...
    //              – eliza, 06/03/2016
    //
    #[inline]
    fn get_ptr(&self) -> Pointer<Self> {
        Pointer {
            limit: (size_of::<Self::Entry>() * self.entry_count()) as u16
          , base: self as *const _
        }
    }

    /// Returns the number of Entries in the `DTable`.
    ///
    /// This is used for calculating the limit.
    fn entry_count(&self) -> usize;

    /// Load the descriptor table with the appropriate load instruction
    fn load(&'static self);
}


================================================
FILE: cpu/src/x86_all/flags.rs
================================================
//
//  SOS: the Stupid Operating System
//  by Eliza Weisman (eliza@elizas.website)
//
//  Copyright (c) 2015-2017 Eliza Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! Flags present in the `%eflags`/`%rflags` register on x86 CPUs.
use super::PrivilegeLevel;

bitflags! {
    /// Contents of the `%eflags`/`%rflags` register.
    ///
    /// Note that on early x86 systems, this is a 16-bit register (`%flags`),
    /// but we only support the 32-bit `%eflags` and 64-bit `%rflags`, since
    /// SOS is a protected mode/long mode OS only.
    pub flags Flags: usize {
        /// Carry flag
        const CF = 1 << 0
      , /// Parity flag
        const PF = 1 << 2
      , /// Adjust flag
        const AF = 1 << 4
      , /// Zero flag
        const ZF = 1 << 6
      , /// Sign flag
        const SF = 1 << 7
      , /// Trap flag (single step)
        ///
        /// If 1, IT'S A TRAP!
        const TF = 1 << 8
      , /// Interrupt enable flag
        const IF = 1 << 9
      , /// Direction flag
        const DF = 1 << 10
      , /// Overflow flag
        const OF = 1 << 11

      , const IOPL_RING_0 = 0 << 12
      , const IOPL_RING_1 = 1 << 12
      , const IOPL_RING_2 = 2 << 12
      , const IOPL_RING_3 = 3 << 12
      , /// I/0 Privilege Level
        ///
        /// This flag is always one on the 8086 and 186.
        const IOPL = IOPL_RING_0.bits | IOPL_RING_1.bits |
                     IOPL_RING_2.bits | IOPL_RING_3.bits

      , /// Nested task flag
        ///
        /// Always 1 on 8086 and 186s.
        const NT = 1 << 14

      , /// Should always be 1
        const RESERVED = 1 << 15

      , /// Resume flag
        ///
        /// Present on 386 and later.
        const RF = 1 << 16
      , /// Virtual 8086 Mode flag
        ///
        /// Of course, this is only present on 386 and later.
        const VM = 1 << 17
      , /// Alignment Check
        ///
        /// Present on 486SX and later.
        const AC = 1 << 18
      , /// Virtual Interrupt flag
        ///
        /// Present on Pentium and later.
        const VIF = 1 << 19
      , /// Virtual Interrupt Pending
        ///
        /// Present on Pentium and later.
        const VIP = 1 << 20
      , /// Able to use `CPUID` instruction.
        ///
        /// Present on Pentium and later.
        const ID = 1 << 21
    }
}

impl Flags {
    pub fn iopl(&self) -> PrivilegeLevel {
        use core::mem::transmute;
        let bits = (*self & IOPL).bits >> 12;
        unsafe { transmute(bits as u16) }
    }
}

/// Read the current value from `$eflags`/`%rflags`.
pub fn read() -> Flags {
    let result: usize;
    unsafe {
        asm!(   "pushf
                 pop $0"
            :   "=r"(result)
            ::: "intel" );
    }
    Flags { bits: result }
}


================================================
FILE: cpu/src/x86_all/interrupts/idt/gate32.rs
================================================
//
//  SOS: the Stupid Operating System
//  by Eliza Weisman (eliza@elizas.website)
//
//  Copyright (c) 2015-2017 Eliza Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! 32-bit IDT gate implementation
use ::segment;
use super::{GateFlags};
use super::super::{InterruptHandler, ErrorCodeHandler};
use core::mem::transmute;

extern {
    /// Offset of the 32-bit GDT main code segment.
    /// Exported by `boot.asm`
    #[link_name="gdt32_offset"]
    static GDT_OFFSET: u16;
}

/// An IDT entry is called a gate.
///
/// Based on [code](http://wiki.osdev.org/Interrupt_Descriptor_Table#Structure)
/// from the OS Dev Wiki.
#[repr(C, packed)]
#[derive(Copy,Clone, Default)]
pub struct Gate { /// bits 0 - 15 of the offset
                 pub offset_lower: u16
               , /// code segment selector (GDT or LDT)
                 pub selector: segment::Selector
               , /// always zero
                 _zero: u8
               , /// indicates the gate's type and attributes.
                 /// the second half indicates the type:
                 /// + `0b1100`: Call gate
                 /// + `0b1110`: Interrupt gate
                 /// + `0b1111`: Trap Gate
                 pub flags: GateFlags
               , /// bits 16 - 31 of the offset
                 pub offset_upper: u16
               }

impl GateFlags {

   /// Returns a new trap gate
   pub const fn new_trap() -> Self {
       GateFlags { bits: super::TRAP_GATE_16.bits | super::PRESENT.bits }
   }

   /// Returns a new interrupt gate
   pub const fn new_interrupt() -> Self {
       GateFlags { bits: super::INT_GATE_16.bits | super::PRESENT.bits }
   }

}

impl Gate {

   /// Creates a new IDT gate marked as `absent`.
   ///
   /// This is basically just for filling the new IDT table
   /// with valid (but useless) gates upon init.
   ///
   /// Actually triggering an absent interrupt will send a General Protection
   /// fault (13).
    pub const fn absent() -> Self {
       Gate { offset_lower: 0
            , selector: 0
            , _zero: 0
            , flags: GateFlags { bits: 0 }
            , offset_upper: 0
            }
    }

}

impl convert::From<ErrorCodeHandler> for Gate {

    /// Creates a new IDT gate pointing at the given handler function.
    ///
    /// The `handler` function must have been created with valid interrupt
    /// calling conventions.
    fn from(handler: ErrorCodeHandler) -> Self {
        unsafe {
            let (low, mid): (u16, u16) = mem::transmute(handler);

            Gate { offset_lower: low
                 , selector: segment::Selector::from_raw(GDT_OFFSET)
                 , _zero: 0
                 , type_attr: GateFlags::new_interrupt()
                 , offset_upper: high
                 , _reserved: 0
                 }
        }
    }
}

impl convert::From<InterruptHandler> for Gate {

    /// Creates a new IDT gate pointing at the given handler function.
    ///
    /// The `handler` function must have been created with valid interrupt
    /// calling conventions.
    fn from(handler: ErrorCodeHandler) -> Self {
        unsafe {
            let (low, mid): (u16, u16) = mem::transmute(handler);

            Gate { offset_lower: low
                 , selector: segment::Selector::from_raw(GDT_OFFSET)
                 , _zero: 0
                 , type_attr: GateFlags::new_interrupt()
                 , offset_upper: high
                 , _reserved: 0
                 }
        }
    }
}


================================================
FILE: cpu/src/x86_all/interrupts/idt/gate64.rs
================================================
//
//  SOS: the Stupid Operating System
//  by Eliza Weisman (eliza@elizas.website)
//
//  Copyright (c) 2015-2017 Eliza Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! 64-bit IDT gate implementation
use ::segment;
use super::{GateFlags};
use super::super::{InterruptHandler, ErrorCodeHandler};

use core::{convert, mem, ops};
use core::marker::PhantomData;

impl GateFlags {

    /// Returns a new trap gate
    pub const fn new_trap() -> Self {
        GateFlags { bits: super::TRAP_GATE_32.bits | super::PRESENT.bits }
    }

    /// Returns a new call gate
    pub const fn new_task() -> Self {
        GateFlags { bits: super::TASK_GATE_32.bits | super::PRESENT.bits }
    }

    /// Returns a new interrupt gate
    pub const fn new_interrupt() -> Self {
        GateFlags { bits: super::INT_GATE_32.bits | super::PRESENT.bits }
    }

}


/// An IDT entry is called a gate.
///
/// Based on [code](http://wiki.osdev.org/Interrupt_Descriptor_Table#Structure)
/// from the OS Dev Wiki.
///
/// Refer also to "6.14.1 64-Bit Mode IDT"  and "Table 3-2. System-Segment and
/// Gate-Descriptor Types" in the _Intel® 64 and IA-32 Architectures
/// Software Developer’s Manual_
#[repr(C, packed)]
#[derive(Copy, Clone)]
pub struct Gate<H = InterruptHandler>
    { /// bits 0 - 15 of the offset
      pub offset_lower: u16
    , /// code segment selector (GDT or LDT)
      pub selector: segment::Selector
    , /// always zero
      _zero: u8
    , /// indicates the gate's type and attributes.
      /// the second half indicates the type:
      ///   + `0b1100`: Call gate
      ///   + `0b1110`: Interrupt gate
      ///   + `0b1111`: Trap Gate
      pub flags: GateFlags
    , /// bits 16 - 31 of the offset
      pub offset_mid: u16
    , /// bits 32 - 63 of the offset
      pub offset_upper: u32
    , /// always zero (according to the spec, this is "reserved")
      _reserved: u32
    , _handler_type: PhantomData<H>
    }

impl<H> Gate<H> {

    /// Creates a new IDT gate marked as `absent`.
    ///
    /// This is basically just for filling the new IDT table
    /// with valid (but useless) gates upon init.
    ///
    /// Actually triggering an absent interrupt will send a General Protection
    /// fault (13).
    pub const fn absent() -> Self {
       Gate { offset_lower: 0
            , selector: segment::Selector::from_raw(0)
            , _zero: 0
            , flags: GateFlags { bits:  0b1000_1110 }
            , offset_mid: 0
            , offset_upper: 0
            , _reserved: 0
            , _handler_type: PhantomData
            }
    }

    /// Set the handler function corresponding to this gate.
    #[inline]
    pub fn set_handler<F>(&mut self, handler: F) -> &mut Self
    where Self: convert::From<F> {
        *self = Self::from(handler);
        self
    }

    /// Sets the TRAP GATE flag to true
    #[inline]
    pub fn set_trap(&mut self) -> &mut Self {
        self.flags.insert(super::TRAP_GATE_32);
        self
    }

}


impl<H> Default for Gate<H> {
    fn default() -> Self {
        Gate { offset_lower: 0
             , selector: segment::Selector::from_raw(0)
             , _zero: 0
             , flags: GateFlags { bits: 0b1000_1110 }
             , offset_mid: 0
             , offset_upper: 0
             , _reserved: 0
             , _handler_type: PhantomData
             }
    }
}

impl<H> ops::Deref for Gate<H> {
    type Target = GateFlags;

    #[inline] fn deref(&self) -> &Self::Target { &self.flags }
}

impl<H> ops::DerefMut for Gate<H> {
    #[inline] fn deref_mut(&mut self) -> &mut Self::Target { &mut self.flags }
}

impl convert::From<InterruptHandler> for Gate<InterruptHandler> {

    /// Creates a new IDT gate pointing at the given handler function.
    ///
    /// The `handler` function must have been created with valid interrupt
    /// calling conventions.
    fn from(handler: InterruptHandler) -> Self {
        unsafe { // trust me on this, `mem::transmute()` is glorious black magic
                let (low, mid, high): (u16, u16, u32) = mem::transmute(handler);

            Gate { offset_lower: low
                 , offset_mid: mid
                 , offset_upper: high
                 , selector: segment::Selector::from_cs()
                 , flags: GateFlags::new_interrupt()
                 , ..Default::default()
                 }
        }
    }
}

impl convert::From<ErrorCodeHandler> for Gate<ErrorCodeHandler> {

    /// Creates a new IDT gate pointing at the given handler function.
    ///
    /// The `handler` function must have been created with valid interrupt
    /// calling conventions.
    fn from(handler: ErrorCodeHandler) -> Self {
        unsafe { // trust me on this, `mem::transmute()` is glorious black magic
                let (low, mid, high): (u16, u16, u32) = mem::transmute(handler);

            Gate { offset_lower: low
                 , offset_mid: mid
                 , offset_upper: high
                 , selector: segment::Selector::from_cs()
                 , flags: GateFlags::new_interrupt()
                 , ..Default::default()
                 }
        }
    }
}

impl convert::From<*const u8> for Gate {

    /// Creates a new IDT gate pointing at the given handler function.
    ///
    /// The `handler` function must have been created with valid interrupt
    /// calling conventions.
    ///
    /// This should probably not be used, if it can possibly be avoided.
    //  TODO: it would be really nice if we didn't need this any more.
    //        after the Revolution, once handlers are created in Rust-land with
    //        naked functions...
    fn from(handler: *const u8) -> Self {
        unsafe {
            let (low, mid, high): (u16, u16, u32) = mem::transmute(handler);

            Gate { offset_lower: low
                 , offset_mid: mid
                 , offset_upper: high
                 , selector: segment::Selector::from_cs()
                 , flags: GateFlags::new_interrupt()
                 , ..Default::default()
                 }
        }
    }
}


================================================
FILE: cpu/src/x86_all/interrupts/idt/mod.rs
================================================
//
//  SOS: the Stupid Operating System
//  by Eliza Weisman (eliza@elizas.website)
//
//  Copyright (c) 2015-2017 Eliza Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! Common functionality for the `x86` and `x86_64` Interrupt Descriptor Table.
#![warn(missing_docs)]
use core::{mem, convert, ops};

use ::dtable::DTable;
use ::PrivilegeLevel;

/// Number of entries in the system's Interrupt Descriptor Table.
pub const ENTRIES: usize = 256;

#[cfg(test)] mod tests;

//==------------------------------------------------------------------------==
// IDT Gates
#[cfg(target_arch = "x86")]    #[path = "gate32.rs"] pub mod gate;
#[cfg(target_arch = "x86_64")] #[path = "gate64.rs"] pub mod gate;
pub use self::gate::*;

bitflags! {
    /// Bitflags field in an IDT gate.
    ///
    /// The structure of the flags field is as follows:
    ///
    /// ```ignore
    ///   7                           0
    /// +---+---+---+---+---+---+---+---+
    /// | P |  DPL  | S |    GateType   |
    /// +---+---+---+---+---+---+---+---+
    /// ```
    ///
    /// Fields have the following meanings:
    ///
    ///  + `P`: One bit, indicating if the ISR is present. Set to 0 for unused
    ///         interrupts.
    ///  + `DPL`: Two bits, indicating the escriptor's priveliege level as an
    ///           integer, with zero being Ring 0.
    ///  + `S`: One bit, set if the descriptor refers to an interrupt in the
    ///         storage segment.
    ///  + `GateType`: Four bits, indicating the type of the interrupt with the
    ///               following values (architecture-dependent):
    ///    - `0101`: 80386 32-bit task gate
    ///    - `0110`: 80286 16-bit interrupt gate
    ///    - `0111`: 80286 16-bit trap gate
    ///    - `1110`: 80386 32-bit interrupt gate
    ///    - `1111`: 80386 32-bit trap gate
    ///
    /// For more information, refer to the _Intel® 64 and IA-32 Architectures
    /// Software Developer’s Manual_, Vol. 3A, section 6.11, "IDT Descriptors";
    /// and to the OS Dev Wiki
    /// [article](http://wiki.osdev.org/Interrupts_Descriptor_Table)
    /// "Interrupts Descriptor Table".
    pub flags GateFlags: u8 {
        /// Set to 0 for unused interrupts.
        ///
        /// Indicates whether or not this gate is present.
        /// An interrupt on a non-present gate will trigger a
        /// General Protection Fault.
        const PRESENT       = 0b1000_0000

      , /// Bit indicating that the descriptor priveliege level is Ring 0
        const DPL_RING_0    = 0b0000_0000
      , /// Bit indicating that the descriptor priveliege level is Ring 1
        const DPL_RING_1    = 0b0010_0000
      , /// Bit indicating that the descriptor priveliege level is Ring 2
        const DPL_RING_2    = 0b0100_0000
      , /// Bit indicating that the descriptor priveliege level is Ring 3
        const DPL_RING_3    = 0b0110_0000
      , /// Descriptor priveliege level bitfield.
        const DPL           = DPL_RING_0.bits | DPL_RING_1.bits |
                              DPL_RING_2.bits | DPL_RING_3.bits

      , /// Storage segment flag.
        ///
        /// Set to 0 for interrupt gates.
        const SEGMENT       = 0b0001_0000
      , /// Set if this `Gate` points to a 32-bit ISR.
        const LONG_MODE     = 0b0000_1000

      , /// Set if this is an interrupt gate.
        const INT_GATE_16   = 0b0000_0110
      , /// Set if this is an interrupt gate and points to a 32-bit ISR.
        const INT_GATE_32   = INT_GATE_16.bits | LONG_MODE.bits
      , /// Set if this is a trap gate.
        const TRAP_GATE_16  = 0b0000_0111
      , /// Set if this is a trap gate that points to a 32-bit ISR
        const TRAP_GATE_32  = TRAP_GATE_16.bits | LONG_MODE.bits
      , /// Set if this is a 32-bit task gate.
        const TASK_GATE_32  = 0b0000_0101 | LONG_MODE.bits
    }
}

impl GateFlags {
    /// Returns true if this `Gate` is a trap gate
    #[inline] pub fn is_trap(&self) -> bool {
        self.contains(TRAP_GATE_16)
    }

    /// Returns true if this `Gate` points to a present ISR
    #[inline] pub fn is_present(&self) -> bool {
        self.contains(PRESENT)
    }

    /// Sets the present bit for this gate
    #[inline] pub fn set_present(&mut self, present: bool) -> &mut Self {
        if present { self.insert(PRESENT) }
        else { self.remove(PRESENT) }
        self
    }

    /// Checks the gate's privilege
    #[inline] pub fn get_dpl(&self) -> PrivilegeLevel {
        unsafe { mem::transmute((*self & DPL).bits as u16 >> 5) }
    }

    /// Sets the privilege level of the gate
    pub fn set_dpl(&mut self, dpl: PrivilegeLevel) -> &mut Self {
        self.insert(GateFlags::from_bits_truncate((dpl as u8) << 5));
        self
    }

}


impl Default for GateFlags {
    fn default() -> Self { GateFlags { bits: 0 } }
}

//==------------------------------------------------------------------------==
use super::ErrorCodeHandler;
//  IDT implementation
/// An Interrupt Descriptor Table
///
/// The IDT is either 64-bit or 32-bit.
#[repr(C)]
pub struct Idt {
    pub divide_by_zero: Gate
  , /// debug interrupt handler - reserved
    pub debug: Gate
  , pub nmi: Gate
  , pub breakpoint: Gate
  , pub overflow: Gate
  , pub bound_exceeded: Gate
  , pub undefined_opcode: Gate
  , pub device_not_available: Gate
  , pub double_fault: Gate<ErrorCodeHandler>
  , _coprocessor_segment_overrun: Gate<ErrorCodeHandler>
  , pub invalid_tss: Gate<ErrorCodeHandler>
  , pub segment_not_present: Gate<ErrorCodeHandler>
  , pub stack_segment_fault: Gate<ErrorCodeHandler>
  , pub general_protection_fault: Gate<ErrorCodeHandler>
  , pub page_fault: Gate<ErrorCodeHandler>
  , _reserved: Gate
  , pub floating_point_error: Gate
  , pub alignment_check: Gate<ErrorCodeHandler>
  , pub machine_check: Gate
  , pub simd_fp_exception: Gate
  , pub virtualization: Gate
  , _reserved_2: [Gate; 9]
  , pub security_exception: Gate<ErrorCodeHandler>
  , _reserved_3: Gate
  , /// user-defined interrupts
    pub interrupts: [Gate; ENTRIES - super::NUM_EXCEPTIONS]
}

impl Default for Idt {
    #[inline]
    fn default() -> Self {
        Idt {
            interrupts: [Default::default(); ENTRIES - super::NUM_EXCEPTIONS]
            , ..Default::default()
        }
    }
}

impl ops::Index<usize> for Idt {
    type Output = Gate;

    #[inline]
    fn index(&self, index: usize) -> &Gate {
        unsafe {
            &mem::transmute::<&Self, &[Gate; ENTRIES]>(self)[index]
        }
    }
}

impl ops::IndexMut<usize> for Idt {

    #[inline]
    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
        unsafe {
            &mut mem::transmute::<&mut Self, &mut [Gate; ENTRIES]>(self)[index]
        }
    }
}

impl Idt {

    /// Construct a new IDT with all interrupt gates set to [`absent`].
    ///
    /// [`absent`]: struct.Gate.absent.html
    pub const fn new() -> Self {
        Idt { divide_by_zero: Gate::absent()
            , debug: Gate::absent()
            , nmi: Gate::absent()
            , breakpoint: Gate::absent()
            , overflow: Gate::absent()
            , bound_exceeded: Gate::absent()
            , undefined_opcode: Gate::absent()
            , device_not_available: Gate::absent()
            , double_fault: Gate::absent()
            , _coprocessor_segment_overrun: Gate::absent()
            , invalid_tss: Gate::absent()
            , segment_not_present: Gate::absent()
            , stack_segment_fault: Gate::absent()
            , general_protection_fault: Gate::absent()
            , page_fault: Gate::absent()
            , _reserved: Gate::absent()
            , floating_point_error: Gate::absent()
            , alignment_check: Gate::absent()
            , machine_check: Gate::absent()
            , simd_fp_exception: Gate::absent()
            , virtualization: Gate::absent()
            , _reserved_2: [Gate::absent(); 9]
            , security_exception: Gate::absent()
            , _reserved_3: Gate::absent()
            , interrupts: [Gate::absent(); ENTRIES - super::NUM_EXCEPTIONS]
            }
    }

    /// Enable interrupts
    pub unsafe fn enable_interrupts() { asm!("sti") }
    /// Disable interrupts
    pub unsafe fn disable_interrupts() { asm!("cli") }

    /// Add a new interrupt gate pointing to the given handler
    #[inline]
    pub fn add_handler<Handler>( &mut self
                               , idx: usize
                               , handler: Handler)
                               -> &mut Self
    where Gate: convert::From<Handler> {
        self.add_gate(idx, Gate::from(handler))
    }

    /// Add a [`Gate`](struct.Gate.html) to the IDT.
    #[inline]
    pub fn add_gate(&mut self, idx: usize, gate: Gate) -> &mut Self {
        self[idx] = gate;
        self
    }

}

impl DTable for Idt {
    type Entry = Gate;

    #[inline] fn entry_count(&self) -> usize { ENTRIES }

    #[inline] fn load(&'static self) {
        unsafe {
            asm!(  "lidt ($0)"
                :: "r"(&self.get_ptr())
                :  "memory" );
        }
        kinfoln!(dots: " . . ", target: "Loading IDT", "[ OKAY ]");
    }
}


================================================
FILE: cpu/src/x86_all/interrupts/idt/tests.rs
================================================
#[test] fn test_task_gate_32() { assert_eq!(super::TASK_GATE_32.bits, 5)}
#[test] fn test_int_gate_32() { assert_eq!(super::INT_GATE_32.bits, 14)}

#[test] fn test_trap_gate_32() { assert_eq!(super::TRAP_GATE_32.bits, 16)}


================================================
FILE: cpu/src/x86_all/interrupts/mod.rs
================================================
//
//  SOS: the Stupid Operating System
//  by Eliza Weisman (eliza@elizas.website)
//
//  Copyright (c) 2015-2017 Eliza Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! Intterupt handling on x86 machines.
//!
//! This module provides support for interrupt handling on both `x86` and
//! `x86_64` as a black box. Code that depends on this can use the same API
//! regardless of system word size.
#![warn(missing_docs)]
pub mod idt;
pub mod pics;

use vga::{CONSOLE, Color};

use core::fmt;
use core::fmt::Write;

use context::InterruptFrame;

/// Number of interrupt vectors corresponding to CPU exceptions.
///
/// These are the first 32 vectors in the IDT.
pub const NUM_EXCEPTIONS: usize = 32;

/// An ISR that handles a regular interrupt
pub type InterruptHandler = extern "x86-interrupt" fn (&InterruptFrame);
/// An ISR that handles an error with an error code
pub type ErrorCodeHandler = extern "x86-interrupt" fn (&InterruptFrame, usize);

/// A description of a CPU exception
#[derive(Debug)]
pub struct ExceptionInfo { /// The name of the exception
                           pub name: &'static str
                         , /// The mnemomic code for the exception
                           pub mnemonic: &'static str
                         , /// The type of IRQ for this exception
                           /// - fault
                           /// - trap
                           /// - interrupt
                           pub irq_type: &'static str
                         , /// The source triggering the exception.
                           ///
                           /// Typically this refers to what opcode(s) can
                           /// cause this exception.
                           pub source: &'static str
                         }

bitflags! {
   flags PageFaultErrorCode: u32 {
       /// If 1, the error was caused by a page that was present.
       /// Otherwise, the page was non-present.
       const PRESENT = 1 << 0
     , /// If 1, the error was caused by a read. If 0, the cause was a write.
       const READ_WRITE = 1 << 1
     , /// If 1, the error was caused during user-mode execution.
       /// If 0, the processor was in kernel mode.
       const USER_MODE = 1 << 2
     , /// If 1, the fault was caused by reserved bits set to 1 during a fetch.
       const RESERVED = 1 << 3
     , /// If 1, the fault was caused during an instruction fetch.
       const INST_FETCH = 1 << 4
     , /// If 1, there was a protection key violation.
       const PROTECTION = 1 << 5
   }
}

impl fmt::Display for PageFaultErrorCode {
   fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
       write!( f, "Caused by {}{}{} during a {}{} executing in {} mode."
             , if self.contains(PRESENT) { "a present page" }
               else { "a non-present page" }
             , if self.contains(PROTECTION) { " protection-key violation" }
               else { "" }
             , if self.contains(RESERVED) { " reserved bits set to one "}
               else { "" }
             , if self.contains(READ_WRITE) { "read" } else { "write" }
             , if self.contains(INST_FETCH) { " in an instruction fetch"}
               else { "" }
             , if self.contains(USER_MODE) { "user" } else { "kernel" }            )
   }
}

/// Handler for the system timer interrupt
pub extern "x86-interrupt" fn timer(_frame: &InterruptFrame) {
    // do nothing, just signal the pics to end the IRQ
    // println!("timer!");
    unsafe { pics::end_pic_interrupt(0x20); }
}



/// Handles page fault exceptions
#[no_mangle] #[inline(never)]
pub extern "x86-interrupt" fn page_fault( frame: &InterruptFrame, error_code: usize) {
   let _ = write!( CONSOLE.lock()
                      .set_colors(Color::White, Color::Blue)
                   //   .clear()
             , "IT'S NOT MY FAULT: Page Fault at {:p} \
                \nError code: {:#x}\n\n{}\n{:?}"
             , (*frame).rip
             , error_code
             , PageFaultErrorCode::from_bits_truncate(error_code as u32)
             , *frame
             );
   // TODO: stack dumps please

   loop { }
}

/// Test interrupt handler for ensuring that the IDT is configured correctly.
#[no_mangle] #[inline(never)]
pub extern "x86-interrupt" fn test(_frame: &InterruptFrame) {
   // assert_eq!(state.int_id, 0x80);
   kinfoln!(dots: " . . ", target: "Testing interrupt handling:", "[ OKAY ]");
   // send the PICs the end interrupt signal
   unsafe {
       pics::end_pic_interrupt(0xff);
   }
}


================================================
FILE: cpu/src/x86_all/interrupts/pics.rs
================================================
//
//  SOS: the Stupid Operating System
//  by Eliza Weisman (eliza@elizas.website)
//
//  Copyright (c) 2015-2017 Eliza Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! Support for the 8259 Programmable Interrupt Controller.
//!
//! The 8259 PIC controls all of our IO IRQs. The PIC recieves IRQ requests
//! and feeds them to the CPU in order. An x86 system typically has two PICs,
//! PIC1 and PIC2, each of which provides 8 IRQs. Two PICs provide us with 15
//! unique IRQs, because one interrupt on the leader PIC is linked to interrupts
//! on the follower PIC.
//!
//! Mistakes were made, and Intel boneheadedly decided that it was a good idea
//! to map the vector offset of PIC1 to 8, so that it maps to interrupts
//! 8 ... 15 in the IDT. This conflicts with some of the interrupt numbers
//! used by CPU exceptions. Therefore, we must remap the PIC vectors so that
//! PIC1 starts at 32 and PIC2 at 40.

use Port;
use spin::Mutex;

use core::mem::transmute;

/// Starting offset for PIC1
const OFFSET: u8 = 0x20;
/// Command port for the follower PIC (PIC2)
const FOLLOWER_CMD_PORT: u16 = 0xA0;
/// Command port for the leader PIC (PIC1)
const LEADER_CMD_PORT: u16 = OFFSET as u16;

/// Commands to send to the PIC
#[repr(u8)]
#[derive(Eq, PartialEq, Ord, PartialOrd, Copy, Clone)]
enum Command { /// Command to set the PIC to 8086 mode
               Mode8086 = 0x01
             , /// Command to initialize a PIC
               Init     = 0x11
             , /// Command that ends an interrupt request
               EndIRQ   = 0x20
             , /// Command to read the Interrupt Request Register
               ReadIRR  = 0x0a
             , /// Command to read the Interrupt Service Register
               ReadISR  = 0x0b
             }

/// List of IRQs on the x86.
///
/// See [here](https://en.wikibooks.org/wiki/X86_Assembly/Programmable_Interrupt_Controller) for more info.
#[repr(u8)]
#[derive(Eq, PartialEq, Ord, PartialOrd, Copy, Clone)]
pub enum IRQ { /// System timer IRQ
               Timer        = OFFSET
             , /// PS/2 keyboard controller
               PS2Keyboard  = 1 + OFFSET
             , /// PIC2 cascade IRQ
               Cascade      = 2 + OFFSET
             , /// COM2 serial port
               COM2         = 3 + OFFSET
             , /// COM1 serial port
               COM1         = 4 + OFFSET
             , /// Line printer 2
               LPT2         = 5 + OFFSET
             , /// Floppy disc controller
               Floppy       = 6 + OFFSET
             , /// Line printer 1
               LPT1         = 7 + OFFSET
             , /// CMOS clock
               RTCTimer     = 8 + OFFSET
             , /// PS/2 mouse controller
               PS2Mouse     = 12 + OFFSET
             , /// Floating-point Coprocessor
               FPU          = 13 + OFFSET
             , /// ATA channel 1
               PrimaryATA   = 14 + OFFSET
             , /// ATA channel 2
               SecondaryATA = 15 + OFFSET
             }


/// A 8259 Programmable Interrupt Controller.
pub struct PIC {
    /// The base offset to which interrupts on this PIC are mapped
    offset: u8
  , /// The port on the CPU that sends commands to this PIC.
    command_port: Port<u8>
  , /// The port that sends and recieves data from the PIC
    data_port: Port<u8>
}

impl PIC {

    /// Construct a new leader PIC
    pub const fn leader() -> PIC {
        PIC { offset: OFFSET
            , command_port: Port::<u8>::new(LEADER_CMD_PORT)
            , data_port: Port::<u8>::new(LEADER_CMD_PORT + 1)
            }
    }

    /// Construct a new follower PIC
    pub const fn follower() -> PIC {
        PIC { offset: OFFSET + 8
            , command_port: Port::<u8>::new(FOLLOWER_CMD_PORT)
            , data_port: Port::<u8>::new(FOLLOWER_CMD_PORT + 1)
            }
    }

    /// Returns true if this PIC is the leader PIC
    #[inline]
    pub fn is_leader(&self) -> bool {
        self.offset == OFFSET
    }

    /// Send a command to the PIC
    #[inline]
    fn send_command(&self, command: Command) {
        self.command_port
            .write(command as u8)
    }

    /// Send a byte of data to the PIC
    #[inline]
    pub fn send_data(&self, data: u8) {
        self.data_port
            .write(data)
    }

    /// Send the "initialize" command to this PIC
    #[inline]
    pub fn initialize(&self) {
         self.send_command(Command::Init)
    }

    /// Read the contents of the ISR (Interrupt Service Register) from this PIC
    #[inline]
    pub fn read_isr(&self) -> u8 {
            self.send_command(Command::ReadISR);
            self.data_port.read()
    }

/// Read the contents of the IRR (Interrupt Request Register) from this PIC
    #[inline]
    pub fn read_irr(&self) -> u8 {
        self.send_command(Command::ReadIRR);
        self.data_port.read()
    }

}

/// Trait for something which is capable of handling a PIC IRQ
trait IRQHandler {
    /// Returns whether or not this handler handles the given IRQ
    fn handles(&self, irq: IRQ) -> bool;
    /// End an interrupt request
    fn end_interrupt(&self, irq: IRQ);
}

impl IRQHandler for PIC {

    fn handles(&self, irq: IRQ) -> bool {
        self.offset <= (irq as u8) && (irq as u8) < self.offset + 8
    }

    fn end_interrupt(&self, _: IRQ) {
        let _ = self.send_command(Command::EndIRQ);
    }
}

/// A pair of PICs in cascade mode.
///
/// This is the standard configuration on all modern x86 systems.
struct BothPICs (PIC, PIC);

impl BothPICs {

    /// Constructs the system's pair of PICs
    const fn new() -> Self {
        BothPICs (PIC::leader(), PIC::follower())
    }

    /// Initialize the system's PICs.
    pub unsafe fn initialize(&mut self) {
        let wait_port = Port::<u8>::new(0x80);
        let wait = || { wait_port.write(0); };
        // helper macro to avoid writing repetitive code
        macro_rules! send {
            (pic0 => $data:expr) => {
                self.0.send_data($data);
                wait();
            };
            (pic1 => $data:expr) => {
                self.1.send_data($data);
                wait();
            };
        }

        // Read the default interrupt masks from PIC1 and PIC2
        let (saved_mask1, saved_mask2)
            = (self.0.data_port.read(), self.1.data_port.read());

        // Send both PICs the 'initialize' command.
        self.0.initialize(); wait();
        self.1.initialize(); wait();

        // Each PIC then expects us to send it the following:
        // 1. the PIC's new vector offset
        send!(pic0 => self.0.offset);
        send!(pic1 => self.1.offset);
        // 2. number to configure PIC cascading
        send!(pic0 => 0x04);
        send!(pic1 => 0x02);
        // 3. command for 8086 mode
        send!(pic0 => Command::Mode8086 as u8);
        send!(pic1 => Command::Mode8086 as u8);
        // 4. finally, the mask we saved earlier
        send!(pic0 => saved_mask1);
        send!(pic1 => saved_mask2);
    }
}

impl IRQHandler for BothPICs {

    fn handles(&self, irq: IRQ) -> bool {
        self.0.handles(irq) ||
        self.1.handles(irq)
    }

    fn end_interrupt(&self, irq: IRQ) {
        if self.1.handles(irq) {
            self.1.end_interrupt(irq);
        }
        self.0.end_interrupt(irq);
    }

}

/// Global PIC instance and mutex
static PICS: Mutex<BothPICs>
    = Mutex::new(BothPICs::new());

/// Initialize the system's Programmable Interrupt Controller
///
/// # Safety
///  - This should only ever be called by the kernel boot process.
///    Initializing the PICs once they have already been inicialized
///    will probably cause Bad Things to take place.
pub unsafe fn initialize() {
    PICS.lock()
        .initialize();
    kinfoln!(dots: " . . ", target: "Initializing PICs", "[ OKAY ]");

}

/// If an interrupt is being handled by the PICs, end that interrupt.
///
/// This is called by the interrupt handler at the end of all interrupts.
/// If the interrupt is not a PIC interrupt, it silently does nothing.
///
/// # Safety
///  - This should only be called by interrupt handler functions.
pub unsafe fn end_pic_interrupt(interrupt_id: u8) {
    let pics = PICS.lock();
    let irq: IRQ = transmute(interrupt_id);

    if pics.handles(irq) {
        pics.end_interrupt(irq)
    }
}


================================================
FILE: cpu/src/x86_all/mod.rs
================================================
//
//  SOS: the Stupid Operating System
//  by Eliza Weisman (eliza@elizas.website)
//
//  Copyright (c) 2015-2017 Eliza Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! Common functionality for `x86` and `x86_64` CPUs
//!
//! Note that while we support both the `x86` and `x86_64` platforms,
//! we only support 32-bit `x86` machines. SOS is a protected mode or
//! long mode OS, and will not run on early x86 machines such as 286s.
use util::{io, Void};

macro_rules! cpu_flag {
    ($doc:meta, $flag:ident, $get:ident, $set:ident) => {
        #[$doc]
        pub unsafe fn $get() -> bool {
            read().contains($flag)
        }
        #[$doc]
        pub unsafe fn $set(set: bool) {
            let mut flags: Flags = read();
            if set {
                flags.insert($flag);
            } else {
                flags.remove($flag);
            }
            write(flags)
        }
    };
    ($doc:meta, $flag:ident, $get:ident) => {
        #[$doc]
        pub unsafe fn $get() -> bool {
            read().contains($flag)
        }
    }
}

pub mod control_regs;
pub mod segment;
pub mod dtable;
pub mod flags;
pub mod timer;
pub mod interrupts;

/// Represents an x86 privilege level.
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Ord, Eq)]
#[repr(u16)]
pub enum PrivilegeLevel { /// Ring 0 is the most privileged ring
                          KernelMode = 0
                        , Ring1 = 1
                        , Ring2 = 2
                        , /// Ring 3 is the least privileged ring
                          UserMode = 3

}

impl PrivilegeLevel {
    /// Returns the current I/O Privilege Level from `%eflags`/`%rflags`.
    #[inline] pub fn current_iopl() -> Self { flags::read().iopl() }
}

pub struct UnsafePort(u16);

impl UnsafePort {

    pub const unsafe fn new(number: u16) -> UnsafePort { UnsafePort(number) }

    /// Read a byte (8 bits) from this port
    pub unsafe fn in8(&self) -> u8 {
        let result: u8;
        asm!(  "in al, dx"
            :  "={al}"(result)
            :  "{dx}"(self.0)
            :: "intel"
             , "volatile" );
        result
    }
    /// Read a word (16 bits) from this port
    pub unsafe fn in16(&self) -> u16 {
        let result: u16;
        asm!(  "in ax, dx"
            :  "={ax}"(result)
            :  "{dx}"(self.0)
            :: "intel"
             , "volatile" );
        result
    }

    /// Read a long word (32 bits) from this port
    pub unsafe fn in32(&self) -> u32 {
        let result: u32;
        asm!(  "in eax, dx"
            :  "={eax}"(result)
            :  "{dx}"(self.0)
            :: "intel"
             , "volatile" );
        result
    }

    pub unsafe fn out8(&self, value: u8) {
         asm!(  "out dx, al"
             :: "{dx}"(self.0)
              , "{al}"(value)
             :: "intel"
              , "volatile" );
    }

    pub unsafe fn out16(&self, value: u16) {
         asm!(  "out dx, ax"
             :: "{dx}"(self.0)
              , "{ax}"(value)
             :: "intel"
              , "volatile" );
    }

    pub unsafe fn out32(&self, value: u32) {
         asm!(  "out dx, eax"
             :: "{dx}"(self.0)
              , "{eax}"(value)
             :: "intel"
              , "volatile" );
    }
}


impl io::Read for UnsafePort {
    type Error = Void;

    /// Reads a single byte into the given buffer
    fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
        unsafe {
            Ok(match &mut *buf {
                // if the length of the buffer is 0, then obviously
                // no bytes were read
                &mut []                  => 0
                // otherwise, read one byte into the head of the buffer
              , &mut [ref mut head, _..] => { *head = self.in8(); 1 }
            })
        }
    }

    /// Reads a new byte into each position in the buffer.
    fn read_all(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
        let mut read_bytes = 0;
        for idx in buf.iter_mut() {
            // for each index in the buffer, read another byte from the port
            unsafe { *idx = self.in8(); }
            // and increment the number of bytes read (this should be faster
            // than calling `buf.len()` later; as we only need 1 loop)
            read_bytes += 1;
        }
        Ok(read_bytes)
    }

}

impl io::Write for UnsafePort {
    type Error = Void;

    fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
        let mut written_bytes = 0;
        for byte in buf {
            // write each byte in the buffer to the port
            unsafe { self.out8(*byte); }
            // and increment the number of bytes written (this should be faster
            // than calling `buf.len()` later; as we only need 1 loop)
            written_bytes += 1;
        }
        Ok(written_bytes)
    }
}


================================================
FILE: cpu/src/x86_all/segment.rs
================================================
//
//  SOS: the Stupid Operating System
//  by Eliza Weisman (eliza@elizas.website)
//
//  Copyright (c) 2016 Eliza Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! Code for using the `x86` and `x86_64` segmentation hardware.
//!
//! For more information, refer to the _Intel® 64 and IA-32 Architectures
//! Software Developer’s Manual_, Vol. 3A, section 3.2, "Using Segments".
//! Some of the documentation present in this module was taken from the Intel
//! manual.
//!

// because some extern types have bitflags members, which cannot
// be marked repr(C) but should compile down to an unsigned integer
#![allow(improper_ctypes)]
#![deny(missing_docs)]

use core::{fmt, mem};
use super::{PrivilegeLevel, dtable};
/// The number of entries in the GDT
#[cfg(target_arch = "x86_64")]
pub const GDT_SIZE: usize = 2;

/// Structure representing a Global Descriptor Table
#[cfg(target_arch = "x86_64")]
#[repr(C, packed)]
pub struct Gdt { _null: Descriptor
               , /// The code segment descriptor
                 pub code: Descriptor
            //    , /// The data segment descriptor
            //      pub data: Descriptor
               }

/// The number of entries in the GDT
#[cfg(target_arch = "x86")]
pub const GDT_SIZE: usize = 512;

#[cfg(target_arch = "x86")]
pub type Gdt = [Descriptor; GDT_SIZE];

impl dtable::DTable for Gdt {
    type Entry = Descriptor;

    /// Returns the number of Entries in the `DTable`.
    ///
    /// This is used for calculating the limit.
    #[inline(always)] fn entry_count(&self) -> usize { GDT_SIZE }

    /// Load the GDT table with the `lgdt` instruction.
    #[inline] fn load(&self) {
        unsafe {
            asm!(  "lgdt ($0)"
            :: "r"(&self.get_ptr())
            :  "memory" );
        }
    }
}


extern {

    /// A Global Descriptor Table (GDT)
    ///
    /// This is used for configuring segmentation. Since we use paging rather than
    /// segmentation for memory protection, we never actually _use_ the GDT, but
    /// x86 requires that it be properly configured nonetheless. So, here it is.
    #[cfg(target_arch = "x86_64")]
    #[link_section = ".gdt64"]
    pub static GDT: Gdt;
}

bitflags! {
    /// A segment selector is a 16-bit identifier for a segment.
    ///
    /// It does not point directly to the segment, but instead points to the
    /// segment descriptor that defines the segment.
    ///
    /// A segment selector contains the following items:
    ///
    /// + *Requested Privilege Level (RPL)*: bits 0 and 1.
    ///    Specifies the privelege level of the selector.
    /// + *Table Indicator*: bit 2. Specifies which descriptor table to use.
    /// + *Index*: bits 3 through 15. Selects one of 8192 descriptors in the
    ///    GDT or LDT. The processor multiplies the index value by 8 (the number
    ///    of bytes in a segment descriptor) and adds the result to the base
    ///    address of the GDT or LDT (from the `%gdtr` or `%ldtr` register,
    ///    respectively).
    #[repr(C)]
    pub flags Selector: u16 { /// Set if the RPL is in Ring 0
                              const RPL_RING_0 = 0b00
                            , /// Set if the RPL is in Ring 1
                              const RPL_RING_1 = 0b01
                            , /// Set if the RPL is in Ring 2
                              const RPL_RING_2 = 0b10
                            , /// Set if the RPL is in Ring 3
                              const RPL_RING_3 = 0b11

                            , /// Requested Privelege Level (RPL) bits
                              const RPL = RPL_RING_0.bits
                                        | RPL_RING_1.bits
                                        | RPL_RING_2.bits
                                        | RPL_RING_3.bits

                            , /// If the Table Indicator (TI) is 0, use the GDT
                              const TI_GDT = 0 << 3

                            , /// If the TI is 1, use the LDT
                              const TI_LDT = 1 << 3
                            }
}

impl Selector {
    /// Create a new `Selector`
    ///
    /// # Arguments
    ///   - `index`: the index in the GDT or LDT
    pub const fn new(index: u16) -> Self {
        Selector { bits: index << 3 }
    }

    /// Create a new `Selector` from raw bits
    pub const fn from_raw(bits: u16) -> Self {
        Selector { bits: bits }
    }

    /// Returns the current value of the code segment register.
    pub fn from_cs() -> Self {
        let cs: u16;
        unsafe {
            asm!( "mov $0, cs"
                : "=r"(cs)
                ::: "intel" )
        };
        Selector::from_bits_truncate(cs)
    }

    /// Extracts the index from a segment selector
    #[inline] pub fn index(&self) -> u16 {
        self.bits >> 3
    }

    /// Sets this segment selector to be a GDT segment.
    ///
    /// If the segment is already a GDT segment, this will quietly do nothing.
    #[inline] pub fn set_global(&mut self) -> &mut Self {
        self.remove(TI_LDT);
        self
    }

    /// Sets this segment selector to be an LDT segment.
    ///
    /// If the segment is already an LDT segment, this will quietly do nothing.
    #[inline] pub fn set_local(&mut self) -> &mut Self {
        self.insert(TI_GDT);
        self
    }

    /// Sets the Requested Priveliege Level (RPL)
    ///
    /// The RPL must be in the range between 0 and 3.
    #[inline] pub fn set_rpl(&mut self, rpl: PrivilegeLevel) -> &mut Self {
        self.bits &= rpl as u16;
        self
    }

    /// Checks the segment's privelige.
    #[inline] pub fn get_rpl(&self) -> PrivilegeLevel {
        unsafe { mem::transmute(*self & RPL) }
    }


    /// Load this selector into the stack segment register (`ss`).
    pub unsafe fn load_ss(&self) {
        asm!(  "mov ss, $0"
            :: "r"(self.bits)
            :  "memory"
            :  "intel");
    }

    /// Load this selector into the data segment register (`ds`).
    pub unsafe fn load_ds(&self) {
        asm!(  "mov ds, $0"
            :: "r"(self.bits)
            :  "memory"
            :  "intel");
    }

    /// Load this selector into the `es` segment register.
    pub unsafe fn load_es(&self) {
        asm!(  "mov es, $0"
            :: "r"(self.bits)
            :  "memory"
            :  "intel");
    }

    /// Load this selector into the `fs` segment register.
    pub unsafe fn load_fs(&self) {
        asm!(  "mov fs, $0"
            :: "r"(self.bits)
            :  "memory"
            :  "intel");
    }

    /// Load this selector into the `gs` segment register.
    pub unsafe fn load_gs(&self) {
        asm!(  "mov gs, $0"
            :: "r"(self.bits)
            :  "memory"
            :  "intel");
    }


    /// Load this selector into the code segment register.
    ///
    /// N.B. that as we cannot `mov` directly to `cs`, we have to do this
    /// differently. We push the selector and return value onto the stack,
    /// and use `lret` to reload `cs`.
    #[cfg(target_arch = "x86_64")]
    pub unsafe fn load_cs(&self) {
        asm!(  "push $0
                lea rax, [rip + 1]
                push rax
                iret
                1:"
            :: "r"(self.bits as u64)
            :  "rax", "memory"
            :  "intel");
    }

}


impl Default for Selector {
    #[inline] fn default() -> Self { Selector::from_cs() }
}

impl fmt::Display for Selector {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        // TODO: this could be much less ugly.
        let ring = if self.contains(RPL_RING_3) { "3" }
                   else if self.contains(RPL_RING_2) { "2" }
                   else if self.contains(RPL_RING_1) { "1" }
                   else if self.contains(RPL_RING_0) { "0" }
                   else { unreachable!() };
        let table = if self.contains(TI_GDT) { "GDT" }
                    else { "LDT" };
        write!(f, "{}[{}], Ring {}", table, self.index(), ring)
    }
}

/// A segment descriptor is an entry in an IDT or GDT.
///
/// A segment descriptor is a data structure in a GDT or LDT that provides the
/// processor with the size and location of a segment, as well as access control
/// and status information. Segment descriptors are typically created by
/// compilers, linkers, loaders, or the operating system or executive, but not
/// application programs.
///
#[repr(C, packed)]
pub struct Descriptor { /// The last 8 bits of the base address
                        pub base_high: u8
                      , /// The next 16 bits are bitflags
                        pub flags: Flags
                      , /// The middle 8 bits of the base address
                        pub base_mid: u8
                      , /// The first 16 bits of the base address
                        pub base_low: u16
                      , /// the segment limit
                        pub limit: u16
                      }

impl Descriptor {

    /// Constructs a new null `Descriptor`
    pub const fn null() -> Self {
        Descriptor { base_high: 0
                   , flags: Flags::null()
                   , base_mid: 0
                   , base_low: 0
                   , limit: 0
                   }
    }

    /// Constructs a new `Descriptor` from a `limit` and a `base` address
    pub fn new(base: u32, limit: u32) -> Self {
        let (hi, mid, lo): (u8, u8, u16) = unsafe { mem::transmute(base) };
        let (limit_lo, limit_hi): (u16, u16) = unsafe { mem::transmute(limit) };
        // I hope this is right...
        let flags = (limit_hi & 0b1111) << 8;

        Descriptor { base_high: hi
                   , flags: Flags::from_bits_truncate(flags)
                   , base_mid: mid
                   , base_low: lo
                   , limit: limit_lo
                   }
    }

    /// Extract the limit part from the flags and limit fields.
    #[inline]
    pub fn get_limit(&self) -> u32 {
        // TODO: i hope this is right...
        self.flags.get_limit_part() & self.limit as u32
    }

}

impl Default for Descriptor {
    #[inline] fn default() -> Self { Descriptor::null() }
}

bitflags! {
    /// Segment descriptor bitflags field.
    ///
    /// Some of the bitflags vary based on the type of segment. Currently
    /// the API for this is a bit of a mess.
    pub flags Flags: u16 {
        /// 1 if this is a code or data segment that has been accessed
        const CODE_DATA_ACC = 1 << 0
      , /// Four bits that indcate the type of the segment
        const SEGMENT_TYPE  = 0b0000_0000_0000_1111
      , /// 1 if this is a data/code segment, 0 if this is a system segment
        const DESCR_TYPE    = 1 << 4
      , /// Two bits indicating the descriptor priveliege level
        const DPL           = 0b0000_0000_0110_0000
      , /// 1 if this segment is present.
        const PRESENT       = 1 << 7
      , /// bits 16...19 of the limit
        const LIMIT         = 0b0000_1111_0000_0000
      , /// 1 if this segment is available for use by system software
        const AVAILABLE     = 1 << 12
      , /// 0 if this is a 16- or 32-bit segment, 1 if it is a 64-bit segment
        const LENGTH        = 1 << 13
      , /// 0 if this is a 16-bit segment, 1 if it is a 32-bit segment
        const DEFAULT_SIZE  = 1 << 14
      , /// 0 if the limit of this segment is given in bytes, 1 if it is given
        /// in 4092-byte pages
        const GRANULARITY   = 1 << 15
      , /// If this is a code or data segment and the accessed bit is set,
        /// it has been accessed.
        const ACCESSED      = DESCR_TYPE.bits & CODE_DATA_ACC.bits
    }
}

impl Flags {

    /// Returns a new set of `Flag`s with all bits set to 0.
    pub const fn null() -> Self {
        Flags { bits: 0 }
    }

    /// Returns a new set of `Flag`s from a raw `u16`
    pub const fn from_raw(bits: u16) -> Self {
        Flags { bits: bits }
    }

    /// Get the Descriptor Privilege Level (DPL) from the flags
    #[inline] pub fn get_dpl(&self) -> PrivilegeLevel {
        unsafe { mem::transmute((*self & DPL).bits >> 5) }
    }

    /// Returns true if this segment is a system segment.
    ///
    /// Returns false if it is a code or data segment.
    #[inline] pub fn is_system(&self) -> bool {
        !self.contains(DESCR_TYPE)
    }

    /// Returns false if this segment is present
    #[inline] pub fn is_present(&self) -> bool {
        !self.contains(PRESENT)
    }

    /// Returns false if this segment is available to system software
    #[inline] pub fn is_available(&self) -> bool {
        self.contains(AVAILABLE)
    }

    /// Returns true if this is a code or data segment that has been accessed.
    ///
    /// Returns false if it has not been accessed OR if it is a system segment.
    #[inline] pub fn is_accessed(&self) -> bool {
        self.contains(ACCESSED)
    }

    /// Returns the system type indicator, if this is a system segment.
    ///
    /// # Returns
    /// + `Some(SysType)` if this is a system segment
    /// + `None` if this is a code or data segment
    pub fn get_system_type(&self) -> Option<SysType> {
        if self.is_system() {
            Some(unsafe { mem::transmute((*self & SEGMENT_TYPE).bits) })
        } else {
            None
        }
    }

    /// Returns the code type indicator.
    ///
    /// # Returns
    /// + `Some(CodeType)` if this is not a system segment
    /// + `None` if this is a system segment
    pub fn get_code_type(&self) -> Option<CodeFlags> {
        if self.is_system() {
            None
        } else {
            Some(CodeFlags::from_bits_truncate(self.bits))
        }
    }

    /// Returns the data type indicator.
    ///
    /// # Returns
    /// + `Some(DataType)` if this is not a system segment
    /// + `None` if this is a system segment
    pub fn get_data_type(&self) -> Option<DataFlags> {
        if self.is_system() {
            None
        } else {
            Some(DataFlags::from_bits_truncate(self.bits))
        }
    }

    #[inline]
    fn get_limit_part(&self) -> u32 {
        ((*self & LIMIT).bits as u32) << 8
    }

}

/// Possible ways to interpret the type bits of a segment selector.
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum Type { /// The type bits interpreted as a system segment
                System(SysType)
              , /// The type bits interpreted as a code segment
                Code(CodeFlags)
              , /// The type bits interpreted as a data segment
                Data(DataFlags)
              }

/// Possible types of for a system segment.
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
#[repr(u16)]
pub enum SysType { /// System segment used for storing a local descriptor table.
                   Ldt           = 0b0010
                 , /// An available translation stack segment.
                   TssAvailable  = 0b1001
                 , /// A busy translation stack segment
                   TssBusy       = 0b1011
                 , /// A call gate system segment
                   CallGate      = 0b1100
                 , /// An interrupt gate system segment
                   InterruptGate = 0b1110
                 , /// A trap gate system segment
                   TrapGate      = 0b1111
                 }

bitflags! {
    /// The type-specific section of a data segment's flags
    pub flags DataFlags: u16 {
        /// 0 if this segment hasn't been accessed, 1 if it has
        const DATA_ACCESSED = 0b0001
      , /// 0 if this segment is read-only, 1 if it is read-write
        const WRITE         = 0b0010
      , /// 1 if this segment expands down
        const EXPAND_DOWN   = 0b0100
    }
}

impl DataFlags {
    /// Returns true if the data segment is read-only
    #[inline] pub fn is_read_only(&self) -> bool {
        !self.contains(WRITE)
    }

    /// Returns true if the data segment has been accessed
    #[inline] pub fn is_accessed(&self) -> bool {
        self.contains(DATA_ACCESSED)
    }

    /// Returns true if the data segment expands down
    #[inline] pub fn is_expand_down(&self) -> bool {
        self.contains(EXPAND_DOWN)
    }
}

bitflags! {
    /// The type-specific section of a code segment's flags
    pub flags CodeFlags: u16 {
        /// 0 if this segment hasn't been accessed, 1 if it has
        const CODE_ACCESSED = 0b0001
      , /// 0 if this segment is read-only, 1 if it is read-write
        const READ          = 0b0010
      , /// 0 if this segment is not executable, 1 if it is executable
        const EXECUTE       = 0b1000
      , /// 0 if this segment is non-conforming, 1 if it is conforming
        const CONFORMING    = 0b0100
      , /// Whether this segment is execute-only
        const EXEC_ONLY     = EXECUTE.bits & !READ.bits
    }
}

impl CodeFlags {
    /// Returns true if the code segment is execute-only (not readable)
    #[inline] pub fn is_exec_only(&self) -> bool {
        self.contains(EXEC_ONLY)
    }

    /// Returns true if the code segment is readable
    #[inline] pub fn is_readable(&self) -> bool {
        self.contains(READ)
    }

    /// Returns true if the code segment has been accessed.
    #[inline] pub fn is_accessed(&self) -> bool {
        self.contains(CODE_ACCESSED)
    }

    /// Returns true if the code segment is conforming.
    #[inline] pub fn is_conforming(&self) -> bool {
        self.contains(CONFORMING)
    }
}


================================================
FILE: cpu/src/x86_all/timer.rs
================================================
//
//  SOS: the Stupid Operating System
//  by Eliza Weisman (eliza@elizas.website)
//
//  Copyright (c) 2016 Eliza eisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! Code for interacting with the system timer & timestamp register.
#![warn(missing_docs)]
pub mod timestamp {
    //! x86 Timestamp register
    use core::mem;


    /// Read the current value of the timestamp counter.
    ///
    /// # Safety
    /// + This will cause a General Protection Fault if the TSD flag in register
    ///   `%cr4` is set and the CPL is greater than 0.
    pub unsafe fn rtdsc() -> u64 {
        let (high, low): (u32, u32);
        asm!( "rdtsc"
            : "={eax}" (low), "={edx}" (high));
        mem::transmute((high, low))
    }

    /// Read the current timestamp, after other instructions have been executed.
    ///
    /// # Safety
    /// + This will cause a General Protection Fault if the TSD flag in register
    ///   `%cr4` is set and the CPL is greater than 0.
    pub unsafe fn rtdscp() -> u64 {
        let (high, low): (u32, u32);
        asm!( "rdtscp"
            : "={eax}" (low), "={edx}" (high)
            ::: "volatile");
        mem::transmute((high, low))
    }

    /// Returns true if timestamps are currently available.
    #[inline]
    pub fn is_available() -> Result<(), &'static str> {
        use ::control_regs::cr4;
        use ::PrivilegeLevel;

        if PrivilegeLevel::current_iopl() != PrivilegeLevel::KernelMode {
            Err("Reading timestamp register requires kernel mode.")
        } else if
            // it's safe to do this since we already know we are in kernel mode.
            unsafe { cr4::is_timestamp_disabled() } {
            Err("Timestamp Disable bit in %cr4 is set")
        } else { Ok(()) }
    }

    /// Returns the current timestamp, or an error
    #[inline]
    pub fn get_timestamp() -> Result<u64, &'static str> {
        is_available().map(|_| unsafe { rtdsc() })
    }

    /// Returns the current timestamp or an error, after other instructions have
    /// been executed.
    #[inline]
    pub fn wait_get_timestamp() -> Result<u64, &'static str> {
        is_available().map(|_| unsafe { rtdscp() })
    }
}


================================================
FILE: elf/Cargo.toml
================================================
[package]
name = "elf"
version = "0.0.2"
authors = [ "Eliza Weisman <eliza@elizas.website>" ]

[profile.dev]
opt-level = 3
debug = true
rpath = false
lto = false
debug-assertions = true
codegen-units = 1
panic = "abort"

[profile.release]
opt-level = 3
debug = true
rpath = false
lto = false
panic = "abort"

[dependencies]
bitflags = "0.7"
memory = { path = "../memory" }

[dependencies.macro-attr]
git = "https://github.com/DanielKeep/rust-custom-derive.git"
version = "0.2.1"
default-features = false


================================================
FILE: elf/README.md
================================================
elf: ELF parsing and loading
============================

a library for parsing, navigating, and loading 32- and 64-bit [Executable and Linkable File](http://wiki.osdev.org/ELF)s.

### why are we writing our own ELF lib?

although there are a number of other nice [ELF](https://github.com/nrc/xmas-elf) [libraries](https://github.com/m4b/goblin) for Rust, I'm writing my own for the following handful of reasons:

+ requirements specific to our use-case (no std, no allocation, &c)
+ up to date with recent Rust language features (not all ELF libs are actively maintained)
+ compatibility with SOS' types & representations without translation layers (e.g., uses our `PAddr` type.)
+ it's fun & I want to do it myself!


================================================
FILE: elf/src/file.rs
================================================
//
//  SOS: the Stupid Operating System
//  by Eliza Weisman (eliza@elizas.website)
//
//  Copyright (c) 2015-2017 Eliza Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! ELF file header
use super::{ElfResult, ElfWord, Section, section};
use super::ValidatesWord;

use section::Header as SectionHeader;

use core::{fmt, mem, convert};
use core::ops::Range;

/// Trait representing an ELF File Header.
///
/// This trait allows [HeaderRepr] to provide a consistent API regardless
/// of whether the header section uses 32- or 64-bit [ELF word]s. A number of
/// field values in the header of various sizes are converted to `usize` by
/// this API so that they can be used as indices, etc.
///
/// For more information on ELF File Headers, refer to:
/// + the ELF [specification]
/// + the [OS Dev Wiki]
///
/// [ELF word]: ../type.ElfWord.html
/// [HeaderRepr]: struct.HeaderRepr.html
/// [specification](http://www.sco.com/developers/gabi/latest/ch4.eheader.html)
/// [OS Dev Wiki](http://wiki.osdev.org/ELF#Header)
pub trait Header: Sized {
    type Word: ElfWord;

    /// Attempt to extract an ELF file header from a slice of bytes.
    fn from_slice<'a>(input: &'a [u8]) -> ElfResult<&'a Self>;

    /// Attempt to extract a section header from a slice of bytes.
    /// TODO: can/should the index be `usize`?
    //          - eliza, 03/08/2017
    fn parse_section<'a>(&'a self, input: &'a [u8], idx: u16)
                            -> ElfResult<&'a Section<Self::Word>>;

    fn sh_range(&self) -> Range<usize> {
        let start = self.sh_offset();
        start .. start + (self.sh_entry_size() * self.sh_count())
    }

    fn ph_range(&self) -> Range<usize> {
        let start = self.ph_offset();
        start .. start + (self.ph_entry_size() * self.ph_count())
    }

    /// Calculate the index for a [section header]
    ///
    /// TODO: should this check the index is reasonable & return a `Result`
    //          - eliza, 03/10/2017
    /// [section header]: ../section/struct.Header.html
    fn section_index(&self, idx: usize) -> Range<usize> {
        let size = self.sh_entry_size();
        let start = self.sh_offset() + (idx * size);
        start .. start + size
    }

    /// Calculate the index for a program header
    ///
    /// TODO: should this check the index is reasonable & return a `Result`
    //          - eliza, 03/10/2017
    fn program_header_index(&self, idx: usize) -> Range<usize> {
        let size = self.ph_entry_size();
        let start = self.ph_offset() + (idx * size);
        start .. start + size
    }

    // Field accessors -------------------------------------------
    fn ident(&self) -> Ident;
    fn get_type(&self) -> Type;
    fn machine(&self) -> Machine;
    /// Offset of the program entry point
    fn entry_point(&self) -> usize;
    /// Offset of the start of program headers
    fn ph_offset(&self) -> usize;
    /// Number of program headers.
    fn ph_count(&self) -> usize;
    /// Size of a program header.
    fn ph_entry_size(&self) -> usize;
    /// Offset of the start of [section header]s.
    ///
    /// [section header]: ../section/struct.Header.html
    fn sh_offset(&self) -> usize;
    /// Number of [section header]s.
    ///
    /// [section header]: ../section/struct.Header.html
    fn sh_count(&self) -> usize;
    /// Size of a [section header].
    ///
    /// [section header]: ../section/struct.Header.html
    fn sh_entry_size(&self) -> usize;
    /// TODO: can this return the flags type?
    //          - eliza, 03/08/2017
    fn flags(&self) -> u32;
    /// Index of the section header [string table].
    ///
    /// [string table]: ../section/struct.StrTable.html"]
    fn sh_str_idx(&self) -> usize;
}

macro_rules! Header {
    (($($size:ty),+) $(pub)* enum $name:ident $($tail:tt)* ) => {
        Header! { @impl $name, $($size)+ }
    };
    (($($size:ty),+) $(pub)* struct $name:ident $($tail:tt)*) => {
        Header! { @impl $name, $($size)+ }
    };
    (@impl $name:ident, $($size:ty)+) => {
        $(impl Header for $name<$size> {
            type Word = $size;
            /// Attempt to extract an ELF file header from a slice of bytes.
            fn from_slice<'a>(input: &'a [u8]) -> ElfResult<&'a Self> {
                if input.len() < mem::size_of::<Self>() {
                    Err("Input too short to extract ELF header")
                } else {
                    unsafe {
                        super::extract_from_slice::<Self>(input, 0, 1)
                            .map(|x| &x[0]) }
                }
            }

            /// Attempt to extract a [section header] from a slice of bytes.
            ///
            /// TODO: should this move to the `File` type since it owns the
            ///       byte slice (which then wouldn't have to be passed as an
            ///       argument)?
            //          - eliza, 03/10/2017
            ///
            /// [section header]: ../section/struct.Header.html
            fn parse_section<'a>(&'a self, input: &'a [u8], idx: u16)
                                -> ElfResult<&'a Section<Self::Word>>
            where section::HeaderRepr<Self::Word>: SectionHeader<Word = Self::Word> {
                if idx < section::SHN_LORESERVE {
                    Err("Cannot parse reserved section.")
                } else {
                    // use ValidatesWord to check if this section's Class field
                    // will let us interpret the section with the requested
                    // word length. this is a bit of a hack around the type
                    // system not letting me do this the way I wanted to to....
                    let validator: &ValidatesWord<Self::Word>
                        = &self.ident.class;
                    validator.check()?;

                    let raw = &input[self.section_index(idx as usize)];

                    unsafe {
                        Ok(&*(raw as *const [u8]
                                  as *const _
                                  as *const section::HeaderRepr<Self::Word>))
                    }
                }
            }

            #[inline] fn get_type(&self) -> Type { self.elftype.as_type() }

            impl_getters! {
                #[doc = "Index for the start of [section header]s. \
                         [section header]: ../section/struct.Header.html"]
                fn sh_offset(&self) -> usize;
                fn sh_entry_size(&self) -> usize;
                fn sh_count(&self) -> usize;

                #[doc = "Index for the start of program headers"]
                fn ph_offset(&self) -> usize;
                fn ph_entry_size(&self) -> usize;
                fn ph_count(&self) -> usize;

                #[doc = "Index for the program entry point"]
                fn entry_point(&self) -> usize;
                #[doc = "Index of the section header [string table] \
                         [string table]: ../section/struct.StrTable.html"]
                fn sh_str_idx(&self) -> usize;
                fn flags(&self) -> u32;
                fn ident(&self) -> Ident;
                fn machine(&self) -> Machine;
            }
        }

        impl<'a> convert::TryFrom<&'a [u8]> for &'a $name<$size> {
            type Error = &'static str;
            #[inline]
            fn try_from(slice: &'a [u8]) -> ElfResult<Self> {
                <$name<$size> as Header>::from_slice(slice)
            }
        }
        )+
    }
}

macro_attr! {
    /// Raw representation of an ELF file header.
    #[derive(Copy, Clone, Debug, Header!(u32, u64))]
    #[repr(C, packed)]
    pub struct HeaderRepr<W: ElfWord> {
        /// the ELF [file identifier](struct.Ident.html)
        pub ident: Ident
      , elftype: TypeRepr
      , pub machine: Machine
      , /// Program entry point
        entry_point: W
      , /// Offset for start of program headers
        ph_offset: W
      , /// Offset for start of [section header]s.
        /// [section header]: ../section/struct.Header.html
        sh_offset: W
      , pub flags: u32
      , pub header_size: u16
      , pub ph_entry_size: u16
      , pub ph_count: u16
      , pub sh_entry_size: u16
      , pub sh_count: u16
      , /// Index of the section header string table
        sh_str_idx: u16
    }
}

/// ELF header magic
pub const MAGIC: Magic = [0x7f, b'E', b'L', b'F'];

/// Type of header magic
pub type Magic = [u8; 4];


/// ELF identifier (`e_ident` in the ELF standard)
#[derive(Copy, Clone, Debug)]
#[repr(C, packed)]
pub struct Ident {
    /// ELF magic numbers. Must be equal to the [ELF magic], `[0x7, E, L, F]`.
    ///
    /// [ELF magic]: constant.MAGIC.html
    pub magic: Magic
  , /// ELF [file class](enum.Class.html) (32- or 64-bit)
    pub class: Class
  , /// ELF [data encoding](enum.DataEncoding.html) (big- or little-endian)
    pub encoding: DataEncoding
  , /// ELF file [version](enum.Version.html)
    pub version: Version
  , /// What [operating system ABI] this file was compiled for.
    ///
    /// [operating system ABI]: enum.OsAbi.html
    pub abi: OsAbi
  , /// ABI version (often this is just padding)
    pub abi_version: u8
  , _padding: [u8; 7]
}

impl Ident {
    #[inline] pub fn check_magic(&self) -> bool { self.magic == MAGIC }

    /// Returns true if the identifier section identifies a valid ELF file.
    #[inline] pub fn is_valid(&self) -> bool {
        // the ELF magic number is correct
        self.check_magic() &&
        // the file class is either 32- or 64-bits
        self.class.is_valid() &&
        // the data encoding is either big- or little-endian
        self.encoding.is_valid()
    }
}

/// Identifies the class of the ELF file
#[derive(Copy, Clone, PartialEq, Debug)]
#[repr(u8)]
pub enum Class {
    /// Invalid ELF class file (`ELFCLASSNONE` in the standard)
    None  = 0
  , /// 32-bit ELF file (`ELFCLASS32` in the standard)
    Elf32 = 1
  , /// 64-bit ELF file (`ELFCLASS64` in the standard)
    Elf64 = 2
}

impl Class {
    /// Returns true if the class field for this file is valid.
    #[inline]
    pub fn is_valid(&self) -> bool {
        match *self { Class::None => false
                    , _ => true
                    }
    }

}

impl ValidatesWord<u64> for Class {
    #[inline]
    fn check(&self) -> ElfResult<()> {
        use self::Class::*;
        match *self {
            None => Err("Invalid ELF type ELFCLASSNONE!")
          , Elf32 => Err("Cannot extract 64-bit section from 32-bit ELF")
          , Elf64 => Ok(())
        }
    }
}

impl ValidatesWord<u32> for Class {
    #[inline]
    fn check(&self) -> ElfResult<()> {
        use self::Class::*;
        match *self {
            None => Err("Invalid ELF type ELFCLASSNONE!")
          , Elf64 =>
                // TODO: is this actually true?
                //          - eliza, 03/08/2017
                Err("Cannot extract 32-bit section from 64-bit ELF")
          , Elf32 => Ok(())
        }
    }
}

/// Identifies the data encoding of the ELF file
#[derive(Copy, Clone, PartialEq, Debug)]
#[repr(u8)]
pub enum DataEncoding {
    /// Invalid data encoding (`ELFDATANONE` in the standard)
    None  = 0
  , /// Twos-complement little-endian data encoding
    /// (`ELFDATA2LSB` in the standard)
    LittleEndian = 1
  , /// Twos-complement big-endian data encoding
    /// (`ELFDATA2MSB` in the standard)
    BigEndian = 2
}

impl DataEncoding {
    /// Returns true if the data encoding field for this file is valid.
    #[inline]
    pub fn is_valid(&self) -> bool {
        match *self { DataEncoding::None => false
                    , _ => true
                    }
    }
}

/// Operating system ABI
#[derive(Copy, Clone, Debug)]
#[repr(u8)]
pub enum OsAbi { /// Ox00 also represents "none"
                 SystemV = 0x00
               , HpUx    = 0x01
               , NetBsd  = 0x02
               , Linux   = 0x03
               , Solaris = 0x06
               , Aix     = 0x07
               , Irix    = 0x08
               , FreeBsd = 0x09
               , OpenBsd = 0x0C
               , OpenVms = 0x0D
               }

/// Identifies the version of the ELF file
#[derive(Copy, Clone, PartialEq, Debug)]
#[repr(u8)]
pub enum Version { None = 0, Current = 1 }

#[derive(Clone, Copy, PartialEq)]
struct TypeRepr(u16);

impl TypeRepr {
    /// TODO: rewrite this as a `convert::Into` implementation
    ///         - eliza, 03/09/2017
    pub fn as_type(&self) -> Type {
        match self.0 {
            0 => Type::None
          , 1 => Type::Relocatable
          , 2 => Type::Executable
          , 3 => Type::SharedObject
          , 4 => Type::Core
          , anything => Type::Other(anything)
        }
    }
}

impl fmt::Debug for TypeRepr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.as_type().fmt(f)
    }
}

#[derive(Clone, Copy, PartialEq, Debug)]
pub enum Type { None
              , Relocatable
              , Executable
              , SharedObject
              , Core
              , Other(u16)
              }

#[allow(non_camel_case_types)]
#[derive(Clone, Copy, PartialEq, Debug)]
#[repr(u16)]
pub enum Machine { None    = 0
                 , Sparc   = 0x02
                 , X86     = 0x03
                 , Mips    = 0x08
                 , PowerPc = 0x14
                 , Arm     = 0x28
                 , SuperH  = 0x2A
                 , Ia64    = 0x32
                 , X86_64  = 0x3E
                 , AArch64 = 0xB7
                 }


================================================
FILE: elf/src/lib.rs
================================================
//
//  SOS: the Stupid Operating System
//  by Eliza Weisman (eliza@elizas.website)
//
//  Copyright (c) 2015-2017 Eliza Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! Parsing and loading Executable and Linkable Format (ELF) 32- and 64-bit
//! binaries.
//!
//! For more information on the ELF format, refer to:
//!
//!  + [Wikipedia](https://en.wikipedia.org/wiki/Executable_and_Linkable_Format)
//!  + The [OS Dev Wiki](http://wiki.osdev.org/ELF)
//!  + The [ELF Format Specification](elfspec)
//!
//! [elfspec]: http://www.skyfree.org/linux/references/ELF_Format.pdf
#![feature(core_intrinsics)]
#![feature(try_from)]
#![no_std]

#[macro_use] extern crate bitflags;
#[macro_use] extern crate macro_attr;

extern crate memory;

use core::{ ops, mem, slice, convert };
use core::convert::TryFrom;

use memory::{ FrameRange, PhysicalPage };


macro_rules! impl_getters {
    ($(#[$attr:meta])* pub fn $name:ident(&self) -> PAddr; $($rest:tt)*) => {
        $(#[$attr])* #[inline] pub fn $name(&self) -> ::memory::PAddr {
            use ::memory::{PAddr, Addr};
            PAddr::from(self.$name as <PAddr as Addr>::Repr)
        }
        impl_getters!{ $( $rest )* }
    };
    ($(#[$attr:meta])* fn $name:ident(&self) -> PAddr; $($rest:tt)*) => {
        $(#[$attr])* #[inline] fn $name(&self) -> ::memory::PAddr {
            use ::memory::{PAddr, Addr};
            PAddr::from(self.$name as <PAddr as Addr>::Repr)
        }
        impl_getters!{ $( $rest )* }
    };
    ($(#[$attr:meta])* pub fn $name:ident(&self) -> PAddr;) => {
        $(#[$attr])* #[inline] pub fn $name(&self) -> ::memory::PAddr {
            use ::memory::{PAddr, Addr};
            PAddr::from(self.$name as <PAddr as Addr>::Repr)
        }
        impl_getters!{ $( $rest )* }
    };
    ($(#[$attr:meta])* fn $name:ident(&self) -> PAddr;) => {
        $(#[$attr])* #[inline] fn $name(&self) -> ::memory::PAddr {
            use ::memory::{PAddr, Addr};
            PAddr::from(self.$name as <PAddr as Addr>::Repr)
        }
        impl_getters!{ $( $rest )* }
    };
    ($(#[$attr:meta])* pub fn $name:ident(&self) -> $ty:ty; $($rest:tt)*) => {
        $(#[$attr])* #[inline] pub fn $name(&self) -> $ty { self.$name as $ty }
        impl_getters!{ $( $rest )* }
    };
    ($(#[$attr:meta])* fn $name:ident(&self) -> $ty:ty; $($rest:tt)*) => {
        $(#[$attr])* #[inline] fn $name(&self) -> $ty { self.$name as $ty }
        impl_getters!{ $( $rest )* }
    };
    ( $(#[$attr:meta])* pub fn $name: ident (&self)-> $ty:ty; ) => {
        $(#[$attr])* #[inline] pub fn $name(&self) -> $ty { self.$name as $ty }
    };
    ( $(#[$attr:meta])* fn $name: ident (&self)-> $ty:ty; ) => {
        $(#[$attr])* #[inline] fn $name(&self) -> $ty { self.$name as $ty }
    };
    () => {};
}

pub mod section;
pub mod file;
pub mod program;

/// An ELF section header.
pub type Section<W> = section::Header<Word = W>;
pub type ProgramHeader<W> = program::Header<Word = W>;
/// An ELF header file.
pub type FileHeader<W> = file::HeaderRepr<W>;

/// TODO: should ELF have its own error type?
pub type ElfResult<T> = Result<T, &'static str>;

pub trait ElfWord: Sized + Copy + Clone
                         + ops::Add<Self> + ops::Sub<Self>
                         + ops::Mul<Self> + ops::Div<Self>
                         + ops::Shl<Self> + ops::Shr<Self> { }
impl ElfWord for u64 { }
impl ElfWord for u32 { }

#[cfg(target_pointer_width = "32")]
type DefaultWord = u32;
#[cfg(target_pointer_width = "64")]
type DefaultWord = u64;

/// Hack to make the type-system let me do what I want
trait ValidatesWord<Word: ElfWord> {
    fn check(&self) -> ElfResult<()>;
}

/// A handle on a parsed ELF binary
///  TODO: do we want this to own a HashMap of section names to section headers,
///        to speed up section lookup?
//          - eliza, 03/08/2017
#[derive(Debug)]
pub struct Image< 'bytes             // lifetime of the byte slice
                , Word = DefaultWord // default to machine's pointer size
                , ProgHeader = ProgramHeader<Word> // same word type
                , SectHeader = Section<Word>
                , Header = FileHeader<Word> // must have same word type
                > // jesus christ
where Word: ElfWord + 'bytes
    , ProgHeader: program::Header<Word = Word> + Sized + 'bytes
    , SectHeader: section::Header<Word = Word> + Sized + 'bytes
    , Header: file::Header<Word = Word> + 'bytes
    {
    /// the binary's [file header](file/trait.Header.html)
    pub header: &'bytes Header
  , /// references to each [section header](section/struct.Header.html)
    pub sections: &'bytes [SectHeader]
  , /// references to each [program header](program/trait.Header.html)
    pub program_headers: &'bytes [ProgHeader]
  , /// the raw binary contents of the ELF binary.
    /// note that this includes the _entire_ binary contents of the file,
    /// so the file header and each section header is included in this slice.
    binary: &'bytes [u8]
}

impl <'a, Word, ProgHeader, SectHeader, Header>
Image<'a, Word, ProgHeader, SectHeader, Header>
where Word: ElfWord + 'a
    , ProgHeader: program::Header<Word = Word> + Sized + 'a
    , SectHeader: section::Header<Word = Word> + Sized + 'a
    , Header: file::Header<Word = Word> + 'a
    {
    /// Returns the section header [string table].
    ///
    /// [string table]: section/struct.StrTable.html
    pub fn sh_str_table(&'a self) -> section::StrTable<'a> {
        // TODO: do we want to validate that the string table index is
        //       reasonable (e.g. it's not longer than the binary)?
        //          - eliza, 03/08/2017
        // TODO: do we want to cache a ref to the string table?
        //          - eliza, 03/08/2017
        section::StrTable::from(&self.binary[self.header.sh_str_idx()..])
    }

}

impl<'a, Word, PH, SH, FH> TryFrom<&'a [u8]> for Image<'a, Word, PH, SH, FH>
where Word: ElfWord + 'a
    , PH: program::Header<Word = Word> + 'a
    , SH: section::Header<Word = Word> + 'a
    , FH: file::Header<Word = Word> + 'a
    , &'a FH: convert::TryFrom<&'a [u8], Error = &'static str>
    {

    type Error = &'static str;

    fn try_from(bytes: &'a [u8]) -> ElfResult<Self> {
        let header: &'a FH = <&'a FH>::try_from(bytes)?;

        let sections = unsafe { extract_from_slice::<SH>(
            &bytes[header.sh_range()]
          , 0
          , header.sh_count()
        )? };
        let prog_headers = unsafe { extract_from_slice::<PH>(
            &bytes[header.ph_range()]
          , 0
          , header.ph_count()
        )? };
        Ok(Image { header: header
              , sections: sections
              , program_headers: prog_headers
              , binary: bytes
        })
    }
}

/// Extract `n` instances of type `T` from a byte slice.
///
/// This is essentially just a _slightly_ safer wrapper around
/// [`slice::from_raw_parts`]. Unlike `from_raw_parts`, this function takes
/// a valid byte slice, rather than a pointer. Therefore, some of the safety
/// issues with `from_raw_parts` are avoided:
///
/// + the lifetime (`'slice`) of the returned slice should be the same as the
///   lifetime of the input slice (`data`), rather than inferred arbitrarily.
/// + this function will panic rather than reading past the end of the slice.
///
/// # Arguments
///
/// + `data`: the byte slice to extract a slice of `&[T]`s from
/// + `offset`: a start offset into `data`
/// + `n`: the number of instances of `T` which should be contained
///        in `data[offset..]`
///
/// # Safety
///
/// While this function is safer than [`slice::from_raw_parts`],
/// it is still unsafe for the following reasons:
///
/// + The contents of `data` may not be able to be interpreted as instances of
///   type `T`.
///
/// # Caveats
///
/// + If `n` == 0, this will give you an `&[]`. Just a warning.
//    thanks to Max for making  me figure this out.
/// + `offset` must be aligned on a `T`-sized boundary.
///
/// # Panics
///
/// + If the index `offset` is longer than `T`
///
/// TODO: rewrite this as a `TryFrom` implementation (see issue #85)
//          - eliza, 03/09/2017
///       wait, possibly we should NOT do that. actually we should
///       almost certainly not do that. since this function is unsafe,
///       but `TryFrom` is not, and because this would be WAY generic.
//          - eliza, 03/09/2017
/// TODO: is this general enough to move into util?
//          - eliza, 03/09/2017
/// TODO: refactor this to take a `RangeArgument`?
//          - eliza, 03/13/2017
///       or, we could just remove the offset and expect the caller to
///       offset the slice?
//          - eliza, 03/14/2017
///
/// [`slice::from_raw_parts`]: https://doc.rust-lang.org/stable/std/slice/fn.from_raw_parts.html
unsafe fn extract_from_slice<'slice, T: Sized>( data: &'slice [u8]
                                              , offset: usize
                                              , n: usize)
                                              -> ElfResult<&'slice [T]> {
    if offset % mem::align_of::<T>() != 0 {
        // TODO: these error messages don't contain as much information as they
        //       used to, since the return type is `&'static str` that can't be
        //       dynamically formatted as the panic was. refactor this?
        //       (e.g. should ELF get its own error type?)
        //        - eliza, 03/15/2017
        Err("extract_from_slice: Offset not aligned on type T sized boundary!")
        // assert!(
        //        , "Offset {} not aligned on a {}-sized boundary (must be \
        //           divisible by {})."
        //        , offset, type_name::<T>(), mem::align_of::<T>()
        //        );
    } else if data.len() - offset < mem::size_of::<T>() * n {
        Err("extract_from_slice: Slice too short to contain n instances of T!")
        // assert!(
        //        , "Slice too short to contain {} objects of type {}"
        //        , n, type_name::<T>()
        //        );
    } else {
        Ok(slice::from_raw_parts(data[offset..].as_ptr() as *const T, n))
    }
}

impl<'a, W: ElfWord> convert::Into<FrameRange> for &'a Section<W> {
    #[inline]
    fn into(self) -> FrameRange {
        use memory::Page;
        let start = PhysicalPage::containing(self.address());
        let end = PhysicalPage::containing(self.end_address());
        start .. end
    }
}


================================================
FILE: elf/src/program.rs
================================================
//
//  SOS: the Stupid Operating System
//  by Eliza Weisman (eliza@elizas.website)
//
//  Copyright (c) 2015-2017 Eliza Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//

use super::ElfWord;

/// Trait representing an ELF Program Header.
///
/// This trait allows [HeaderRepr] to provide a consistent API regardless
/// of whether the header section uses 32- or 64-bit [ELF word]s. A number of
/// field values in the header of various sizes are converted to `usize` by
/// this API so that they can be used as indices, etc.
///
/// For more information on ELF Program Headers, refer to:
/// + the ELF [specification]
/// + the [OS Dev Wiki]
///
/// [ELF word]: ../type.ElfWord.html
/// [HeaderRepr]: struct.HeaderRepr.html
/// [specification](http://www.sco.com/developers/gabi/latest/ch5.pheader.html)
/// [OS Dev Wiki](http://wiki.osdev.org/ELF#Header)
pub trait Header: Sized {
    type Word: ElfWord;

    /// Returns the [type](enum.Type.html) of this program header.
    ///
    /// This member tells what kind of segment this header describes or how to
    /// interpret the array element's information.
    fn ty(&self) -> Type;

    /// Returns this segment's start offset from the beginning of the binary.
    fn offset(&self) -> usize;

    /// Returns the virtual address of the first byte in this segment.
    fn vaddr(&self) -> Self::Word;

    /// Returns the physical address of the first byte in this segment.
    fn paddr(&self) -> Self::Word;

    /// Returns the number of bytes in the file image of the segment.
    ///
    /// This may be zero.
    fn file_size(&self) -> usize;

    /// Returns the number of bytes in the memory image of the segment.
    ///
    /// This may be zero.
    fn mem_size(&self) -> usize;

    /// Returns the [flags] for this segment.
    ///
    /// [flags]: struct.Flags.html
    fn flags(&self) -> Flags;

    fn align(&self) -> usize;

}


macro_rules! Header {
    (($($size:ty),+) $(pub)* enum $name:ident $($tail:tt)* ) => {
        Header! { @impl $name, $($size)+ }
    };
    (($($size:ty),+) $(pub)* struct $name:ident $($tail:tt)*) => {
        Header! { @impl $name, $($size)+ }
    };
    (@impl $name:ident, $size:ty) => {
        impl Header for $name {
            type Word = $size;

            impl_getters! {
                fn ty(&self) -> Type;
                fn flags(&self) -> Flags;
                fn offset(&self) -> usize;

                fn vaddr(&self) -> Self::Word;
                fn paddr(&self) -> Self::Word;

                fn file_size(&self) -> usize;
                fn mem_size(&self) -> usize;
                fn align(&self) -> usize;
            }
        }
    };
}

/// The type field of an ELF program header
#[repr(u32)]
#[derive(Copy, Clone, Debug)]
pub enum Type {
    /// `PT_NULL`: Program header table entry unused
    Null = 0
  , /// `PT_LOAD`: Loadable program segment
    Loadable = 1
  , /// `PT_DYNAMIC`: Dynamic linking information
    Dynamic = 2
  , /// `PT_INTERP`: Program interpreter
    Interpreter = 3
  , /// `PT_NOTE`: Auxiliary information
    Note = 4
  , /// `PT_SHLIB`
    ShLib = 5
  , /// `PT_PHDR`: Program Header table
    HeaderTable = 6
  , /// `PT_TLS`: Thread-local storage
    ThreadLocal = 7
  , /// GCC `.eh_frame_hdr` segment
    GnuEhFrame = 0x6474e550
  , /// Indicates stack executability
    GnuStack = 0x6474e551
  , /// Read-only after relocation
    GnuRelRo = 0x6474e552
}

bitflags! {
    pub flags Flags: u32 {
        const NONE = 0
      , const EXECUTABLE = 1 << 0
      , const WRITABLE = 1 << 1
      , const READABLE = 1 << 2
    }
}

macro_attr! {
    /// A 64-bit ELF Program Header
    #[derive(Copy, Clone, Debug, Header!(u64))]
    pub struct HeaderRepr64 {
        pub ty: Type
      , pub flags: Flags
      , pub offset: u64
      , pub vaddr: u64
      , pub paddr: u64
      , pub file_size: u64
      , pub mem_size: u64
      , pub align: u64
    }
}

macro_attr! {
    /// A 32-bit ELF Program Header
    #[derive(Copy, Clone, Debug, Header!(u32))]
    pub struct HeaderRepr32 {
        pub ty: Type
      , pub offset: u32
      , pub vaddr: u32
      , pub paddr: u32
      , pub file_size: u32
      , pub mem_size: u32
      , pub flags: Flags
      , pub align: u32
    }
}


================================================
FILE: elf/src/section.rs
================================================
//
//  SOS: the Stupid Operating System
//  by Eliza Weisman (eliza@elizas.website)
//
//  Copyright (c) 2015-2017 Eliza Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
use super::{ElfResult, ElfWord};

use core::{convert, fmt, ops};
use core::iter::IntoIterator;

use memory::{Addr, PAddr};

// Distinguished section indices.
pub const SHN_UNDEF: u16        = 0;
pub const SHN_LORESERVE: u16    = 0xff00;
pub const SHN_LOPROC: u16       = 0xff00;
pub const SHN_HIPROC: u16       = 0xff1f;
pub const SHN_LOOS: u16         = 0xff20;
pub const SHN_HIOS: u16         = 0xff3f;
pub const SHN_ABS: u16          = 0xfff1;
pub const SHN_COMMON: u16       = 0xfff2;
pub const SHN_XINDEX: u16       = 0xffff;
pub const SHN_HIRESERVE: u16    = 0xffff;

pub const SHT_LOOS: u32   = 0x60000000;
pub const SHT_HIOS: u32   = 0x6fffffff;
pub const SHT_LOPROC: u32 = 0x70000000;
pub const SHT_HIPROC: u32 = 0x7fffffff;
pub const SHT_LOUSER: u32 = 0x80000000;
pub const SHT_HIUSER: u32 = 0xffffffff;

/// Represents an ELF section header
///
/// Refer to [Figure 4-8], "Section Header", from Chapter 4 of the ELF standard
/// for more information.
///
/// [Figure 4-8]: (http://www.sco.com/developers/gabi/latest/ch4.sheader.html#section_header)
// #[derive(Clone, Copy, Debug)]
// pub enum Header<'a> {
//     ThirtyTwo(&'a HeaderRepr<u32>)
//   , SixtyFour(&'a HeaderRepr<u64>)
// }
pub trait Header: fmt::Debug {
    type Word: ElfWord;

    // /// Returns the start address of this section
    // fn addr(&self) -> PAddr;

    /// Returns the end address of this section
    /// TODO: refactor this to return a Range instead?
    //          - eliza, 03/14/2017
    #[inline] fn end_address(&self) -> PAddr {
        self.address() + self.length() as <PAddr as Addr>::Repr
    }

    /// Returns true if this section is writable.
    #[inline] fn is_writable(&self) -> bool {
        self.flags().contains(SHF_WRITE)
    }

    /// Returns true if this section occupies memory during program execution.
    #[inline] fn is_allocated(&self) -> bool {
        self.flags().contains(SHF_ALLOC)
    }

    /// Returns true if this section contains executable instructions.
    #[inline] fn is_executable(&self) -> bool {
        self.flags().contains(SHF_EXECINSTR)
    }

    /// Returns true if this section can be merged.
    #[inline] fn is_mergeable(&self) -> bool {
        self.flags().contains(SHF_MERGE)
    }

    /// Returns true if this section contains data that is of a uniform size.
    #[inline] fn is_uniform(&self) -> bool {
        let flags = self.flags();
        flags.contains(SHF_MERGE) &&
        !flags.contains(SHF_STRINGS)
    }

    /// Look up the name of this section in the passed string table.
    #[inline] fn get_name<'a>(&self, strtab: StrTable<'a>) -> &'a str {
        unimplemented!()
    }

    // Field accessors -------------------------------------------------
    fn name_offset(&self) -> u32;
    /// This member categorizes the section's contents and semantics.
    fn get_type(&self) -> ElfResult<Type>;
    fn flags(&self) -> Flags;
    fn address(&self) -> PAddr;
    fn offset(&self) -> usize;
    /// TODO: should offset + length make a Range?
    //          - eliza, 03/14/2017
    fn length(&self) -> usize;
    fn link(&self) -> u32;
    fn info(&self) -> u32;
    fn address_align(&self) -> Self::Word;
    fn entry_length(&self) -> usize;
}

macro_rules! Header {
    (($($size:ty),+) $(pub)* enum $name:ident $($tail:tt)* ) => {
        Header! { @impl $name, $($size)+ }
    };
    (($($size:ty),+) $(pub)* struct $name:ident $($tail:tt)*) => {
        Header! { @impl $name, $($size)+ }
    };
    (@impl $name:ident, $($size:ty)+) => {
        $(impl Header for $name<$size> {
            type Word = $size;

            /// Returns the type of this section
            #[inline] fn get_type(&self) -> ElfResult<Type> {
                 self.ty.as_type()
             }

            impl_getters! {
                fn name_offset(&self) -> u32;
                fn flags(&self) -> Flags;
                /// TODO: shold this return a PAddr?
                //          - eliza, 03/14/2017
                fn address(&self) -> PAddr;
                fn offset(&self) -> usize;
                /// TODO: should offset + length make a Range?
                //          - eliza, 03/14/2017
                fn length(&self) -> usize;
                fn link(&self) -> u32;
                fn info(&self) -> u32;
                fn address_align(&self) -> Self::Word;
                fn entry_length(&self) -> usize;
            }
        })+
    };
}

impl<Word> fmt::Display for Header<Word = Word>
where Word: ElfWord
    , Header<Word = Word>: fmt::Debug {
    #[inline]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        // TODO: do we want to actually get the section's name from the string
        //       table and display it here?
        //          - eliza, 03/05/2017
        // TODO: do we want to print the header's flags, or would that make the //       format too long?
        //          - eliza, 03/05/2017
        if let Ok(ty) = self.get_type() {
            // the ELF section was valid
            write!(f, "{:?} section at {:?} ... {:?}"
                  , ty, self.address(), self.end_address())
        } else {
            // we couldn't successfully extract a type from the ELF section!
            write!(f, "Bad ELF section {:?}", self)
        }
    }
}

macro_attr! {
    /// Raw representation of an ELF section header in an ELF binary.
    ///
    /// Refer to [Figure 4-8], "Section Header", from Chapter 4 of the ELF
    /// standard for more information.
    ///
    /// [Figure 4-8]: (http://www.sco.com/developers/gabi/latest/ch4.sheader.html#section_header)
    //  TODO: add docs for all fields!
    //          - eliza, 03/05/2017
    #[derive(Debug, Header!(u32, u64))]
    #[repr(C)]
    pub struct HeaderRepr<Word> {
        /// This member specifies the name of the section.
        ///
        /// Its value is an index into the section header string table section,
        /// giving the location of a null-terminated string.
        name_offset: u32
      , /// This member categorizes the section's contents and semantics.
        ty: TypeRepr
      , flags: Flags
      , address: Word
      , offset: Word
      , length: Word
      , link: u32
      , info: u32
      , address_align: Word
      , entry_length: Word
    }
}


bitflags! {
    // TODO: add documentation to the flags
    //          - eliza, 03/05/2017
    pub flags Flags: usize {
        // Flags (SectionHeader::flags)
        const SHF_WRITE            =        0x1
      , const SHF_ALLOC            =        0x2
      , const SHF_EXECINSTR        =        0x4
      , const SHF_MERGE            =       0x10
      , const SHF_STRINGS          =       0x20
      , const SHF_INFO_LINK        =       0x40
      , const SHF_LINK_ORDER       =       0x80
      , const SHF_OS_NONCONFORMING =      0x100
      , const SHF_GROUP            =      0x200
      , const SHF_TLS              =      0x400
      , const SHF_COMPRESSED       =      0x800
      , const SHF_MASKOS           = 0x0ff00000
      , const SHF_MASKPROC         = 0xf0000000
    }
}

impl fmt::LowerHex for Flags {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.bits.fmt(f)
    }
}

bitflags! {
    pub flags GroupFlags: u32 {
        const GRP_COMDAT	=        0x1
      , const GRP_MASKOS	= 0x0ff00000
      , const GRP_MASKPROC	= 0xf0000000
    }
}

pub enum Contents<'a> {
    Empty
  , Undefined(&'a [u8])
  , Group { flags: &'a u32
          , indicies: &'a[u32] }
}

/// Underlying representation of a section header type field
///
/// Unfortunately, we cannot have enums with open ranges yet, so we have
/// to convert between the ELF file underlying representation and our
/// type-safe representation.
///
/// Refer to [Figure 4-9]: "Section Types, `sh_type`" in Section 4 of the
/// ELF standard for more information.
///
/// [Figure 4-9]:  http://www.sco.com/developers/gabi/latest/ch4.sheader.html#sh_type
#[derive(Debug, Copy, Clone)]
struct TypeRepr(u32);

impl TypeRepr {
    /// TODO: rewrite this as a `TryFrom` implementation (see issue #85)
    //          - eliza, 03/09/2017
    #[inline] fn as_type(&self) -> ElfResult<Type> {
        match self.0 {
            0 => Ok(Type::Null)
          , 1 => Ok(Type::ProgramBits)
          , 2 => Ok(Type::SymbolTable)
          , 3 => Ok(Type::StringTable)
          , 4 => Ok(Type::Rela)
          , 5 => Ok(Type::HashTable)
          , 6 => Ok(Type::Dynamic)
          , 7 => Ok(Type::Notes)
          , 8 => Ok(Type::NoBits)
          , 9 => Ok(Type::Rel)
          , 10 => Ok(Type::Shlib)
          , 11 => Ok(Type::DynSymTable)
          , 14 => Ok(Type::InitArray)
          , 15 => Ok(Type::FiniArray)
          , 16 => Ok(Type::PreInitArray)
          , x @ SHT_LOOS ... SHT_HIOS => Ok(Type::OsSpecific(x))
          , x @ SHT_LOPROC ... SHT_HIPROC => Ok(Type::ProcessorSpecific(x))
          , x @ SHT_LOUSER ... SHT_HIUSER => Ok(Type::User(x))
          , _ => Err("Invalid section type!")
        }
    }
}

/// Enum representing an ELF file section type.
///
/// Refer to [Figure 4-9]: "Section Types, `sh_type`" in Section 4 of the
/// ELF standard for more information.
///
/// [Figure 4-9]:  http://www.sco.com/developers/gabi/latest/ch4.sheader.html#sh_type
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd)]
pub enum Type {
    /// Section type 0: `SHT_NULL`
    ///
    /// This value marks the section header as inactive; it does not have an
    /// associated section. Other members of the section header have
    /// undefined values.
    Null
  , /// Section type 1: `SHT_PROGBITS`
    ///
    /// The section holds information defined by the program, whose format and
    /// meaning are determined solely by the program.
    ProgramBits
  , /// Section type 2: `SHT_SYMTAB`
    ///
    /// Typically, `SHT_SYMTAB` provides symbols for link editing, though it
    /// may also be used for dynamic linking. As a complete symbol table, it
    /// may contain many symbols unneces- sary for dynamic linking.
    ///
    /// Consequently, an object file may also contain a `SHT_DYNSYM` section,
    /// which holds a minimal set of dynamic linking symbols, to save space.
    SymbolTable
  , /// Section type 3: `SHT_STRTAB`
    ///
    /// The section holds a string table. An object file may have multiple
    /// string table sections.
    StringTable
  , /// Section type 4: `SHT_RELA`
    ///
    /// The section holds relocation entries with explicit addends, such as
    /// type `Elf32_Rela` for the 32-bit class of object files. An object file
    /// may have multiple relocation sections.
    Rela
  , /// Section type 5: `SHT_HASH`
    ///
    /// The section holds a symbol hash table. All objects participating in
    /// dynamic linking must contain a symbol hash table. Currently, an object
    /// file may have only one hash table, but this restriction may be relaxed
    /// in the future.
    HashTable
  , /// Section type 6: `SHT_DYNAMIC`
    ///
    /// The section holds information for dynamic linking. Currently, an object
    /// file may have only one dynamic section, but this restriction may be
    ///  relaxed in the future.
    Dynamic
  , /// Section type 7: `SHT_NOTE`
    ///
    /// The section holds information that marks the file in some way.
    Notes
  , /// Section type 8: `SHT_NOBITS`
    ///
    /// A section of this type occupies no space in the file but otherwise
    /// resembles `SHT_PROGBITS`. Although this section contains no bytes, the
    /// `sh_offset` member contains the conceptual file offset.
    NoBits
  , /// Section type 9: `SHT_REL`
    ///
    /// The section holds relocation entries without explicit addends, such as
    /// type `Elf32_Rel` for the 32-bit class of object files. An object file
    /// may have multiple reloca- tion sections.
    Rel
  , /// Section type 10: `SHT_SHLIB`
    ///
    /// This section type is reserved but has unspecified semantics. Programs
    /// that contain a section of this type do not conform to the ABI.
    Shlib
  , /// Section type 11: `SHT_DYNSYM`
    ///
    /// Typically, `SHT_SYMTAB` provides symbols for link editing, though it
    /// may also be used for dynamic linking. As a complete symbol table, it
    /// may contain many symbols unneces- sary for dynamic linking.
    ///
    /// Consequently, an object file may also contain a `SHT_DYNSYM` section,
    /// which holds a minimal set of dynamic linking symbols, to save space.
    DynSymTable
  , InitArray
  , FiniArray
  , PreInitArray
  , Group
  , SymbolTableShIndex
  , OsSpecific(u32)
  , ProcessorSpecific(u32)
  , User(u32)
}

/// Iterator over ELF64 sections
#[derive(Clone,Debug)]
pub struct Sections<'a, W: 'a>
where W: ElfWord { curr: &'a HeaderRepr<W>
                 , remaining: u32
                 , size: u32
                 }

impl<'a, W: 'a> Sections<'a, W>
where W: ElfWord {

    pub fn new(curr: &'a HeaderRepr<W>, remaining: u32, size: u32)
               -> Sections<'a, W>
    {
        Sections { curr: curr, remaining: remaining, size: size }

    }

}


impl<'a, W> Iterator for Sections<'a, W>
where W: ElfWord
    , HeaderRepr<W>: Header<Word = W> {
    type Item = &'a Header<Word = W>;

    fn next(&mut self) -> Option<Self::Item> {
        if self.remaining == 0 {
            None
        } else {
            let current = self.curr;
            self.curr =  unsafe {
                (self.curr as *const HeaderRepr<W>).offset(1)
                    .as_ref()
                    .expect("Expected an ELF section header, but got a null \
                             pointer!\nThis shouldn't happen!")
            };
            self.remaining -= 1;
            if current.get_type().unwrap() == Type::Null {
                self.next()
            } else {
                Some(current)
            }
        }
    }
}

/// Characters in the ELF string table are 8-bit ASCII characters.
type ElfChar = u8;

/// An ELF string table.
///
/// Refer to the String Table [entry] in Section 4 of the ELF standard
/// for more information.
///
/// [entry]: http://www.sco.com/developers/gabi/latest/ch4.strtab.html
//  TODO: this should be indexable by string number, possibly?
//          - eliza, 03/07/2017
//  TODO: add a function to get the name of the section (which always lives)
//        at index 0.
//          - eliza, 03/07/2017
#[derive(Clone, Debug)]
pub struct StrTable<'a>(&'a [ElfChar]);

impl<'a> convert::From<&'a [ElfChar]> for StrTable<'a> {
    #[inline(always)]
    fn from(binary: &'a [ElfChar]) -> Self { StrTable(binary) }
}

impl<'a> StrTable<'a> {

    /// Returns the string at a given index in the string table,
    /// if there is one.
    // TODO: these docs are Bad
    //          - eliza, 03/07/2017
    // TODO: this def. shouldn't be u64, but i didn't want to annotate the
    //       string table type with ElfWord...figure this out
    //          - eliza, 03/07/2017
    // TODO: can this be replaced with an ops::Index implementation?
    //       but then we can't implement Deref to a slice any more?
    //          - eliza, 03/07/2017
    pub fn at_index(&'a self, i: usize) -> Option<&'a str> {
        use core::str::from_utf8_unchecked;
        if i <= self.len() {
            read_to_null(&self[i..])
                .map(|bytes| unsafe {
                    // TODO: should this be checked, or do we assume the ELF
                    //       binary has only well-formed strings? this could be
                    //       a Security Thing...
                    //          - eliza, 03/07/2017
                    from_utf8_unchecked(bytes)
                    // TODO: can the conversion to a Rust string be moved to
                    //       `read_to_null()`? we also do this in the iterator
                    //          - eliza, 03/07/2017
                })

        } else {
            None
        }
    }
}

// impl<'a> StrTable<'a> {
Download .txt
gitextract_7fg8ki17/

├── .editorconfig
├── .gitignore
├── .gitmodules
├── .travis.yml
├── BUILDING.md
├── Brewfile
├── CHANGES.md
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── Cargo.toml
├── LICENSE-APACHE
├── LICENSE-MIT
├── Makefile
├── Notes.md
├── README.md
├── Vagrantfile
├── Xargo.toml
├── boot/
│   ├── Cargo.toml
│   ├── README.md
│   └── src/
│       └── lib.rs
├── build.rs
├── cpu/
│   ├── Cargo.toml
│   └── src/
│       ├── armv7/
│       │   └── mod.rs
│       ├── lib.rs
│       ├── x86/
│       │   ├── cpu.rs
│       │   └── mod.rs
│       ├── x86_64/
│       │   ├── context.rs
│       │   ├── mod.rs
│       │   ├── msr.rs
│       │   └── task.rs
│       └── x86_all/
│           ├── control_regs/
│           │   ├── cr0.rs
│           │   ├── cr4.rs
│           │   └── mod.rs
│           ├── dtable.rs
│           ├── flags.rs
│           ├── interrupts/
│           │   ├── idt/
│           │   │   ├── gate32.rs
│           │   │   ├── gate64.rs
│           │   │   ├── mod.rs
│           │   │   └── tests.rs
│           │   ├── mod.rs
│           │   └── pics.rs
│           ├── mod.rs
│           ├── segment.rs
│           └── timer.rs
├── elf/
│   ├── Cargo.toml
│   ├── README.md
│   └── src/
│       ├── file.rs
│       ├── lib.rs
│       ├── program.rs
│       └── section.rs
├── memory/
│   ├── Cargo.toml
│   └── src/
│       ├── arch/
│       │   ├── mod.rs
│       │   ├── x86/
│       │   │   └── mod.rs
│       │   └── x86_64/
│       │       └── mod.rs
│       ├── lib.rs
│       └── macros.rs
├── paging/
│   ├── Cargo.toml
│   └── src/
│       ├── arch/
│       │   ├── mod.rs
│       │   └── x86_64/
│       │       ├── cr3.rs
│       │       ├── mod.rs
│       │       ├── table.rs
│       │       ├── temp.rs
│       │       └── tlb.rs
│       ├── lib.rs
│       └── stack.rs
├── params/
│   ├── Cargo.toml
│   └── src/
│       ├── lib.rs
│       └── mem.rs
├── rustfmt.toml
├── scripts/
│   ├── README.md
│   ├── install-env-linux.sh
│   ├── install-env-mac.sh
│   └── install-env.sh
├── sos_alloc/
│   ├── Cargo.toml
│   └── src/
│       ├── borrow.rs
│       ├── buddy/
│       │   ├── math.rs
│       │   ├── mod.rs
│       │   ├── system.rs
│       │   └── test.rs
│       ├── bump_ptr.rs
│       ├── first_fit.rs
│       ├── frame/
│       │   ├── mem_map.rs
│       │   └── mod.rs
│       ├── free.rs
│       ├── lib.rs
│       ├── place.rs
│       └── system.rs
├── sos_intrusive/
│   ├── Cargo.toml
│   └── src/
│       ├── lib.rs
│       ├── list/
│       │   ├── mod.rs
│       │   └── test.rs
│       ├── rawlink.rs
│       └── stack/
│           ├── mod.rs
│           └── test.rs
├── src/
│   ├── arch/
│   │   ├── README.md
│   │   ├── mod.rs
│   │   ├── x86_64/
│   │   │   ├── boot.asm
│   │   │   ├── drivers/
│   │   │   │   ├── mod.rs
│   │   │   │   ├── serial.rs
│   │   │   │   └── vga.rs
│   │   │   ├── grub.cfg
│   │   │   ├── interrupts.rs
│   │   │   ├── linker.ld
│   │   │   └── mod.rs
│   │   └── x86_all/
│   │       ├── bda.rs
│   │       └── multiboot2.rs
│   ├── heap.rs
│   ├── io/
│   │   ├── keyboard.rs
│   │   ├── mod.rs
│   │   └── term.rs
│   ├── logger.rs
│   └── main.rs
├── targets/
│   ├── x86_32-sos-bootstrap-gnu.json
│   └── x86_64-sos-kernel-gnu.json
├── tokamak.toml
├── util/
│   ├── Cargo.toml
│   └── src/
│       ├── io.rs
│       ├── lib.rs
│       └── macros/
│           ├── mod.rs
│           └── newtype_impl.rs
└── vga/
    ├── Cargo.toml
    └── src/
        ├── kinfo.rs
        ├── lib.rs
        ├── panic.rs
        └── status.rs
Download .txt
SYMBOL INDEX (942 symbols across 71 files)

FILE: boot/src/lib.rs
  constant TABLE_LENGTH (line 45) | const TABLE_LENGTH: usize = 512;
  constant HUGE_PAGE_SIZE (line 47) | const HUGE_PAGE_SIZE: u64 = 2 * 1024 * 1024;
  constant ENTRY_FLAGS_PW (line 49) | const ENTRY_FLAGS_PW: u64 = 0b11;
  type Table (line 52) | type Table = [TableEntry; TABLE_LENGTH];
  type PageTable (line 54) | trait PageTable: Sized {
    method set_top_level (line 57) | unsafe fn set_top_level(&'static self) {
  type TableEntry (line 71) | struct TableEntry(u64);
    method map_to_table (line 78) | unsafe fn map_to_table(&mut self, to: &'static Table) {
    method map_to_page (line 84) | unsafe fn map_to_page(&mut self, number: usize) {
  type Gdt (line 110) | pub struct Gdt { _null: u64
  type GdtPointer (line 115) | pub struct GdtPointer { /// the length of the GDT
    method load (line 123) | unsafe fn load (&self) {
    method from (line 130) | fn from(gdt: &'static Gdt) -> Self {
  function boot_write (line 146) | fn boot_write(s: &[u8]) {
  function create_page_tables (line 167) | unsafe fn create_page_tables() {
  function set_long_mode (line 188) | unsafe fn set_long_mode() {
  function is_multiboot_supported (line 221) | unsafe fn is_multiboot_supported() -> bool {
  function _start (line 232) | pub unsafe extern "C" fn _start() {
  function panic_fmt (line 263) | fn panic_fmt() -> ! {

FILE: build.rs
  function main (line 3) | fn main() {

FILE: cpu/src/armv7/mod.rs
  constant ARCH_BITS (line 12) | pub const ARCH_BITS: u8 = 64;

FILE: cpu/src/lib.rs
  type Port (line 51) | pub struct Port<T> { raw_port: UnsafePort

FILE: cpu/src/x86/mod.rs
  constant ARCH_BITS (line 16) | pub const ARCH_BITS: u8 = 32;

FILE: cpu/src/x86_64/context.rs
  type Registers (line 22) | pub struct Registers { pub rsi: u64
    method to_array (line 38) | pub unsafe fn to_array(&self) -> [u64; 9] {
    method empty (line 48) | pub const fn empty() -> Self {
    method push (line 61) | pub unsafe fn push() {
    method pop (line 81) | pub unsafe fn pop() {
    method fmt (line 97) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  type InterruptFrame (line 111) | pub struct InterruptFrame {
    method fmt (line 145) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  function test_interrupt_frame_correct_size (line 136) | fn test_interrupt_frame_correct_size() {
  type Context (line 165) | pub struct Context { /// Value of the stack pointer (`rsp`) register
    method empty (line 175) | pub fn empty() -> Self {

FILE: cpu/src/x86_64/msr.rs
  constant IA32_EFER (line 12) | pub const IA32_EFER: u32 = 0xc0000080;
  function write (line 19) | pub unsafe fn write(msr: u32, value: u64) {
  function read (line 29) | pub unsafe fn read(msr: u32) -> u64 {
  function enable_nxe (line 44) | pub unsafe fn enable_nxe() {

FILE: cpu/src/x86_64/task.rs
  type StateDescriptor (line 15) | pub struct StateDescriptor { pub upper: segment::Descriptor
  type StateSegment (line 23) | pub struct StateSegment {
    method new (line 40) | pub const fn new() -> Self {

FILE: cpu/src/x86_all/control_regs/cr0.rs
  function read (line 116) | pub unsafe fn read() -> Flags {
  function write (line 129) | pub unsafe fn write(flags: Flags) {
  method fmt (line 136) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {

FILE: cpu/src/x86_all/control_regs/cr4.rs
  function read (line 8) | pub unsafe fn read() -> Flags {
  function write (line 21) | pub unsafe fn write(flags: Flags) {
  method fmt (line 111) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {

FILE: cpu/src/x86_all/control_regs/mod.rs
  type CrState (line 21) | pub struct CrState { /// `%cr0` contains flags that control the CPU's op...
    method fmt (line 35) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  function dump (line 42) | pub fn dump() -> CrState {
  function read (line 72) | pub unsafe fn read() -> usize {
  function write (line 85) | pub unsafe fn write(value: usize) {
  function read (line 105) | pub unsafe fn read() -> PAddr {
  function read (line 119) | pub unsafe fn read() -> PAddr {
  function write (line 133) | pub unsafe fn write(addr: PAddr) {
  function write (line 147) | pub unsafe fn write(addr: PAddr) {
  function current_pagetable_frame (line 159) | pub unsafe fn current_pagetable_frame() -> PhysicalPage {
  function set_pagetable_frame (line 169) | pub unsafe fn set_pagetable_frame(frame: PhysicalPage) {

FILE: cpu/src/x86_all/dtable.rs
  type Pointer (line 21) | pub struct Pointer<T: DTable> { /// the length of the descriptor table
  type DTable (line 42) | pub trait DTable: Sized {
    method get_ptr (line 78) | fn get_ptr(&self) -> Pointer<Self> {
    method entry_count (line 88) | fn entry_count(&self) -> usize;
    method load (line 91) | fn load(&'static self);

FILE: cpu/src/x86_all/flags.rs
  method iopl (line 86) | pub fn iopl(&self) -> PrivilegeLevel {
  function read (line 94) | pub fn read() -> Flags {

FILE: cpu/src/x86_all/interrupts/idt/gate32.rs
  type Gate (line 28) | pub struct Gate { /// bits 0 - 15 of the offset
    method absent (line 67) | pub const fn absent() -> Self {
    method from (line 84) | fn from(handler: ErrorCodeHandler) -> Self {
    method from (line 105) | fn from(handler: ErrorCodeHandler) -> Self {
  method new_trap (line 47) | pub const fn new_trap() -> Self {
  method new_interrupt (line 52) | pub const fn new_interrupt() -> Self {

FILE: cpu/src/x86_all/interrupts/idt/gate64.rs
  method new_trap (line 20) | pub const fn new_trap() -> Self {
  method new_task (line 25) | pub const fn new_task() -> Self {
  method new_interrupt (line 30) | pub const fn new_interrupt() -> Self {
  type Gate (line 47) | pub struct Gate<H = InterruptHandler>
    method from (line 185) | fn from(handler: *const u8) -> Self {
  function absent (line 78) | pub const fn absent() -> Self {
  function set_handler (line 92) | pub fn set_handler<F>(&mut self, handler: F) -> &mut Self
  function set_trap (line 100) | pub fn set_trap(&mut self) -> &mut Self {
  method default (line 109) | fn default() -> Self {
  type Target (line 123) | type Target = GateFlags;
  function deref (line 125) | fn deref(&self) -> &Self::Target { &self.flags }
  function deref_mut (line 129) | fn deref_mut(&mut self) -> &mut Self::Target { &mut self.flags }
  function from (line 138) | fn from(handler: InterruptHandler) -> Self {
  function from (line 159) | fn from(handler: ErrorCodeHandler) -> Self {

FILE: cpu/src/x86_all/interrupts/idt/mod.rs
  constant ENTRIES (line 17) | pub const ENTRIES: usize = 256;
  method is_trap (line 102) | pub fn is_trap(&self) -> bool {
  method is_present (line 107) | pub fn is_present(&self) -> bool {
  method set_present (line 112) | pub fn set_present(&mut self, present: bool) -> &mut Self {
  method get_dpl (line 119) | pub fn get_dpl(&self) -> PrivilegeLevel {
  method set_dpl (line 124) | pub fn set_dpl(&mut self, dpl: PrivilegeLevel) -> &mut Self {
  method default (line 133) | fn default() -> Self { GateFlags { bits: 0 } }
  type Idt (line 143) | pub struct Idt {
    type Output (line 184) | type Output = Gate;
    method index (line 187) | fn index(&self, index: usize) -> &Gate {
    method index_mut (line 197) | fn index_mut(&mut self, index: usize) -> &mut Self::Output {
    method new (line 209) | pub const fn new() -> Self {
    method enable_interrupts (line 239) | pub unsafe fn enable_interrupts() { asm!("sti") }
    method disable_interrupts (line 241) | pub unsafe fn disable_interrupts() { asm!("cli") }
    method add_handler (line 245) | pub fn add_handler<Handler>( &mut self
    method add_gate (line 255) | pub fn add_gate(&mut self, idx: usize, gate: Gate) -> &mut Self {
  method default (line 175) | fn default() -> Self {
  type Entry (line 263) | type Entry = Gate;
  method entry_count (line 265) | fn entry_count(&self) -> usize { ENTRIES }
  method load (line 267) | fn load(&'static self) {

FILE: cpu/src/x86_all/interrupts/idt/tests.rs
  function test_task_gate_32 (line 1) | fn test_task_gate_32() { assert_eq!(super::TASK_GATE_32.bits, 5)}
  function test_int_gate_32 (line 2) | fn test_int_gate_32() { assert_eq!(super::INT_GATE_32.bits, 14)}
  function test_trap_gate_32 (line 4) | fn test_trap_gate_32() { assert_eq!(super::TRAP_GATE_32.bits, 16)}

FILE: cpu/src/x86_all/interrupts/mod.rs
  constant NUM_EXCEPTIONS (line 28) | pub const NUM_EXCEPTIONS: usize = 32;
  type InterruptHandler (line 31) | pub type InterruptHandler = extern "x86-interrupt" fn (&InterruptFrame);
  type ErrorCodeHandler (line 33) | pub type ErrorCodeHandler = extern "x86-interrupt" fn (&InterruptFrame, ...
  type ExceptionInfo (line 37) | pub struct ExceptionInfo { /// The name of the exception
  method fmt (line 73) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  function timer (line 89) | pub extern "x86-interrupt" fn timer(_frame: &InterruptFrame) {
  function page_fault (line 99) | pub extern "x86-interrupt" fn page_fault( frame: &InterruptFrame, error_...
  function test (line 117) | pub extern "x86-interrupt" fn test(_frame: &InterruptFrame) {

FILE: cpu/src/x86_all/interrupts/pics.rs
  constant OFFSET (line 29) | const OFFSET: u8 = 0x20;
  constant FOLLOWER_CMD_PORT (line 31) | const FOLLOWER_CMD_PORT: u16 = 0xA0;
  constant LEADER_CMD_PORT (line 33) | const LEADER_CMD_PORT: u16 = OFFSET as u16;
  type Command (line 38) | enum Command { /// Command to set the PIC to 8086 mode
  type IRQ (line 55) | pub enum IRQ { /// System timer IRQ
  type PIC (line 85) | pub struct PIC {
    method leader (line 97) | pub const fn leader() -> PIC {
    method follower (line 105) | pub const fn follower() -> PIC {
    method is_leader (line 114) | pub fn is_leader(&self) -> bool {
    method send_command (line 120) | fn send_command(&self, command: Command) {
    method send_data (line 127) | pub fn send_data(&self, data: u8) {
    method initialize (line 134) | pub fn initialize(&self) {
    method read_isr (line 140) | pub fn read_isr(&self) -> u8 {
    method read_irr (line 147) | pub fn read_irr(&self) -> u8 {
  type IRQHandler (line 155) | trait IRQHandler {
    method handles (line 157) | fn handles(&self, irq: IRQ) -> bool;
    method end_interrupt (line 159) | fn end_interrupt(&self, irq: IRQ);
    method handles (line 164) | fn handles(&self, irq: IRQ) -> bool {
    method end_interrupt (line 168) | fn end_interrupt(&self, _: IRQ) {
    method handles (line 227) | fn handles(&self, irq: IRQ) -> bool {
    method end_interrupt (line 232) | fn end_interrupt(&self, irq: IRQ) {
  type BothPICs (line 176) | struct BothPICs (PIC, PIC);
    method new (line 181) | const fn new() -> Self {
    method initialize (line 186) | pub unsafe fn initialize(&mut self) {
  function initialize (line 251) | pub unsafe fn initialize() {
  function end_pic_interrupt (line 265) | pub unsafe fn end_pic_interrupt(interrupt_id: u8) {

FILE: cpu/src/x86_all/mod.rs
  type PrivilegeLevel (line 51) | pub enum PrivilegeLevel { /// Ring 0 is the most privileged ring
    method current_iopl (line 62) | pub fn current_iopl() -> Self { flags::read().iopl() }
  type UnsafePort (line 65) | pub struct UnsafePort(u16);
    method new (line 69) | pub const unsafe fn new(number: u16) -> UnsafePort { UnsafePort(number) }
    method in8 (line 72) | pub unsafe fn in8(&self) -> u8 {
    method in16 (line 82) | pub unsafe fn in16(&self) -> u16 {
    method in32 (line 93) | pub unsafe fn in32(&self) -> u32 {
    method out8 (line 103) | pub unsafe fn out8(&self, value: u8) {
    method out16 (line 111) | pub unsafe fn out16(&self, value: u16) {
    method out32 (line 119) | pub unsafe fn out32(&self, value: u32) {
    type Error (line 130) | type Error = Void;
    method read (line 133) | fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
    method read_all (line 146) | fn read_all(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
    type Error (line 161) | type Error = Void;
    method write (line 163) | fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {

FILE: cpu/src/x86_all/segment.rs
  constant GDT_SIZE (line 26) | pub const GDT_SIZE: usize = 2;
  type Gdt (line 31) | pub struct Gdt { _null: Descriptor
    type Entry (line 46) | type Entry = Descriptor;
    method entry_count (line 51) | fn entry_count(&self) -> usize { GDT_SIZE }
    method load (line 54) | fn load(&self) {
  constant GDT_SIZE (line 40) | pub const GDT_SIZE: usize = 512;
  type Gdt (line 43) | pub type Gdt = [Descriptor; GDT_SIZE];
    type Entry (line 46) | type Entry = Descriptor;
    method entry_count (line 51) | fn entry_count(&self) -> usize { GDT_SIZE }
    method load (line 54) | fn load(&self) {
  method new (line 121) | pub const fn new(index: u16) -> Self {
  method from_raw (line 126) | pub const fn from_raw(bits: u16) -> Self {
  method from_cs (line 131) | pub fn from_cs() -> Self {
  method index (line 142) | pub fn index(&self) -> u16 {
  method set_global (line 149) | pub fn set_global(&mut self) -> &mut Self {
  method set_local (line 157) | pub fn set_local(&mut self) -> &mut Self {
  method set_rpl (line 165) | pub fn set_rpl(&mut self, rpl: PrivilegeLevel) -> &mut Self {
  method get_rpl (line 171) | pub fn get_rpl(&self) -> PrivilegeLevel {
  method load_ss (line 177) | pub unsafe fn load_ss(&self) {
  method load_ds (line 185) | pub unsafe fn load_ds(&self) {
  method load_es (line 193) | pub unsafe fn load_es(&self) {
  method load_fs (line 201) | pub unsafe fn load_fs(&self) {
  method load_gs (line 209) | pub unsafe fn load_gs(&self) {
  method load_cs (line 223) | pub unsafe fn load_cs(&self) {
  method default (line 238) | fn default() -> Self { Selector::from_cs() }
  method fmt (line 242) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  type Descriptor (line 264) | pub struct Descriptor { /// The last 8 bits of the base address
    method null (line 279) | pub const fn null() -> Self {
    method new (line 289) | pub fn new(base: u32, limit: u32) -> Self {
    method get_limit (line 305) | pub fn get_limit(&self) -> u32 {
  method default (line 313) | fn default() -> Self { Descriptor::null() }
  method null (line 352) | pub const fn null() -> Self {
  method from_raw (line 357) | pub const fn from_raw(bits: u16) -> Self {
  method get_dpl (line 362) | pub fn get_dpl(&self) -> PrivilegeLevel {
  method is_system (line 369) | pub fn is_system(&self) -> bool {
  method is_present (line 374) | pub fn is_present(&self) -> bool {
  method is_available (line 379) | pub fn is_available(&self) -> bool {
  method is_accessed (line 386) | pub fn is_accessed(&self) -> bool {
  method get_system_type (line 395) | pub fn get_system_type(&self) -> Option<SysType> {
  method get_code_type (line 408) | pub fn get_code_type(&self) -> Option<CodeFlags> {
  method get_data_type (line 421) | pub fn get_data_type(&self) -> Option<DataFlags> {
  method get_limit_part (line 430) | fn get_limit_part(&self) -> u32 {
  type Type (line 438) | pub enum Type { /// The type bits interpreted as a system segment
  type SysType (line 449) | pub enum SysType { /// System segment used for storing a local descripto...
  method is_read_only (line 477) | pub fn is_read_only(&self) -> bool {
  method is_accessed (line 482) | pub fn is_accessed(&self) -> bool {
  method is_expand_down (line 487) | pub fn is_expand_down(&self) -> bool {
  method is_exec_only (line 510) | pub fn is_exec_only(&self) -> bool {
  method is_readable (line 515) | pub fn is_readable(&self) -> bool {
  method is_accessed (line 520) | pub fn is_accessed(&self) -> bool {
  method is_conforming (line 525) | pub fn is_conforming(&self) -> bool {

FILE: cpu/src/x86_all/timer.rs
  function rtdsc (line 21) | pub unsafe fn rtdsc() -> u64 {
  function rtdscp (line 33) | pub unsafe fn rtdscp() -> u64 {
  function is_available (line 43) | pub fn is_available() -> Result<(), &'static str> {
  function get_timestamp (line 58) | pub fn get_timestamp() -> Result<u64, &'static str> {
  function wait_get_timestamp (line 65) | pub fn wait_get_timestamp() -> Result<u64, &'static str> {

FILE: elf/src/file.rs
  type Header (line 33) | pub trait Header: Sized {
    method from_slice (line 37) | fn from_slice<'a>(input: &'a [u8]) -> ElfResult<&'a Self>;
    method parse_section (line 42) | fn parse_section<'a>(&'a self, input: &'a [u8], idx: u16)
    method sh_range (line 45) | fn sh_range(&self) -> Range<usize> {
    method ph_range (line 50) | fn ph_range(&self) -> Range<usize> {
    method section_index (line 60) | fn section_index(&self, idx: usize) -> Range<usize> {
    method program_header_index (line 70) | fn program_header_index(&self, idx: usize) -> Range<usize> {
    method ident (line 77) | fn ident(&self) -> Ident;
    method get_type (line 78) | fn get_type(&self) -> Type;
    method machine (line 79) | fn machine(&self) -> Machine;
    method entry_point (line 81) | fn entry_point(&self) -> usize;
    method ph_offset (line 83) | fn ph_offset(&self) -> usize;
    method ph_count (line 85) | fn ph_count(&self) -> usize;
    method ph_entry_size (line 87) | fn ph_entry_size(&self) -> usize;
    method sh_offset (line 91) | fn sh_offset(&self) -> usize;
    method sh_count (line 95) | fn sh_count(&self) -> usize;
    method sh_entry_size (line 99) | fn sh_entry_size(&self) -> usize;
    method flags (line 102) | fn flags(&self) -> u32;
    method sh_str_idx (line 106) | fn sh_str_idx(&self) -> usize;
  constant MAGIC (line 226) | pub const MAGIC: Magic = [0x7f, b'E', b'L', b'F'];
  type Magic (line 229) | pub type Magic = [u8; 4];
  type Ident (line 235) | pub struct Ident {
    method check_magic (line 256) | pub fn check_magic(&self) -> bool { self.magic == MAGIC }
    method is_valid (line 259) | pub fn is_valid(&self) -> bool {
  type Class (line 272) | pub enum Class {
    method is_valid (line 284) | pub fn is_valid(&self) -> bool {
    method check (line 294) | fn check(&self) -> ElfResult<()> {
    method check (line 306) | fn check(&self) -> ElfResult<()> {
  type DataEncoding (line 322) | pub enum DataEncoding {
    method is_valid (line 336) | pub fn is_valid(&self) -> bool {
  type OsAbi (line 346) | pub enum OsAbi { /// Ox00 also represents "none"
  type Version (line 362) | pub enum Version { None = 0, Current = 1 }
  type TypeRepr (line 365) | struct TypeRepr(u16);
    method as_type (line 370) | pub fn as_type(&self) -> Type {
    method fmt (line 383) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  type Type (line 389) | pub enum Type { None
  type Machine (line 400) | pub enum Machine { None    = 0

FILE: elf/src/lib.rs
  type Section (line 85) | pub type Section<W> = section::Header<Word = W>;
  type ProgramHeader (line 86) | pub type ProgramHeader<W> = program::Header<Word = W>;
  type FileHeader (line 88) | pub type FileHeader<W> = file::HeaderRepr<W>;
  type ElfResult (line 91) | pub type ElfResult<T> = Result<T, &'static str>;
  type ElfWord (line 93) | pub trait ElfWord: Sized + Copy + Clone
  type DefaultWord (line 101) | type DefaultWord = u32;
  type DefaultWord (line 103) | type DefaultWord = u64;
  type ValidatesWord (line 106) | trait ValidatesWord<Word: ElfWord> {
    method check (line 107) | fn check(&self) -> ElfResult<()>;
  type Image (line 115) | pub struct Image< 'bytes             // lifetime of the byte slice
  function sh_str_table (line 148) | pub fn sh_str_table(&'a self) -> section::StrTable<'a> {
  type Error (line 167) | type Error = &'static str;
  function try_from (line 169) | fn try_from(bytes: &'a [u8]) -> ElfResult<Self> {
  function extract_from_slice (line 241) | unsafe fn extract_from_slice<'slice, T: Sized>( data: &'slice [u8]
  function into (line 270) | fn into(self) -> FrameRange {

FILE: elf/src/program.rs
  type Header (line 27) | pub trait Header: Sized {
    method ty (line 34) | fn ty(&self) -> Type;
    method offset (line 37) | fn offset(&self) -> usize;
    method vaddr (line 40) | fn vaddr(&self) -> Self::Word;
    method paddr (line 43) | fn paddr(&self) -> Self::Word;
    method file_size (line 48) | fn file_size(&self) -> usize;
    method mem_size (line 53) | fn mem_size(&self) -> usize;
    method flags (line 58) | fn flags(&self) -> Flags;
    method align (line 60) | fn align(&self) -> usize;
  type Type (line 95) | pub enum Type {

FILE: elf/src/section.rs
  constant SHN_UNDEF (line 17) | pub const SHN_UNDEF: u16        = 0;
  constant SHN_LORESERVE (line 18) | pub const SHN_LORESERVE: u16    = 0xff00;
  constant SHN_LOPROC (line 19) | pub const SHN_LOPROC: u16       = 0xff00;
  constant SHN_HIPROC (line 20) | pub const SHN_HIPROC: u16       = 0xff1f;
  constant SHN_LOOS (line 21) | pub const SHN_LOOS: u16         = 0xff20;
  constant SHN_HIOS (line 22) | pub const SHN_HIOS: u16         = 0xff3f;
  constant SHN_ABS (line 23) | pub const SHN_ABS: u16          = 0xfff1;
  constant SHN_COMMON (line 24) | pub const SHN_COMMON: u16       = 0xfff2;
  constant SHN_XINDEX (line 25) | pub const SHN_XINDEX: u16       = 0xffff;
  constant SHN_HIRESERVE (line 26) | pub const SHN_HIRESERVE: u16    = 0xffff;
  constant SHT_LOOS (line 28) | pub const SHT_LOOS: u32   = 0x60000000;
  constant SHT_HIOS (line 29) | pub const SHT_HIOS: u32   = 0x6fffffff;
  constant SHT_LOPROC (line 30) | pub const SHT_LOPROC: u32 = 0x70000000;
  constant SHT_HIPROC (line 31) | pub const SHT_HIPROC: u32 = 0x7fffffff;
  constant SHT_LOUSER (line 32) | pub const SHT_LOUSER: u32 = 0x80000000;
  constant SHT_HIUSER (line 33) | pub const SHT_HIUSER: u32 = 0xffffffff;
  type Header (line 46) | pub trait Header: fmt::Debug {
    method end_address (line 55) | fn end_address(&self) -> PAddr {
    method is_writable (line 60) | fn is_writable(&self) -> bool {
    method is_allocated (line 65) | fn is_allocated(&self) -> bool {
    method is_executable (line 70) | fn is_executable(&self) -> bool {
    method is_mergeable (line 75) | fn is_mergeable(&self) -> bool {
    method is_uniform (line 80) | fn is_uniform(&self) -> bool {
    method get_name (line 87) | fn get_name<'a>(&self, strtab: StrTable<'a>) -> &'a str {
    method name_offset (line 92) | fn name_offset(&self) -> u32;
    method get_type (line 94) | fn get_type(&self) -> ElfResult<Type>;
    method flags (line 95) | fn flags(&self) -> Flags;
    method address (line 96) | fn address(&self) -> PAddr;
    method offset (line 97) | fn offset(&self) -> usize;
    method length (line 100) | fn length(&self) -> usize;
    method link (line 101) | fn link(&self) -> u32;
    method info (line 102) | fn info(&self) -> u32;
    method address_align (line 103) | fn address_align(&self) -> Self::Word;
    method entry_length (line 104) | fn entry_length(&self) -> usize;
  function fmt (line 146) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  method fmt (line 216) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  type Contents (line 229) | pub enum Contents<'a> {
  type TypeRepr (line 247) | struct TypeRepr(u32);
    method as_type (line 252) | fn as_type(&self) -> ElfResult<Type> {
  type Type (line 284) | pub enum Type {
  type Sections (line 371) | pub struct Sections<'a, W: 'a>
  function new (line 380) | pub fn new(curr: &'a HeaderRepr<W>, remaining: u32, size: u32)
  type Item (line 393) | type Item = &'a Header<Word = W>;
  method next (line 395) | fn next(&mut self) -> Option<Self::Item> {
  type ElfChar (line 417) | type ElfChar = u8;
  type StrTable (line 431) | pub struct StrTable<'a>(&'a [ElfChar]);
  function from (line 435) | fn from(binary: &'a [ElfChar]) -> Self { StrTable(binary) }
  function at_index (line 450) | pub fn at_index(&'a self, i: usize) -> Option<&'a str> {
  type Target (line 476) | type Target = [ElfChar];
  function deref (line 478) | fn deref(&self) -> &Self::Target { self.0 }
  type IntoIter (line 482) | type IntoIter = Strings<'a>;
  type Item (line 483) | type Item = &'a str;
  method into_iter (line 487) | fn into_iter(self) -> Self::IntoIter { Strings(&self.0) }
  function is_null (line 491) | fn is_null(ch: &ElfChar) -> bool { *ch == b'\0' }
  function read_to_null (line 497) | fn read_to_null<'a>(bytes: &'a [ElfChar]) -> Option<&'a [ElfChar]> {
  type Strings (line 504) | pub struct Strings<'a>(&'a [ElfChar]);
  type Item (line 507) | type Item = &'a str;
  method next (line 509) | fn next(&mut self) -> Option<Self::Item> {
  method size_hint (line 541) | fn size_hint(&self) -> (usize, Option<usize>) {

FILE: memory/src/arch/x86/mod.rs
  type PAddr (line 13) | pub struct PAddr(u32);
    method into (line 19) | fn into(self) -> u32 { self.as_u32() }
    method from (line 23) | fn from(u: u32) -> Self { PAddr::from_u32(u) }
    method from (line 27) | fn from(ptr: *mut u8) -> Self { PAddr::from_ptr(ptr) }
    method from_ptr (line 31) | pub fn from_ptr(ptr: *mut u8) -> Self { PAddr(ptr as u32) }
    method from_u32 (line 32) | pub const fn from_u32(u: u32) -> Self { PAddr(u) }
    method as_u32 (line 33) | pub const fn as_u32(&self) -> u32 { self.0 }

FILE: memory/src/arch/x86_64/mod.rs
  constant PAGE_SHIFT (line 14) | pub const PAGE_SHIFT: u8 = 12;
  constant PAGE_SIZE (line 16) | pub const PAGE_SIZE: u64 = 1 << PAGE_SHIFT;
  constant LARGE_PAGE_SIZE (line 18) | pub const LARGE_PAGE_SIZE: u64 = 1024 * 1024 * 2;
  constant HUGE_PAGE_SIZE (line 20) | pub const HUGE_PAGE_SIZE: u64 = 1024 * 1024 * 1024;
  method fmt (line 38) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  type Output (line 44) | type Output = Self;
  method add (line 46) | fn add(self, rhs: usize) -> Self {
  type Output (line 52) | type Output = Self;
  method sub (line 54) | fn sub(self, rhs: usize) -> Self {
  method add_assign (line 60) | fn add_assign(&mut self, rhs: usize) {
  method sub_assign (line 66) | fn sub_assign(&mut self, rhs: usize) {
  method base_addr (line 75) | pub const fn base_addr(&self) -> PAddr {
  method containing_addr (line 81) | pub const fn containing_addr(addr: PAddr) -> PhysicalPage {
  method as_ptr (line 87) | pub unsafe fn as_ptr<T>(&self) -> *const T {
  method as_mut_ptr (line 93) | pub unsafe fn as_mut_ptr<T>(&self) -> *mut T {

FILE: memory/src/lib.rs
  type Addr (line 37) | pub trait Addr: ops::Add<Self> + ops::Sub<Self>
    method align_down (line 45) | fn align_down(&self, align: Self::Repr) -> Self;
    method align_up (line 46) | fn align_up(&self, align: Self::Repr) -> Self;
    method is_page_aligned (line 49) | fn is_page_aligned(&self) -> bool;
  method from_ptr (line 64) | pub fn from_ptr<T>(ptr: *mut T) -> Self { VAddr(ptr as usize) }
  method from_usize (line 67) | pub const fn from_usize(u: usize) -> Self { VAddr(u) }
  method as_usize (line 70) | pub const fn as_usize(&self) -> usize { self.0 }
  method pml4_index (line 73) | pub fn pml4_index(&self) -> usize {
  method pdpt_index (line 78) | pub fn pdpt_index(&self) -> usize {
  method pd_index (line 83) | pub fn pd_index(&self) -> usize {
  method pt_index (line 88) | pub fn pt_index(&self) -> usize {
  type PageRange (line 97) | pub type PageRange = Range<VirtualPage>;
  type FrameRange (line 98) | pub type FrameRange = Range<PhysicalPage>;
  type Page (line 102) | pub trait Page
    method containing (line 121) | fn containing(addr: Self::Address) -> Self;
    method base (line 124) | fn base(&self) -> Self::Address;
    method end_address (line 127) | fn end_address(&self) -> Self::Address;
    method range_of (line 143) | fn range_of(&self, n: usize) -> Range<Self> {
    method range_until (line 149) | fn range_until(&self, end: Self) -> Range<Self> {
    method number (line 153) | fn number(&self) -> usize;
  method containing_addr (line 165) | fn containing_addr( addr: VAddr) -> Self {
  method fmt (line 174) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  type MemRange (line 185) | pub trait MemRange {
    method length (line 188) | fn length(&self) -> usize;
    method drop_front (line 191) | fn drop_front(&mut self, n: usize) -> &mut Self;
    method drop_back (line 194) | fn drop_back(&mut self, n: usize) -> &mut Self;
    method add_front (line 197) | fn add_front(&mut self, n: usize) -> &mut Self;
    method add_back (line 200) | fn add_back(&mut self, n: usize) -> &mut Self;
    method length (line 219) | fn length(&self) -> usize {
    method drop_front (line 224) | fn drop_front(&mut self, n: usize) -> &mut Self {
    method drop_back (line 231) | fn drop_back(&mut self, n: usize) -> &mut Self {
    method add_front (line 238) | fn add_front(&mut self, n: usize) -> &mut Self {
    method add_back (line 244) | fn add_back(&mut self, n: usize) -> &mut Self {
  type RangeIter (line 251) | pub struct RangeIter<'a, P>
  type Item (line 258) | type Item = P;
  method next (line 260) | fn next(&mut self) -> Option<P> {

FILE: paging/src/arch/x86_64/cr3.rs
  function current_pml4 (line 13) | pub unsafe fn current_pml4() -> *mut Table<PML4Level> {
  function set_pml4 (line 23) | pub unsafe fn set_pml4(pml4: Table<PML4Level>) {

FILE: paging/src/arch/x86_64/mod.rs
  type ActivePageTable (line 31) | pub struct ActivePageTable { pml4: ActivePML4 }
    type Target (line 34) | type Target = ActivePML4;
    method deref (line 36) | fn deref(&self) -> &ActivePML4 {
    method deref_mut (line 42) | fn deref_mut(&mut self) -> &mut ActivePML4 {
    method new (line 48) | pub unsafe fn new() -> ActivePageTable {
    method using (line 54) | pub fn using<F>( &mut self
    method replace_with (line 103) | pub fn replace_with(&mut self, new_table: InactivePageTable)
  type ActivePML4 (line 127) | pub struct ActivePML4(Unique<Table<PML4Level>>);
    method fmt (line 130) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    method new (line 280) | pub unsafe fn new() -> Self {
    method pml4 (line 284) | fn pml4(&self) -> &Table<PML4Level> {
    method pml4_mut (line 288) | fn pml4_mut(&mut self) -> &mut Table<PML4Level> {
    method is_mapped (line 294) | pub fn is_mapped(&self, page: &VirtualPage) -> bool {
  type Flags (line 136) | type Flags = EntryFlags;
  method translate (line 138) | fn translate(&self, vaddr: VAddr) -> Option<PAddr> {
  method translate_page (line 144) | fn translate_page(&self, page: VirtualPage) -> Option<PhysicalPage> {
  method map (line 173) | fn map<A>( &mut self, page: VirtualPage, frame: PhysicalPage
  method identity_map (line 205) | fn identity_map<A>(&mut self, frame: PhysicalPage, flags: EntryFlags
  method map_to_any (line 215) | fn map_to_any<A>( &mut self
  method unmap (line 233) | fn unmap<A>(&mut self, page: VirtualPage, alloc: &mut A) -> MapResult<()>
  type InactivePageTable (line 303) | pub struct InactivePageTable {
    method new (line 308) | pub fn new( frame: PhysicalPage
  function test_paging (line 328) | pub fn test_paging<A>(alloc: &mut A) -> MapResult<()>
  function kernel_remap (line 368) | pub fn kernel_remap<A>(params: &InitParams, alloc: &mut A)

FILE: paging/src/arch/x86_64/table.rs
  constant N_ENTRIES (line 20) | pub const N_ENTRIES: usize = 512;
  constant PAGE_TABLE_SIZE (line 22) | pub const PAGE_TABLE_SIZE: usize = N_ENTRIES * PAGE_SIZE as usize;
  constant PML4_VADDR (line 25) | pub const PML4_VADDR: u64 =  0xffffffff_fffff000;
  constant PML4_PTR (line 28) | pub const PML4_PTR: *mut Table<PML4Level> = PML4_VADDR as *mut _;
  constant ENTRY_FLAGS_MASK (line 31) | pub const ENTRY_FLAGS_MASK: u64 = (PAGE_SIZE as u64 - 1) as u64;
  type Table (line 35) | pub struct Table<L>
  function fmt (line 43) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  type TableLevel (line 52) | pub trait TableLevel {
    constant ADDR_SHIFT_AMOUNT (line 54) | const ADDR_SHIFT_AMOUNT: usize;
    constant PAGE_SHIFT_AMOUNT (line 56) | const PAGE_SHIFT_AMOUNT: usize;
    constant INDEX_MASK (line 58) | const INDEX_MASK: usize = 0o777;
    constant ADDR_SHIFT_AMOUNT (line 104) | const ADDR_SHIFT_AMOUNT: usize = 39;
    constant PAGE_SHIFT_AMOUNT (line 105) | const PAGE_SHIFT_AMOUNT: usize = 27;
    constant ADDR_SHIFT_AMOUNT (line 108) | const ADDR_SHIFT_AMOUNT: usize = 30;
    constant PAGE_SHIFT_AMOUNT (line 109) | const PAGE_SHIFT_AMOUNT: usize = 18;
    constant ADDR_SHIFT_AMOUNT (line 112) | const ADDR_SHIFT_AMOUNT: usize = 21;
    constant PAGE_SHIFT_AMOUNT (line 113) | const PAGE_SHIFT_AMOUNT: usize = 9;
    constant ADDR_SHIFT_AMOUNT (line 116) | const ADDR_SHIFT_AMOUNT: usize = 12;
    constant PAGE_SHIFT_AMOUNT (line 117) | const PAGE_SHIFT_AMOUNT: usize = 0;
  type IndexOf (line 62) | pub trait IndexOf<I> {
    method index_of (line 63) | fn index_of(i: I) -> usize;
  method index_of (line 71) | fn index_of(addr: VAddr) -> usize {
  method index_of (line 81) | fn index_of(page: VirtualPage) -> usize {
  method index_of (line 92) | fn index_of(i: usize) -> usize { i }
  type PML4Level (line 96) | pub enum PML4Level {}
  type PDPTLevel (line 97) | pub enum PDPTLevel {}
  type PDLevel (line 98) | pub enum PDLevel   {}
  type PTLevel (line 99) | pub enum PTLevel   {}
  type Sublevel (line 120) | pub trait Sublevel: TableLevel {
    type Next (line 124) | type Next = PDPTLevel;
    type Next (line 127) | type Next = PDLevel;
    type Next (line 130) | type Next = PTLevel;
  function page_table_for (line 135) | pub fn page_table_for(&self, page: VirtualPage) -> Option<&Table<PTLevel...
  function page_table_mut_for (line 142) | pub fn page_table_mut_for(&mut self, page: VirtualPage)
  type Output (line 154) | type Output = Entry;
  function index (line 156) | fn index(&self, i: I) -> &Entry {
  function index_mut (line 164) | fn index_mut(&mut self, i: I) -> &mut Entry {
  function zero (line 173) | pub fn zero(&mut self) -> &mut Self {
  function start_paddr (line 184) | pub fn start_paddr(&self) -> PAddr {
  function frame (line 190) | pub fn frame(&self) -> PhysicalPage {
  function next_table_addr (line 201) | fn next_table_addr(&self, i: usize) -> Option<VAddr> {
  function next_table (line 213) | pub fn next_table<I>(&self, i: I) -> Option<&Table<L::Next>>
  function next_table_mut (line 221) | pub fn next_table_mut<I>(&self, i: I) -> Option<& mut Table<L::Next>>
  function create_next (line 231) | pub fn create_next<A>(&mut self, i: VirtualPage, alloc: &mut A)
  method is_huge (line 291) | pub fn is_huge(&self) -> bool {
  method is_present (line 297) | pub fn is_present(&self) -> bool {
  method set_present (line 302) | pub fn set_present(&mut self, present: bool) -> &mut Self {
  method set_writable (line 309) | pub fn set_writable(&mut self, writable: bool) -> &mut Self {
  method set_executable (line 316) | pub fn set_executable(&mut self, executable: bool) -> &mut Self {
  type Entry (line 324) | pub struct Entry(u64);
    method new (line 328) | pub fn new(addr: PAddr) -> Self {
    method do_huge (line 335) | pub fn do_huge(&self, offset: usize) -> Option<PhysicalPage> {
    method is_unused (line 350) | pub fn is_unused(&self) -> bool {
    method set_unused (line 356) | pub fn set_unused(&mut self) {
    method is_huge (line 362) | pub fn is_huge(&self) -> bool {
    method flags (line 368) | pub fn flags(&self) -> EntryFlags {
    method get_addr (line 374) | pub fn get_addr(&self) -> PAddr {
    method get_frame (line 379) | pub fn get_frame(&self) -> Option<PhysicalPage> {
    method set (line 388) | pub fn set(&mut self, frame: PhysicalPage, flags: EntryFlags) {
  method from (line 397) | fn from(section: &'a elf::Section<u64>) -> Self {

FILE: paging/src/arch/x86_64/temp.rs
  type TempPage (line 11) | pub struct TempPage { page: VirtualPage
    type Target (line 18) | type Target = VirtualPage;
    method deref (line 19) | fn deref(&self) -> &VirtualPage { &self.page }
    method deref_mut (line 23) | fn deref_mut(&mut self) -> &mut VirtualPage { &mut self.page }
    method new (line 34) | pub fn new<A>(number: usize, alloc: &mut A) -> Self
    method map_to (line 49) | pub fn map_to( &mut self
    method map_to_table (line 61) | pub fn map_to_table( &mut self
    method unmap (line 71) | pub fn unmap(&mut self, table: &mut ActivePageTable) -> MapResult<()> {
  type FrameCache (line 82) | pub struct FrameCache([Option<PhysicalPage>; 3]);
    method new (line 86) | pub fn new<A>(alloc: &mut A) -> Self
  method allocate (line 99) | unsafe fn allocate(&mut self) -> AllocResult<PhysicalPage> {
  method deallocate (line 110) | unsafe fn deallocate(&mut self, frame: PhysicalPage) {
  method allocate_range (line 117) | unsafe fn allocate_range(&mut self, _num: usize)
  method deallocate_range (line 122) | unsafe fn deallocate_range(&mut self, _range: FrameRange) {

FILE: paging/src/arch/x86_64/tlb.rs
  function flush_all (line 8) | pub unsafe fn flush_all() {
  type Flush (line 14) | pub trait Flush {
    method invlpg (line 19) | unsafe fn invlpg(self);
    method invlpg (line 42) | unsafe fn invlpg(self) {
    method invlpg (line 53) | unsafe fn invlpg(self) {

FILE: paging/src/lib.rs
  type MapResult (line 39) | pub type MapResult<T = ()> = Result<T, MapErr>;
  type MapErr (line 42) | pub enum MapErr<P: Page + fmt::Debug = VirtualPage> {
  function fmt (line 52) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  type Mapper (line 57) | pub trait Mapper {
    method translate (line 66) | fn translate(&self, vaddr: VAddr) -> Option<PAddr>;
    method translate_page (line 69) | fn translate_page(&self, page: VirtualPage) -> Option<PhysicalPage>;
    method map (line 78) | fn map<A>( &mut self, page: VirtualPage, frame: PhysicalPage
    method identity_map (line 89) | fn identity_map<A>( &mut self, frame: PhysicalPage
    method map_to_any (line 103) | fn map_to_any<A>( &mut self, page: VirtualPage
    method unmap (line 112) | fn unmap<A>(&mut self, page: VirtualPage, alloc: &mut A) -> MapResult<()>

FILE: paging/src/stack.rs
  type Stack (line 18) | pub type Stack = Range<VAddr>;
  type StackAllocator (line 20) | pub trait StackAllocator {
    method allocate (line 21) | fn allocate<A>( &mut self
    method allocate (line 30) | fn allocate<A>( &mut self

FILE: params/src/lib.rs
  constant MAX_MEM_AREAS (line 33) | const MAX_MEM_AREAS: usize = 32;
  type ElfSections (line 37) | pub type ElfSections = elf::section::Sections<'static, u64>;
  type ElfSections (line 41) | pub type ElfSections = elf::section::Sections<'static, u32>;
  type InitParams (line 45) | pub struct InitParams {
    method elf_sections (line 103) | pub fn elf_sections(&self) ->  ElfSections {
    method multiboot_start (line 116) | pub fn multiboot_start(&self) -> PAddr {
    method multiboot_end (line 128) | pub fn multiboot_end(&self) -> PAddr {
    method kernel_frames (line 142) | pub fn kernel_frames(&self) -> FrameRange {
    method heap_frames (line 155) | pub fn heap_frames(&self) -> FrameRange {
    method stack_frames (line 165) | pub fn stack_frames(&self) -> FrameRange {
    method mem_map (line 171) | pub fn mem_map(&self) -> mem::Map {
  method default (line 76) | fn default() -> Self {

FILE: params/src/mem.rs
  type Map (line 7) | pub type Map<'a> = Iter<'a, Area>;
  type Area (line 11) | pub struct Area {

FILE: sos_alloc/src/borrow.rs
  type Lender (line 6) | pub trait Lender {
    method borrow (line 8) | fn borrow(&self) -> Self::Borrowed;
  type BorrowedPtr (line 21) | pub struct BorrowedPtr<'alloc, A>
  function new (line 34) | pub fn new( ptr: Address
  type Target (line 49) | type Target = Unique<u8>;
  method deref (line 50) | fn deref(&self) ->  &Self::Target { &self.ptr }
  method drop (line 56) | fn drop(&mut self) {
  type Borrowed (line 69) | pub struct Borrowed<'alloc, A, T>
  function new (line 81) | pub fn new( value: Unique<T>, allocator: &'alloc Mutex<A>)
  type Target (line 93) | type Target = T;
  method deref (line 94) | fn deref(&self) ->  &Self::Target { unsafe { self.value.as_ref() } }
  method deref_mut (line 100) | fn deref_mut(&mut self) ->  &mut Self::Target {
  method drop (line 108) | fn drop(&mut self) {

FILE: sos_alloc/src/buddy/math.rs
  constant B (line 2) | const B: [usize; 5]
  constant S (line 7) | const S: [usize; 5] = [ 1, 2, 4, 8, 16 ];
  constant B (line 10) | const B: [usize; 6]
  constant S (line 16) | const S: [usize; 6] = [ 1, 2, 4, 8, 16, 32 ];
  type PowersOf2 (line 18) | pub trait PowersOf2 {
    method is_pow2 (line 19) | fn is_pow2(&self) -> bool;
    method next_pow2 (line 20) | fn next_pow2(&self) -> Self;
    method log2 (line 21) | fn log2(&self) -> Self;
    method is_pow2 (line 25) | fn is_pow2(&self) -> bool {
    method next_pow2 (line 30) | fn next_pow2(&self) -> usize {
    method log2 (line 46) | fn log2(&self) -> usize {
    method log2 (line 61) | fn log2(&self) -> usize {
  function test_next_pow2 (line 82) | fn test_next_pow2() {
  function test_is_pow2 (line 102) | fn test_is_pow2() {
  function test_log2 (line 116) | fn test_log2() {
  function our_next_pow2 (line 126) | fn our_next_pow2(b: &mut Bencher) {
  function std_next_power_of_two (line 138) | fn std_next_power_of_two(b: &mut Bencher) {
  function our_is_pow2 (line 150) | fn our_is_pow2(b: &mut Bencher) {
  function std_is_power_of_two (line 162) | fn std_is_power_of_two(b: &mut Bencher) {

FILE: sos_alloc/src/buddy/mod.rs
  type FreeList (line 33) | pub type FreeList = List<Unique<FreeBlock>, FreeBlock>;
  type FreeBlock (line 36) | pub struct FreeBlock { next: RawLink<FreeBlock>
    method as_ptr (line 40) | unsafe fn as_ptr(&self) -> *mut u8 { mem::transmute(self) }
  method prev (line 44) | fn prev(&self) -> &RawLink<FreeBlock> {
  method next (line 47) | fn next(&self) -> &RawLink<FreeBlock> {
  method prev_mut (line 50) | fn prev_mut(&mut self) -> &mut RawLink<FreeBlock> {
  method next_mut (line 53) | fn next_mut(&mut self) -> &mut RawLink<FreeBlock> {
  type Heap (line 66) | pub struct Heap<'a> {
  function new (line 104) | pub unsafe fn new( start_addr: Address
  function add_block (line 162) | pub unsafe fn add_block(&mut self, block: Address) {
  function alloc_size (line 179) | pub fn alloc_size(&self, layout: &Layout) -> Result<usize, AllocErr> {
  function alloc_order (line 220) | pub fn alloc_order(&self, layout: &Layout) -> Result<usize, AllocErr> {
  function order_alloc_size (line 232) | fn order_alloc_size(&self, order: usize) -> usize {
  function push_block (line 237) | unsafe fn push_block(&mut self, ptr: *mut u8, order: usize) {
  function pop_block (line 243) | unsafe fn pop_block(&mut self, order: usize) -> Option<*mut u8>{
  function split_block (line 269) | unsafe fn split_block( &mut self
  function get_buddy (line 307) | pub unsafe fn get_buddy( &self
  function remove_block (line 343) | pub fn remove_block(&mut self, order: usize, block: Address) -> bool {
  method alloc (line 364) | unsafe fn alloc(&mut self, layout: Layout) -> Result<Address, AllocErr> {
  method dealloc (line 409) | unsafe fn dealloc(&mut self, ptr: Address, layout: Layout) {

FILE: sos_alloc/src/buddy/system.rs
  constant NUM_FREE_LISTS (line 9) | pub const NUM_FREE_LISTS: usize = 19;
  function init_heap (line 33) | pub unsafe fn init_heap(start_addr: *mut u8, heap_size: usize ) {
  function __rust_allocate (line 46) | pub extern "C" fn __rust_allocate(size: usize, align: usize) -> *mut u8 {
  function __rust_deallocate (line 66) | pub extern "C" fn __rust_deallocate( ptr: *mut u8, old_size: usize
  function __rust_reallocate (line 77) | pub extern "C" fn __rust_reallocate( ptr: *mut u8, old_size: usize
  function __rust_reallocate_inplace (line 96) | pub extern "C" fn __rust_reallocate_inplace( _ptr: *mut u8
  function __rust_usable_size (line 105) | pub extern "C" fn __rust_usable_size(size: usize, _: usize) -> usize {
  type BuddyFrameAllocator (line 113) | pub struct BuddyFrameAllocator;
    method new (line 117) | pub const fn new() -> Self { BuddyFrameAllocator }

FILE: sos_alloc/src/buddy/test.rs
  function memalign (line 11) | fn memalign(alignment: usize, size: usize) -> *mut u8;
  function memalign (line 14) | fn memalign(alignment: usize, size: usize) -> *mut u8;
  function free (line 17) | fn free(ptr: *mut u8);
  constant HEAP_ALIGN (line 20) | const HEAP_ALIGN: usize = 4096;
  constant HEAP_SIZE (line 21) | const HEAP_SIZE: usize = 256;
  function test_allocation_size_and_order (line 24) | fn test_allocation_size_and_order() {
  function test_get_buddy (line 84) | fn test_get_buddy() {
  function test_alloc_and_dealloc (line 118) | fn test_alloc_and_dealloc() {

FILE: sos_alloc/src/bump_ptr.rs
  type BumpPtr (line 19) | pub struct BumpPtr { start: PAddr
    method new (line 25) | pub const fn new(start: PAddr, end: PAddr) -> Self {
  method alloc (line 34) | unsafe fn alloc(&mut self, layout: Layout) -> Result<Address, AllocErr> {
  method dealloc (line 46) | unsafe fn dealloc(&mut self, _ptr: Address, _layout: Layout) {

FILE: sos_alloc/src/first_fit.rs
  constant SIZE (line 6) | const SIZE: usize = 256;
  type FirstFit (line 9) | pub struct FirstFit<'a> {
  method allocate (line 15) | unsafe fn allocate(&self) -> Option<PhysicalPage> {
  method deallocate (line 19) | unsafe fn deallocate(&self, _frame: PhysicalPage) {
  method allocate_range (line 23) | unsafe fn allocate_range(&self, num: usize) -> Option<FrameRange> {
  method deallocate_range (line 37) | unsafe fn deallocate_range(&self, _range: FrameRange) {

FILE: sos_alloc/src/frame/mem_map.rs
  type MemMapAllocator (line 29) | pub struct MemMapAllocator<'a> { next_free: Frame
  function next_area (line 36) | fn next_area(&mut self) {
  function from (line 53) | fn from(params: &'a InitParams) -> Self {
  method allocate (line 74) | unsafe fn allocate(&mut self) -> AllocResult<Frame> {
  method deallocate (line 121) | unsafe fn deallocate(&mut self, _frame: Frame) {
  method allocate_range (line 126) | unsafe fn allocate_range(&mut self, _num: usize) -> AllocResult<FrameRan...
  method deallocate_range (line 130) | unsafe fn deallocate_range(&mut self, _range: FrameRange) {

FILE: sos_alloc/src/frame/mod.rs
  type Allocator (line 19) | pub trait Allocator: Sized  {
    method allocate (line 22) | unsafe fn allocate(&mut self) -> AllocResult<Frame>;
    method deallocate (line 24) | unsafe fn deallocate(&mut self, frame: Frame);
    method allocate_range (line 27) | unsafe fn allocate_range(&mut self, num: usize) -> AllocResult<FrameRa...
    method deallocate_range (line 29) | unsafe fn deallocate_range(&mut self, range: FrameRange);
  type Lender (line 36) | pub trait Lender<A>
    method borrow (line 50) | fn borrow(&self) -> AllocResult<BorrowedFrame<A>>;
    method borrow_range (line 69) | fn borrow_range(&self, num: usize) -> AllocResult<BorrowedFrameRange<A>>;
  function borrow (line 75) | fn borrow(&self) -> AllocResult<BorrowedFrame<A>> {
  function borrow_range (line 83) | fn borrow_range(&self, num: usize) -> AllocResult<BorrowedFrameRange<A>> {
  type BorrowedFrame (line 99) | pub struct BorrowedFrame<'alloc, A>
  type Target (line 109) | type Target = Frame;
  function deref (line 110) | fn deref(&self) ->  &Self::Target { &self.frame }
  function deref_mut (line 116) | fn deref_mut(&mut self) ->  &mut Self::Target { &mut self.frame }
  method drop (line 122) | fn drop(&mut self) {
  type BorrowedFrameRange (line 128) | pub struct BorrowedFrameRange<'alloc, A>
  type Target (line 138) | type Target = FrameRange;
  function deref (line 139) | fn deref(&self) -> &Self::Target { &self.range }
  function deref_mut (line 145) | fn deref_mut(&mut self) -> &mut Self::Target { &mut self.range }
  method drop (line 151) | fn drop(&mut self) {

FILE: sos_alloc/src/free.rs
  type List (line 8) | pub type List = IList<Unique<Block>, Block>;
  type Block (line 13) | pub struct Block { next: RawLink<Block>
    method as_ptr (line 17) | pub unsafe fn as_ptr(&self) -> *mut u8 { mem::transmute(self) }
  method prev (line 21) | fn prev(&self) -> &RawLink<Block> {
  method next (line 24) | fn next(&self) -> &RawLink<Block> {
  method prev_mut (line 27) | fn prev_mut(&mut self) -> &mut RawLink<Block> {
  method next_mut (line 30) | fn next_mut(&mut self) -> &mut RawLink<Block> {

FILE: sos_alloc/src/lib.rs
  type AllocResult (line 84) | pub type AllocResult<T> = Result<T, AllocErr>;
  type Size (line 86) | pub type Size = usize;
  type Capacity (line 87) | pub type Capacity = usize;
  type Alignment (line 88) | pub type Alignment = usize;
  type Address (line 90) | pub type Address = *mut u8;
  type Excess (line 97) | pub struct Excess(Address, Capacity);
  function size_align (line 99) | fn size_align<T>() -> (usize, usize) {
  type Layout (line 110) | pub struct Layout {
    method from_size_align (line 130) | pub fn from_size_align(size: usize, align: usize) -> Layout {
    method size (line 137) | pub fn size(&self) -> usize { self.size }
    method align (line 140) | pub fn align(&self) -> usize { self.align }
    method new (line 143) | pub fn new<T>() -> Self {
    method for_value (line 151) | pub fn for_value<T: ?Sized>(t: &T) -> Self {
    method align_to (line 167) | pub fn align_to(&self, align: Alignment) -> Self {
    method padding_needed_for (line 189) | pub fn padding_needed_for(&self, align: Alignment) -> usize {
    method repeat (line 204) | pub fn repeat(&self, n: usize) -> Option<(Self, usize)> {
    method extend (line 227) | pub fn extend(&self, next: Self) -> Option<(Self, usize)> {
    method repeat_packed (line 240) | pub fn repeat_packed(&self, n: usize) -> Option<Self> {
    method extend_packed (line 264) | pub fn extend_packed(&self, next: Self) -> Option<(Self, usize)> {
    method new_unchecked (line 281) | pub unsafe fn new_unchecked<T>() -> Self {
    method extend_unchecked (line 298) | pub unsafe fn extend_unchecked(&self, next: Self) -> (Self, usize) {
    method repeat_unchecked (line 307) | pub unsafe fn repeat_unchecked(&self, n: usize) -> (Self, usize) {
    method repeat_packed_unchecked (line 316) | pub unsafe fn repeat_packed_unchecked(&self, n: usize) -> Self {
    method extend_packed_unchecked (line 336) | pub unsafe fn extend_packed_unchecked(&self, next: Self) -> (Self, usi...
    method array (line 343) | pub fn array<T>(n: usize) -> Option<Self> {
    method array_unchecked (line 356) | pub fn array_unchecked<T>(n: usize) -> Self {
  type AllocErr (line 367) | pub enum AllocErr {
    method invalid_input (line 386) | pub fn invalid_input(details: &'static str) -> Self {
    method is_memory_exhausted (line 389) | pub fn is_memory_exhausted(&self) -> bool {
    method is_request_unsupported (line 392) | pub fn is_request_unsupported(&self) -> bool {
  type CannotReallocInPlace (line 400) | pub struct CannotReallocInPlace;
  type Allocator (line 427) | pub unsafe trait Allocator {
    method alloc (line 443) | unsafe fn alloc(&mut self, layout: Layout) -> Result<Address, AllocErr>;
    method dealloc (line 450) | unsafe fn dealloc(&mut self, ptr: Address, layout: Layout);
    method oom (line 465) | fn oom(&mut self, _: AllocErr) -> ! {
    method usable_size (line 496) | unsafe fn usable_size(&self, layout: &Layout) -> (Capacity, Capacity) {
    method realloc (line 540) | unsafe fn realloc(&mut self,
    method alloc_excess (line 565) | unsafe fn alloc_excess(&mut self, layout: Layout) -> Result<Excess, Al...
    method realloc_excess (line 573) | unsafe fn realloc_excess(&mut self,
    method realloc_in_place (line 604) | unsafe fn realloc_in_place(&mut self,
    method alloc_one (line 623) | unsafe fn alloc_one<T>(&mut self) -> Result<Unique<T>, AllocErr>
    method dealloc_one (line 641) | unsafe fn dealloc_one<T>(&mut self, mut ptr: Unique<T>)
    method alloc_array (line 657) | unsafe fn alloc_array<T>(&mut self, n: usize) -> Result<Unique<T>, All...
    method realloc_array (line 683) | unsafe fn realloc_array<T>(&mut self,
    method dealloc_array (line 704) | unsafe fn dealloc_array<T>(&mut self, ptr: Unique<T>, n: usize) -> Res...
    method alloc_unchecked (line 730) | unsafe fn alloc_unchecked(&mut self, layout: Layout) -> Option<Address> {
    method realloc_unchecked (line 762) | unsafe fn realloc_unchecked(&mut self,
    method alloc_excess_unchecked (line 772) | unsafe fn alloc_excess_unchecked(&mut self, layout: Layout) -> Option<...
    method realloc_excess_unchecked (line 778) | unsafe fn realloc_excess_unchecked(&mut self,
    method alloc_array_unchecked (line 793) | unsafe fn alloc_array_unchecked<T>(&mut self, n: usize) -> Option<Uniq...
    method realloc_array_unchecked (line 807) | unsafe fn realloc_array_unchecked<T>(&mut self,
    method dealloc_array_unchecked (line 826) | unsafe fn dealloc_array_unchecked<T>(&mut self, ptr: Unique<T>, n: usize)

FILE: sos_alloc/src/place.rs
  type IntermediateAlloc (line 25) | pub struct IntermediateAlloc<'alloc, A, T>
  type Place (line 37) | type Place = IntermediateAlloc<'alloc, A, Data>;
  function make_place (line 40) | fn make_place(self) -> Self::Place {
  function pointer (line 53) | fn pointer(&mut self) -> *mut Data {
  type Owner (line 69) | type Owner = Data;
  function finalize (line 74) | unsafe fn finalize(self) -> Self::Owner {

FILE: sos_alloc/src/system.rs
  type Tier (line 14) | pub enum Tier<'a> {
  type Target (line 23) | type Target = Allocator + 'static ;
  method deref (line 24) | fn deref(&self) -> &Self::Target{
  method alloc (line 36) | unsafe fn alloc(&mut self, layout: Layout) -> AllocResult<Address> {
  method dealloc (line 47) | unsafe fn dealloc(&mut self, ptr: Address, layout: Layout) {
  type SystemAllocator (line 59) | pub struct SystemAllocator(Mutex<Tier<'static>>);
    method borrow_ptr (line 68) | pub fn borrow_ptr<'alloc>(&'alloc self, layout: Layout)
    method borrow (line 78) | pub fn borrow<'alloc, T>(&'alloc self)

FILE: sos_intrusive/src/list/mod.rs
  type OwnedRef (line 25) | pub unsafe trait OwnedRef<T> {
    method from_raw (line 26) | unsafe fn from_raw(ptr: *mut T) -> Self;
    method take (line 27) | unsafe fn take(self);
    method get (line 28) | fn get(&self) -> &T;
    method get_mut (line 29) | fn get_mut(&mut self) -> &mut T;
  type Node (line 36) | pub trait Node: Sized {
    method next (line 37) | fn next(&self) -> &RawLink<Self>;
    method prev (line 38) | fn prev(&self) -> &RawLink<Self>;
    method next_mut (line 40) | fn next_mut(&mut self) -> &mut RawLink<Self>;
    method prev_mut (line 41) | fn prev_mut(&mut self) -> &mut RawLink<Self>;
  type List (line 49) | pub struct List<T, N>
  function new (line 73) | pub const fn new() -> Self {
  function len (line 81) | pub fn len(&self) -> usize {
  function front (line 90) | pub fn front(&self) -> Option<&N> {
  function back (line 100) | pub fn back(&self) -> Option<&N> {
  function front_mut (line 109) | pub fn front_mut(&mut self) -> Option<&mut N> {
  function back_mut (line 118) | pub fn back_mut(&mut self) -> Option<&mut N> {
  function is_empty (line 123) | pub fn is_empty(&self) -> bool {
  function push_front (line 129) | pub fn push_front(&mut self, mut item: T) {
  function push_back (line 161) | pub fn push_back(&mut self, mut item: T) {
  function pop_front (line 194) | pub fn pop_front(&mut self) -> Option<T> {
  function pop_back (line 221) | pub fn pop_back(&mut self) -> Option<T> {
  function peek_front (line 244) | pub fn peek_front(&self) -> Option<&N> {
  function cursor_mut (line 249) | pub fn cursor_mut<'a>(&'a mut self) -> ListCursorMut<'a, T, N> {
  function from_iter (line 259) | fn from_iter<I: IntoIterator<Item=T>>(iterator: I) -> Self {
  type Cursor (line 266) | pub trait Cursor {
    method next (line 269) | fn next(&mut self) -> Option<Self::Item>;
    method prev (line 270) | fn prev(&mut self) -> Option<Self::Item>;
    method get (line 271) | fn get(&self) -> Option<Self::Item>;
    method seek_forward (line 272) | fn seek_forward(&mut self, n: usize) -> Option<Self::Item>;
    method seek_backward (line 273) | fn seek_backward(&mut self, n: usize) -> Option<Self::Item>;
  type ListCursorMut (line 287) | pub struct ListCursorMut<'a, T, N>
  function next (line 310) | pub fn next(&mut self) -> Option<&mut N> {
  function prev (line 345) | pub fn prev(&mut self) -> Option<&mut N> {
  function peek_next (line 357) | pub fn peek_next(&self) -> Option<&N> {
  function peek_prev (line 373) | pub fn peek_prev(&self) -> Option<&N> {
  function remove (line 386) | pub fn remove(&mut self) -> Option<T> {
  function find_and_remove (line 416) | pub fn find_and_remove<P>(&mut self, predicate: P) -> Option<T>
  function seek_forward (line 432) | pub fn seek_forward(&mut self, n: usize) -> Option<&mut N> {
  function seek_backward (line 441) | pub fn seek_backward(&mut self, n: usize) -> Option<&mut N> {
  function get (line 485) | fn get(&self) -> &T {
  function get_mut (line 489) | fn get_mut(&mut self) -> &mut T {
  function take (line 494) | unsafe fn take(self) {}
  function from_raw (line 496) | unsafe fn from_raw(ptr: *mut T) -> Self {
  function get (line 506) | fn get(&self) -> &T { &**self }
  function get_mut (line 507) | fn get_mut(&mut self) -> &mut T { &mut **self }
  function take (line 509) | unsafe fn take(self) {
  function from_raw (line 513) | unsafe fn from_raw(ptr: *mut T) -> Self {

FILE: sos_intrusive/src/list/test.rs
  type NumberedNode (line 14) | pub struct NumberedNode {
    method new (line 21) | pub fn new(number: usize) -> Self {
  method prev (line 31) | fn prev(&self) -> &RawLink<Self> {
  method next (line 35) | fn next(&self) -> &RawLink<Self> {
  method prev_mut (line 39) | fn prev_mut(&mut self) -> &mut RawLink<Self> {
  method next_mut (line 43) | fn next_mut(&mut self) -> &mut RawLink<Self> {
  method eq (line 49) | fn eq(&self, rhs: &Self) -> bool { self.number == rhs.number }
  type TestList (line 58) | type TestList = List<Box<NumberedNode>, NumberedNode>;
  function not_empty_after_push (line 61) | fn not_empty_after_push() {
  function contents_after_first_push (line 75) | fn contents_after_first_push() {
  function head_tail_same_first_push (line 85) | fn head_tail_same_first_push() {
  function head_tail_not_same_second_push (line 96) | fn head_tail_not_same_second_push() {
  function contents_after_pushes (line 107) | fn contents_after_pushes() {
  function test_pop_front (line 128) | fn test_pop_front() {
  function test_pop_back (line 165) | fn test_pop_back() {

FILE: sos_intrusive/src/rawlink.rs
  type RawLink (line 23) | pub struct RawLink<T>(*mut T);
  method default (line 34) | fn default() -> Self { Self::none() }
  function fmt (line 39) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  function none (line 56) | pub const fn none() -> RawLink<T> { RawLink(ptr::null_mut()) }
  function some (line 63) | pub fn some(thing: &mut T) -> RawLink<T> { RawLink(thing) }
  function from_raw (line 65) | pub const fn from_raw(ptr: *mut T) -> RawLink<T> { RawLink(ptr) }
  function resolve (line 77) | pub unsafe fn resolve<'a>(&self) -> Option<&'a T> {
  function resolve_mut (line 91) | pub unsafe fn resolve_mut<'a>(&self) -> Option<&'a mut T> {
  function as_raw (line 105) | pub unsafe fn as_raw(&self) -> *mut T { self.0 }
  function is_some (line 108) | pub fn is_some(&self) -> bool { !self.is_none() }
  function is_none (line 111) | pub fn is_none(&self) -> bool { self.0.is_null() }
  function take (line 115) | pub fn take(&mut self) -> Self { mem::replace(self, Self::none()) }
  function map (line 117) | pub unsafe fn map<U, F: FnOnce(T) -> U>(self, _f: F) -> RawLink<U> {

FILE: sos_intrusive/src/stack/mod.rs
  type Node (line 29) | pub trait Node: Sized {
    method next (line 30) | fn next(&self) -> &RawLink<Self>;
    method next_mut (line 31) | fn next_mut(&mut self) -> &mut RawLink<Self>;
  type Stack (line 39) | pub struct Stack<T, N>
  function new (line 52) | pub const fn new() -> Self {
  function len (line 59) | pub fn len(&self) -> usize {
  function peek (line 68) | pub fn peek(&self) -> Option<&N> {
  function peek_mut (line 78) | pub fn peek_mut(&mut self) -> Option<&mut N> {
  function is_empty (line 83) | pub fn is_empty(&self) -> bool {
  function push (line 88) | pub fn push(&mut self, mut item: T) {
  function pop (line 103) | pub fn pop(&mut self) -> Option<T> {
  function from_iter (line 121) | fn from_iter<I: IntoIterator<Item=T>>(iterator: I) -> Self {

FILE: sos_intrusive/src/stack/test.rs
  type NumberedNode (line 14) | pub struct NumberedNode {
    method new (line 20) | pub fn new(number: usize) -> Self {
  method next (line 30) | fn next(&self) -> &RawLink<Self> {
  method next_mut (line 34) | fn next_mut(&mut self) -> &mut RawLink<Self> {
  method eq (line 40) | fn eq(&self, rhs: &Self) -> bool { self.number == rhs.number }
  type TestStack (line 49) | type TestStack = Stack<Box<NumberedNode>, NumberedNode>;
  function not_empty_after_push (line 52) | fn not_empty_after_push() {
  function contents_after_first_push (line 65) | fn contents_after_first_push() {
  function contents_after_pushes (line 75) | fn contents_after_pushes() {
  function test_pop_front (line 88) | fn test_pop_front() {

FILE: src/arch/x86_64/drivers/serial.rs
  type Serial (line 33) | pub struct Serial(Option<SerialPort>);
    method write_str (line 37) | fn write_str(&mut self, s: &str) -> fmt::Result {
  type SerialPort (line 69) | pub struct SerialPort { data_port: Port<u8>
    method new (line 75) | fn new(port: u16) -> SerialPort {
    method has_byte (line 98) | pub fn has_byte(&self) -> bool {
    method is_empty (line 103) | pub fn is_empty(&self) -> bool {
    method read_byte (line 108) | pub fn read_byte(&self) -> u8 {
    method write_byte (line 114) | pub fn write_byte(&self, byte: u8) {
    type Error (line 121) | type Error = Void;
    method read (line 124) | fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
    method read_all (line 135) | fn read_all(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
    type Error (line 149) | type Error = Void;
    method write (line 151) | fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
    method write_str (line 165) | fn write_str(&mut self, s: &str) -> fmt::Result {

FILE: src/arch/x86_64/drivers/vga.rs
  function clear (line 26) | pub fn clear() {

FILE: src/arch/x86_64/interrupts.rs
  function initialize (line 28) | pub unsafe fn initialize() -> Result<(), ()>{
  function keyboard (line 182) | pub extern "x86-interrupt" fn keyboard(_frame: &InterruptFrame) {
  function breakpoint (line 200) | pub extern "x86-interrupt" fn breakpoint(frame: &InterruptFrame) {
  function empty_handler (line 210) | pub extern "x86-interrupt" fn empty_handler(_frame: &InterruptFrame) {

FILE: src/arch/x86_64/mod.rs
  constant ARCH_BITS (line 17) | pub const ARCH_BITS: u8 = 64;
  function long_mode_init (line 47) | pub unsafe extern "C" fn long_mode_init() {
  function arch_init (line 68) | pub extern "C" fn arch_init(multiboot_addr: PAddr) {

FILE: src/arch/x86_all/bda.rs
  type Word (line 15) | type Word = u16;
  constant PORTS_ADDR (line 19) | const PORTS_ADDR: usize = 0x0400;
  type Ports (line 33) | struct Ports {

FILE: src/arch/x86_all/multiboot2.rs
  constant END_TAG_LEN (line 21) | const END_TAG_LEN: u32 = 8;
  constant HEADER_LEN (line 23) | const HEADER_LEN: u32 = 24;
  constant MAGIC (line 25) | pub const MAGIC: u32 = 0xe85250d6;
  type HeaderArch (line 28) | pub enum HeaderArch {
  type Header (line 34) | pub struct Header {
  type Info (line 55) | pub struct Info { pub length: u32
    method start_addr (line 63) | pub fn start_addr(&self) -> PAddr {
    method end_addr (line 67) | pub fn end_addr(&self) -> PAddr {
    method from (line 73) | pub unsafe fn from(addr: PAddr) -> Result<&'static Self, &'static str> {
    method get_tag (line 97) | pub fn get_tag(&'static self, tag_type: TagType) -> Option<&'static Ta...
    method mem_map (line 108) | pub fn mem_map(&'static self) -> Option<&'static MemMapTag> {
    method elf_sections (line 119) | pub fn elf_sections(&'static self) -> Option<&'static ElfSectionsTag> {
    method tags (line 128) | fn tags(&'static self) -> Tags { Tags(&self.tag_start as *const Tag) }
    method has_end (line 131) | fn has_end(&self) -> bool {
    method kernel_frames (line 142) | pub fn kernel_frames(&'static self) -> Result<FrameRange, &'static str> {
  type IntoIter (line 160) | type IntoIter = Tags;
  type Item (line 161) | type Item = &'static Tag;
  method into_iter (line 162) | fn into_iter(self) -> Self::IntoIter { self.tags() }
  type Tag (line 201) | pub struct Tag { /// the type of this tag.
  type TagType (line 211) | pub enum TagType { /// Tag that indicates the end of multiboot tags
  type Tags (line 227) | pub struct Tags(*const Tag);
    method advance (line 230) | fn advance(&mut self, size: u32) {
  type Item (line 237) | type Item = &'static Tag;
  method next (line 240) | fn next(&mut self) -> Option<Self::Item> {
  type MemMapTag (line 253) | pub struct MemMapTag { tag: Tag
    method areas (line 262) | pub fn areas(&'static self) -> MemAreas {
  type Item (line 275) | type Item = &'static MemArea;
  type IntoIter (line 276) | type IntoIter = MemAreas;
  method into_iter (line 278) | fn into_iter(self) -> Self::IntoIter { self.areas() }
  type CommandLineTag (line 285) | pub struct CommandLineTag { tag: Tag
  type ModulesTag (line 295) | pub struct ModulesTag { tag: Tag
  type MemAreaType (line 306) | pub enum MemAreaType { Available = 1
  type MemArea (line 314) | pub struct MemArea { /// the starting address of the memory area
    method address (line 324) | pub fn address(&self) -> PAddr {
    method fmt (line 343) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  function into (line 331) | fn into(self) -> mem::Area {
  type MemAreas (line 351) | pub struct MemAreas { curr: *const MemArea
  type Item (line 357) | type Item = &'static MemArea;
  method next (line 359) | fn next(&mut self) -> Option<&'static MemArea> {
  type Word (line 382) | pub type Word = u32;
  type Word (line 384) | pub type Word = u64;
  type ElfSectionsTag (line 389) | pub struct ElfSectionsTag { tag: Tag
    method sections (line 402) | pub fn sections(&'static self) -> Sections<'static, Word> {
  type Item (line 413) | type Item = <Self::IntoIter as Iterator>::Item;
  type IntoIter (line 414) | type IntoIter = Sections<'static, Word>;
  method into_iter (line 416) | fn into_iter(self) -> Self::IntoIter { self.sections() }

FILE: src/heap.rs
  function initialize (line 13) | pub unsafe fn initialize<'a>(params: &InitParams) -> Result<&'a str, &'a...

FILE: src/io/keyboard.rs
  type Scancode (line 17) | pub struct Scancode(u8);
    method to_ascii (line 20) | fn to_ascii(&self) -> Option<u8> {
  type Keyboard (line 33) | pub struct Keyboard { /// Port for reading data from the keyboard
    method read_scancode (line 42) | pub fn read_scancode(&self) -> Scancode {
  constant TO_ASCII_LOW (line 48) | const TO_ASCII_LOW: &'static [u8; 17]
  constant TO_ASCII_MID1 (line 51) | const TO_ASCII_MID1: &'static [u8; 14] = b"\tqwertyuiop[]\r";
  constant TO_ASCII_MID2 (line 54) | const TO_ASCII_MID2: &'static [u8; 11] = b"asdfghjkl;'";
  constant TO_ASCII_HIGH (line 57) | const TO_ASCII_HIGH: &'static [u8; 10] = b"zxcvbnm,./";
  method default (line 76) | fn default() -> Self { Modifiers::new() }
  method new (line 81) | pub const fn new() -> Self {
  method is_shifted (line 86) | pub fn is_shifted(&self) -> bool {
  method is_uppercase (line 91) | pub fn is_uppercase(&self) -> bool {
  method update (line 96) | fn update(&mut self, scancode: Scancode) {
  method modify (line 112) | fn modify(&self, ascii: u8) -> u8 {
  function read_char (line 129) | pub fn read_char() -> Option<char> {

FILE: src/logger.rs
  type SerialLogger (line 15) | struct SerialLogger;
    method enabled (line 34) | fn enabled(&self, _metadata: &LogMetadata) -> bool {
    method log (line 39) | fn log(&self, record: &LogRecord) {
    method enabled (line 72) | fn enabled(&self, metadata: &LogMetadata) -> bool {
    method log (line 77) | fn log(&self, record: &LogRecord) {
  function initialize (line 17) | pub fn initialize() -> Result<(), log::SetLoggerError> {
  function shutdown (line 25) | pub fn shutdown() -> Result<(), log::ShutdownLoggerError> {

FILE: src/main.rs
  constant VERSION_STRING (line 72) | pub const VERSION_STRING: &'static str
  function kernel_main (line 77) | pub fn kernel_main() -> ! {
  function kernel_init (line 114) | pub fn kernel_init(params: &InitParams) {
  function main (line 160) | fn main() {

FILE: util/src/io.rs
  type Read (line 24) | pub trait Read {
    method read (line 53) | fn read(&mut self, buf: &mut [u8])     -> Result<usize, Self::Error>;
    method read_all (line 62) | fn read_all(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error>;
  type Write (line 81) | pub trait Write {
    method write (line 108) | fn write(&mut self, buf: &[u8])       -> Result<usize, Self::Error>;

FILE: util/src/lib.rs
  type Void (line 26) | pub enum Void {}
    method fmt (line 28) | fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result {
  type Align (line 33) | pub trait Align: Sized + Copy //+ One
    method align_up (line 38) | fn align_up(&self, to: Self) -> Self {
    method align_down (line 42) | fn align_down(&self, to: Self) -> Self {

FILE: vga/src/lib.rs
  constant X_MAX (line 100) | pub const X_MAX: usize = 80;
  constant Y_MAX (line 101) | pub const Y_MAX: usize = 25;
  type Buffer (line 104) | pub type Buffer = [[Char; X_MAX]; Y_MAX];
  constant ANSI_ESCAPE (line 106) | const ANSI_ESCAPE: &'static str = "\x1b";
  constant FG_MASK (line 107) | const FG_MASK: u8 = 0b0000_1111;
  constant BG_MASK (line 108) | const BG_MASK: u8 = 0b1111_0000;
  type Color (line 113) | pub enum Color { Black = 0
  type Palette (line 132) | pub struct Palette(u8);
    method new (line 136) | pub const fn new(fg: Color, bg: Color) -> Self {
    method set_foreground (line 142) | pub fn set_foreground(&self, fg: Color) -> Self {
    method set_background (line 148) | pub fn set_background(&self, bg: Color) -> Self {
    method foreground (line 153) | pub fn foreground(&self) -> Color {
    method background (line 158) | pub fn background(&self) -> Color {
  type Char (line 166) | pub struct Char { pub ascii: u8
    method empty (line 172) | pub const fn empty() -> Self {
  type Terminal (line 177) | pub struct Terminal { buffer: ptr::Unique<Buffer>
    method x_position (line 185) | pub fn x_position(&self) -> usize {
    method new (line 199) | pub const unsafe fn new( colors: Palette
    method buffer (line 211) | fn buffer(&mut self) -> &mut  Buffer {
    method set_colors (line 216) | pub fn set_colors(&mut self, bg: Color, fg: Color) -> &mut Self {
    method scroll (line 222) | fn scroll(&mut self) {
    method clear (line 257) | pub fn clear(&mut self) -> &mut Self {
    method write_byte (line 278) | pub fn write_byte(&mut self, byte: u8) -> &mut Self {
    method handle_ansi_escape (line 313) | fn handle_ansi_escape(&self, escape_code: &str) -> Result {
  type AnsiEscapeIter (line 373) | struct AnsiEscapeIter<'a> { curr_slice: &'a str
  function new (line 379) | pub fn new(s: &'a str) -> Self {
  type Item (line 387) | type Item = &'a str;
  method next (line 389) | fn next(&mut self) -> Option<Self::Item> {
  method write_str (line 425) | fn write_str(&mut self, s: &str) -> Result {

FILE: vga/src/panic.rs
  function rust_begin_unwind (line 26) | pub extern "C" fn rust_begin_unwind( args: Arguments

FILE: vga/src/status.rs
  type Status (line 4) | pub trait Status {
    method okay (line 5) | fn okay(&mut self) -> Result ;
    method fail (line 6) | fn fail(&mut self) -> Result ;
    method okay (line 10) | fn okay(&mut self) -> Result {
    method fail (line 19) | fn fail(&mut self) -> Result {
Condensed preview — 125 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (523K chars).
[
  {
    "path": ".editorconfig",
    "chars": 849,
    "preview": "# EditorConfig helps developers define and maintain consistent\n# coding styles between different editors and IDEs\n# edit"
  },
  {
    "path": ".gitignore",
    "chars": 2466,
    "preview": "\n# Created by https://www.gitignore.io/api/assembler,rust,emacs,osx,sublimetext,tags,vagrant,vim,linux\n\n### Kernel binar"
  },
  {
    "path": ".gitmodules",
    "chars": 0,
    "preview": ""
  },
  {
    "path": ".travis.yml",
    "chars": 4105,
    "preview": "language: rust\nrust: nightly\n\n# matrix:\n#   allow_failures:\n#     - os: osx\n#   fast_finish: true\n\ncache:\n  cargo: true\n"
  },
  {
    "path": "BUILDING.md",
    "chars": 4037,
    "preview": "setting up a build environment\n============================\n\nUnfortunately, one of the unescapable truths of OS developm"
  },
  {
    "path": "Brewfile",
    "chars": 244,
    "preview": "# for making a bootable ISO\nbrew 'xorriso'\n\n# for running the OS\nbrew 'qemu'\n\n# x86_64-pc-elf cross-compile toolchain\nta"
  },
  {
    "path": "CHANGES.md",
    "chars": 2695,
    "preview": "<a name=\"elf-v0-0-2\"></a>\n## elf v0.0.2 (2017-03-15)\n\n\n#### Bug Fixes\n\n* **elf:**\n  *  add assertion that extract_from_s"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "chars": 3230,
    "preview": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, w"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 8930,
    "preview": "Contributing to SOS\n===================\n\n**Looking for a first issue?** You might want to start out by looking at [issue"
  },
  {
    "path": "Cargo.toml",
    "chars": 1231,
    "preview": "[package]\nname = \"sos_kernel\"\nversion = \"0.1.0\"\nauthors = [ # hacked around by\n            \"Eliza Weisman <eliza@elizas."
  },
  {
    "path": "LICENSE-APACHE",
    "chars": 10850,
    "preview": "                              Apache License\n                        Version 2.0, January 2004\n                     http"
  },
  {
    "path": "LICENSE-MIT",
    "chars": 1062,
    "preview": "Copyright (c) 2015 The SOS Developers\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
  },
  {
    "path": "Makefile",
    "chars": 5021,
    "preview": "arch ?= x86_64\ntarget ?= $(arch)-sos-kernel-gnu\n\nboot_target := x86_32-sos-bootstrap-gnu\nboot_outdir := boot/target/$(bo"
  },
  {
    "path": "Notes.md",
    "chars": 441,
    "preview": "Notes\n=====\n\nOn designing a userland\n-----------------------\n\n+ provide user code written in Rust with a fluent Rust API"
  },
  {
    "path": "README.md",
    "chars": 2421,
    "preview": "# Stupid Operating System \n[![Build Status](https://travis-ci.org/hawkw/sos-kernel.svg?branch=master)](https://travis-ci"
  },
  {
    "path": "Vagrantfile",
    "chars": 643,
    "preview": "# -*- mode: ruby -*-\n# vi: set ft=ruby :\n\nVagrant.configure(2) do |config|\n  config.vm.box = \"hashicorp/precise64\"\n\n  co"
  },
  {
    "path": "Xargo.toml",
    "chars": 66,
    "preview": "[target.x86_64-sos-kernel-gnu.dependencies]\nalloc = {}\n# std = {}\n"
  },
  {
    "path": "boot/Cargo.toml",
    "chars": 448,
    "preview": "[package]\nname = \"boot32\"\nversion = \"0.1.0\"\nauthors = [\"Eliza Weisman <eliza@elizas.website>\"]\n\n[lib]\ncrate-type = [\"sta"
  },
  {
    "path": "boot/README.md",
    "chars": 707,
    "preview": "# SOS x86_64 bootstrap\n\nthis crate contains code for the 32-bit protected mode boot routine for x86_64 CPUs. when we boo"
  },
  {
    "path": "boot/src/lib.rs",
    "chars": 7519,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2016-2017 Eliza"
  },
  {
    "path": "build.rs",
    "chars": 735,
    "preview": "use std::env;\n\nfn main() {\n    let profile = env::var(\"PROFILE\").unwrap();\n    if profile != \"test\" {\n        // target "
  },
  {
    "path": "cpu/Cargo.toml",
    "chars": 673,
    "preview": "[package]\nname = \"cpu\"\nversion = \"0.0.1\"\nauthors = [ \"Eliza Weisman <eliza@elizas.website>\" ]\n\n[profile.dev]\nopt-level ="
  },
  {
    "path": "cpu/src/armv7/mod.rs",
    "chars": 356,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza"
  },
  {
    "path": "cpu/src/lib.rs",
    "chars": 2543,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2016 Eliza eism"
  },
  {
    "path": "cpu/src/x86/cpu.rs",
    "chars": 556,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza"
  },
  {
    "path": "cpu/src/x86/mod.rs",
    "chars": 466,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza"
  },
  {
    "path": "cpu/src/x86_64/context.rs",
    "chars": 5649,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza"
  },
  {
    "path": "cpu/src/x86_64/mod.rs",
    "chars": 612,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2016 Eliza Weis"
  },
  {
    "path": "cpu/src/x86_64/msr.rs",
    "chars": 1307,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Hawk Weisman (hi@hawkweisman.me)\n//\n//  Copyright (c) 2015 Hawk Weisman\n/"
  },
  {
    "path": "cpu/src/x86_64/task.rs",
    "chars": 1400,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza"
  },
  {
    "path": "cpu/src/x86_all/control_regs/cr0.rs",
    "chars": 3825,
    "preview": "use core::fmt;\n\nbitflags! {\n    /// Flag present in `%cr0`.\n    ///\n    /// See [the OS Dev Wiki](http://wiki.osdev.org/"
  },
  {
    "path": "cpu/src/x86_all/control_regs/cr4.rs",
    "chars": 3989,
    "preview": "use core::fmt;\n\n/// Read the current value from `$cr4`.\n///\n/// # Safety\n/// + Reading from control registers while not "
  },
  {
    "path": "cpu/src/x86_all/control_regs/mod.rs",
    "chars": 5107,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza"
  },
  {
    "path": "cpu/src/x86_all/dtable.rs",
    "chars": 4009,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza"
  },
  {
    "path": "cpu/src/x86_all/flags.rs",
    "chars": 2875,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza"
  },
  {
    "path": "cpu/src/x86_all/interrupts/idt/gate32.rs",
    "chars": 3566,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza"
  },
  {
    "path": "cpu/src/x86_all/interrupts/idt/gate64.rs",
    "chars": 6140,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza"
  },
  {
    "path": "cpu/src/x86_all/interrupts/idt/mod.rs",
    "chars": 9210,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza"
  },
  {
    "path": "cpu/src/x86_all/interrupts/idt/tests.rs",
    "chars": 223,
    "preview": "#[test] fn test_task_gate_32() { assert_eq!(super::TASK_GATE_32.bits, 5)}\n#[test] fn test_int_gate_32() { assert_eq!(sup"
  },
  {
    "path": "cpu/src/x86_all/interrupts/mod.rs",
    "chars": 4606,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza"
  },
  {
    "path": "cpu/src/x86_all/interrupts/pics.rs",
    "chars": 8393,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza"
  },
  {
    "path": "cpu/src/x86_all/mod.rs",
    "chars": 4972,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza"
  },
  {
    "path": "cpu/src/x86_all/segment.rs",
    "chars": 17468,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2016 Eliza Weis"
  },
  {
    "path": "cpu/src/x86_all/timer.rs",
    "chars": 2279,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2016 Eliza eism"
  },
  {
    "path": "elf/Cargo.toml",
    "chars": 504,
    "preview": "[package]\nname = \"elf\"\nversion = \"0.0.2\"\nauthors = [ \"Eliza Weisman <eliza@elizas.website>\" ]\n\n[profile.dev]\nopt-level ="
  },
  {
    "path": "elf/README.md",
    "chars": 719,
    "preview": "elf: ELF parsing and loading\n============================\n\na library for parsing, navigating, and loading 32- and 64-bit"
  },
  {
    "path": "elf/src/file.rs",
    "chars": 13562,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza"
  },
  {
    "path": "elf/src/lib.rs",
    "chars": 10483,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza"
  },
  {
    "path": "elf/src/program.rs",
    "chars": 4343,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza"
  },
  {
    "path": "elf/src/section.rs",
    "chars": 18926,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza"
  },
  {
    "path": "memory/Cargo.toml",
    "chars": 832,
    "preview": "[package]\nname = \"memory\"\nversion = \"0.0.1\"\nauthors = [ \"Eliza Weisman <eliza@elizas.website>\" ]\n\n[profile.dev]\nopt-leve"
  },
  {
    "path": "memory/src/arch/mod.rs",
    "chars": 518,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza"
  },
  {
    "path": "memory/src/arch/x86/mod.rs",
    "chars": 1011,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza"
  },
  {
    "path": "memory/src/arch/x86_64/mod.rs",
    "chars": 2726,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza"
  },
  {
    "path": "memory/src/lib.rs",
    "chars": 7941,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2016 Eliza Weis"
  },
  {
    "path": "memory/src/macros.rs",
    "chars": 9800,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza"
  },
  {
    "path": "paging/Cargo.toml",
    "chars": 981,
    "preview": "[package]\nname = \"paging\"\nversion = \"0.0.1\"\nauthors = [ \"Eliza Weisman <hi@hawkweisman.me>\" ]\n\n[profile.dev]\nopt-level ="
  },
  {
    "path": "paging/src/arch/mod.rs",
    "chars": 515,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (hi@hawkweisman.me)\n//\n//  Copyright (c) 2015-2016 Eliza We"
  },
  {
    "path": "paging/src/arch/x86_64/cr3.rs",
    "chars": 760,
    "preview": "use super::table::{Table, PML4Level};\nuse cpu::control_regs::cr3::{read, write};\npub use cpu::control_regs::cr3::*;\n\n///"
  },
  {
    "path": "paging/src/arch/x86_64/mod.rs",
    "chars": 16227,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (hi@hawkweisman.me)\n//\n//  Copyright (c) 2015-2016 Eliza We"
  },
  {
    "path": "paging/src/arch/x86_64/table.rs",
    "chars": 11251,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (hi@hawkweisman.me)\n//\n//  Copyright (c) 2015-2017 Eliza We"
  },
  {
    "path": "paging/src/arch/x86_64/temp.rs",
    "chars": 3999,
    "preview": "use memory::{PAGE_SIZE, Page, PhysicalPage, VAddr, VirtualPage, FrameRange};\nuse alloc::{AllocResult, AllocErr, Layout, "
  },
  {
    "path": "paging/src/arch/x86_64/tlb.rs",
    "chars": 1498,
    "preview": "use memory::VAddr;\nuse super::{Page, VirtualPage};\n\n/// Invalidate the TLB completely by reloading the CR3 register.\n///"
  },
  {
    "path": "paging/src/lib.rs",
    "chars": 3708,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (hi@hawkweisman.me)\n//\n//  Copyright (c) 2015-2016 Eliza We"
  },
  {
    "path": "paging/src/stack.rs",
    "chars": 2451,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza"
  },
  {
    "path": "params/Cargo.toml",
    "chars": 479,
    "preview": "[package]\nname = \"params\"\nversion = \"0.0.1\"\nauthors = [ \"Eliza Weisman <hi@hawkweisman.me>\" ]\n\n[profile.dev]\nopt-level ="
  },
  {
    "path": "params/src/lib.rs",
    "chars": 6287,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (hi@hawkweisman.me)\n//\n//  Copyright (c) 2015-2017 Eliza We"
  },
  {
    "path": "params/src/mem.rs",
    "chars": 454,
    "preview": "//! Memory parameters\n\nuse memory::PAddr;\nuse core::ops::Range;\nuse core::slice::Iter;\n/// A memory map is an iterator o"
  },
  {
    "path": "rustfmt.toml",
    "chars": 245,
    "preview": "where_indent = \"Inherit\"\nstruct_lit_style = \"Visual\"\nchain_base_indent = \"Tabbed\"\nchain_indent = \"Visual\"\nreorder_import"
  },
  {
    "path": "scripts/README.md",
    "chars": 706,
    "preview": "this directory contains a handful of scripts to help install the needed tools to build SOS. these scripts are run by the"
  },
  {
    "path": "scripts/install-env-linux.sh",
    "chars": 2541,
    "preview": "#!/bin/bash\n#\n#  SOS: the Stupid Operating System\n#  by Eliza Weisman (eliza@elizas.website)\n#\n#  Copyright (c) 2015-201"
  },
  {
    "path": "scripts/install-env-mac.sh",
    "chars": 1645,
    "preview": "#!/bin/bash\n#\n#  SOS: the Stupid Operating System\n#  by Eliza Weisman (eliza@elizas.website)\n#\n#  Copyright (c) 2015-201"
  },
  {
    "path": "scripts/install-env.sh",
    "chars": 3366,
    "preview": "#!/bin/bash\n#\n#  SOS: the Stupid Operating System\n#  by Eliza Weisman (eliza@elizas.website)\n#\n#  Copyright (c) 2015-201"
  },
  {
    "path": "sos_alloc/Cargo.toml",
    "chars": 752,
    "preview": "[package]\nname = \"sos_alloc\"\nversion = \"0.1.0\"\nauthors = [\"Eliza Weisman <eliza@elizas.website>\"]\n\n[features]\ndefault = "
  },
  {
    "path": "sos_alloc/src/borrow.rs",
    "chars": 3357,
    "preview": "use super::{Address, Allocator, Layout};\nuse ptr::Unique;\nuse ops::{Deref, DerefMut};\nuse spin::Mutex;\n\npub trait Lender"
  },
  {
    "path": "sos_alloc/src/buddy/math.rs",
    "chars": 4580,
    "preview": "#[cfg(target_arch=\"x86\")]\nconst B: [usize; 5]\n    = [ 0x2, 0xC, 0xF0\n      , 0xFF00\n      , 0xFFFF0000];\n#[cfg(target_ar"
  },
  {
    "path": "sos_alloc/src/buddy/mod.rs",
    "chars": 16672,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza"
  },
  {
    "path": "sos_alloc/src/buddy/system.rs",
    "chars": 5768,
    "preview": "//! This module integrates the buddy heap allocator into the Rust runtime.\nuse spin::Mutex;\nuse core::ptr;\n\nuse ::{Alloc"
  },
  {
    "path": "sos_alloc/src/buddy/test.rs",
    "chars": 6610,
    "preview": "use super::*;\n\nuse ::{Allocator, Layout};\n\nuse core::ptr;\n\nextern \"C\" {\n    /// We need this to allocate aligned memory "
  },
  {
    "path": "sos_alloc/src/bump_ptr.rs",
    "chars": 1543,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (hi@hawkweisman.me)\n//\n//  Copyright (c) 2015-2017 Eliza We"
  },
  {
    "path": "sos_alloc/src/first_fit.rs",
    "chars": 1064,
    "preview": "use arrayvec::ArrayVec;\nuse memory::{Page, MemRange, PhysicalPage, FrameRange};\nuse super::FrameAllocator;\nuse spin::Mut"
  },
  {
    "path": "sos_alloc/src/frame/mem_map.rs",
    "chars": 5347,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza"
  },
  {
    "path": "sos_alloc/src/frame/mod.rs",
    "chars": 4843,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza"
  },
  {
    "path": "sos_alloc/src/free.rs",
    "chars": 886,
    "preview": "use core::ptr::Unique;\nuse core::mem;\n\nuse intrusive::list::{List as IList, Node};\nuse intrusive::rawlink::RawLink;\n\n///"
  },
  {
    "path": "sos_alloc/src/lib.rs",
    "chars": 34703,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza"
  },
  {
    "path": "sos_alloc/src/place.rs",
    "chars": 2400,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (hi@hawkweisman.me)\n//\n//  Copyright (c) 2015-2017 Eliza We"
  },
  {
    "path": "sos_alloc/src/system.rs",
    "chars": 2584,
    "preview": "use spin::Mutex;\nuse super::{Address, Allocator, AllocErr, Layout, AllocResult};\nuse core::ops::Deref;\n\n#[cfg(feature = "
  },
  {
    "path": "sos_intrusive/Cargo.toml",
    "chars": 139,
    "preview": "[package]\nname = \"sos_intrusive\"\nversion = \"0.1.0\"\nauthors = [\"Eliza Weisman <eliza@elizas.website>\"]\n\n[features]\ndefaul"
  },
  {
    "path": "sos_intrusive/src/lib.rs",
    "chars": 1578,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza"
  },
  {
    "path": "sos_intrusive/src/list/mod.rs",
    "chars": 17452,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza"
  },
  {
    "path": "sos_intrusive/src/list/test.rs",
    "chars": 7357,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza"
  },
  {
    "path": "sos_intrusive/src/rawlink.rs",
    "chars": 3568,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza"
  },
  {
    "path": "sos_intrusive/src/stack/mod.rs",
    "chars": 3993,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2017 Eliza Weis"
  },
  {
    "path": "sos_intrusive/src/stack/test.rs",
    "chars": 2953,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2017 Eliza Weis"
  },
  {
    "path": "src/arch/README.md",
    "chars": 264,
    "preview": "Architecture-specific implementation:\n + `arch/x86` contains implementation for x86 32-bit protected mode (not yet imple"
  },
  {
    "path": "src/arch/mod.rs",
    "chars": 1414,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza"
  },
  {
    "path": "src/arch/x86_64/boot.asm",
    "chars": 7203,
    "preview": "%define PAGE_TABLE_SIZE 512 * 8\n%define PAGE_SIZE 4096\n\n; page_map: macro to map the first entry in the first argument t"
  },
  {
    "path": "src/arch/x86_64/drivers/mod.rs",
    "chars": 285,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2016 Eliza eism"
  },
  {
    "path": "src/arch/x86_64/drivers/serial.rs",
    "chars": 5292,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza"
  },
  {
    "path": "src/arch/x86_64/drivers/vga.rs",
    "chars": 697,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza"
  },
  {
    "path": "src/arch/x86_64/grub.cfg",
    "chars": 94,
    "preview": "set timeout=0\nset default=0\n\nmenuentry \"sos\" {\n    multiboot2 /boot/sos_kernel.bin\n    boot\n}\n"
  },
  {
    "path": "src/arch/x86_64/interrupts.rs",
    "chars": 8144,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza"
  },
  {
    "path": "src/arch/x86_64/linker.ld",
    "chars": 1732,
    "preview": "/* Based on http://blog.phil-opp.com/rust-os/multiboot-kernel.html\n *\n * Used to specify a custom linking layout that pu"
  },
  {
    "path": "src/arch/x86_64/mod.rs",
    "chars": 5983,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza"
  },
  {
    "path": "src/arch/x86_all/bda.rs",
    "chars": 1741,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2016 Eliza Weis"
  },
  {
    "path": "src/arch/x86_all/multiboot2.rs",
    "chars": 13320,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza"
  },
  {
    "path": "src/heap.rs",
    "chars": 685,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza"
  },
  {
    "path": "src/io/keyboard.rs",
    "chars": 4552,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza"
  },
  {
    "path": "src/io/mod.rs",
    "chars": 403,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza"
  },
  {
    "path": "src/io/term.rs",
    "chars": 365,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza"
  },
  {
    "path": "src/logger.rs",
    "chars": 2459,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza"
  },
  {
    "path": "src/main.rs",
    "chars": 5284,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza"
  },
  {
    "path": "targets/x86_32-sos-bootstrap-gnu.json",
    "chars": 643,
    "preview": "{\n    \"llvm-target\": \"i386-unknown-unknown-elf\",\n    \"executables\": true,\n    \"linker-flavor\": \"gcc\",\n    \"target-endian"
  },
  {
    "path": "targets/x86_64-sos-kernel-gnu.json",
    "chars": 822,
    "preview": "{\n    \"llvm-target\": \"x86_64-unknown-none-gnu\",\n    \"executables\": true,\n    \"target-endian\": \"little\",\n    \"target-poin"
  },
  {
    "path": "tokamak.toml",
    "chars": 393,
    "preview": "[helper]\npath = \"\"                                  # Reserved for future helper path and configurations\n[options]\nsave_"
  },
  {
    "path": "util/Cargo.toml",
    "chars": 396,
    "preview": "[package]\nname = \"util\"\nversion = \"0.0.1\"\nauthors = [ \"Eliza Weisman <eliza@elizas.website>\" ]\n\n[profile.dev]\nopt-level "
  },
  {
    "path": "util/src/io.rs",
    "chars": 4995,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2016 Eliza Weis"
  },
  {
    "path": "util/src/lib.rs",
    "chars": 1169,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2016 Eliza Weis"
  },
  {
    "path": "util/src/macros/mod.rs",
    "chars": 410,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza"
  },
  {
    "path": "util/src/macros/newtype_impl.rs",
    "chars": 2859,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza"
  },
  {
    "path": "vga/Cargo.toml",
    "chars": 343,
    "preview": "[package]\nname = \"vga\"\nversion = \"0.1.0\"\nauthors = [\"Eliza Weisman <eliza@elizas.website>\"]\n\n[features]\ndefault = []\nsys"
  },
  {
    "path": "vga/src/kinfo.rs",
    "chars": 5488,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2016 Eliza Weis"
  },
  {
    "path": "vga/src/lib.rs",
    "chars": 14548,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza"
  },
  {
    "path": "vga/src/panic.rs",
    "chars": 1347,
    "preview": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza"
  },
  {
    "path": "vga/src/status.rs",
    "chars": 838,
    "preview": "use super::{Terminal, Color};\nuse core::fmt::{Result, Write};\n\npub trait Status {\n    fn okay(&mut self) -> Result ;\n   "
  }
]

About this extraction

This page contains the full source code of the sos-os/kernel GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 125 files (487.0 KB), approximately 131.1k tokens, and a symbol index with 942 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!