[
  {
    "path": ".editorconfig",
    "content": "# EditorConfig helps developers define and maintain consistent\n# coding styles between different editors and IDEs\n# editorconfig.org\nroot = true\n\n### Makefiles #######################################################\n[Makefile]\nindent_style = tab # Makefiles must be indented with tabs.\n\n### Rust source code files ##########################################\n# Based on @xtian's .editorconfig file at\n# https://gist.github.com/xtian/339112af8a11d0583d81\n# and on the Rust style guidelines at\n# https://github.com/rust-lang/rust/tree/master/src/doc/style/style/\n[*.rs]\nend_of_line = lf\ncharset = utf-8\ntrim_trailing_whitespace = true\nindent_style = space\nindent_size = 4\n\n### Assembly language files #########################################\n[*.asm]\nend_of_line = lf\ncharset = utf-8\ntrim_trailing_whitespace = true\nindent_style = space\nindent_size = 4\n"
  },
  {
    "path": ".gitignore",
    "content": "\n# Created by https://www.gitignore.io/api/assembler,rust,emacs,osx,sublimetext,tags,vagrant,vim,linux\n\n### Kernel binaries ###\n*.iso\n*.bin\n*.elf\n\n# serial output\nserial-*.log\n\n### Assembler ###\n*.[sS]\n*.bc\n\n\n### Rust ###\n# Compiled files\n*.o\n*.so\n*.rlib\n*.dll\n\n# Executables\n*.exe\n\n# Generated by Cargo\n/target/\n**/target/\n\n# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries\n# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock\nCargo.lock\n\n\n### Emacs ###\n# -*- mode: gitignore; -*-\n*~\n\\#*\\#\n/.emacs.desktop\n/.emacs.desktop.lock\n*.elc\nauto-save-list\ntramp\n.\\#*\n\n# Org-mode\n.org-id-locations\n*_archive\n\n# flymake-mode\n*_flymake.*\n\n# eshell files\n/eshell/history\n/eshell/lastdir\n\n# elpa packages\n/elpa/\n\n# reftex files\n*.rel\n\n# AUCTeX auto folder\n/auto/\n\n# cask packages\n.cask/\n\n# Flycheck\nflycheck_*.el\n\n# server auth directory\n/server/\n\n\n### OSX ###\n.DS_Store\n.AppleDouble\n.LSOverride\n\n# Icon must end with two \\r\nIcon\n\n\n# Thumbnails\n._*\n\n# Files that might appear in the root of a volume\n.DocumentRevisions-V100\n.fseventsd\n.Spotlight-V100\n.TemporaryItems\n.Trashes\n.VolumeIcon.icns\n\n# Directories potentially created on remote AFP share\n.AppleDB\n.AppleDesktop\nNetwork Trash Folder\nTemporary Items\n.apdisk\n\n\n### SublimeText ###\n# cache files for sublime text\n*.tmlanguage.cache\n*.tmPreferences.cache\n*.stTheme.cache\n\n# workspace files are user-specific\n*.sublime-workspace\n\n# project files should be checked into the repository, unless a significant\n# proportion of contributors will probably not be using SublimeText\n# *.sublime-project\n\n# sftp configuration file\nsftp-config.json\n\n\n### Tags ###\n# Ignore tags created by etags, ctags, gtags (GNU global) and cscope\nTAGS\n.TAGS\n!TAGS/\ntags\n.tags\n!tags/\ngtags.files\nGTAGS\nGRTAGS\nGPATH\ncscope.files\ncscope.out\ncscope.in.out\ncscope.po.out\n\n\n\n### Vagrant ###\n.vagrant/\n\n\n### Vim ###\n# swap\n[._]*.s[a-w][a-z]\n[._]s[a-w][a-z]\n# session\nSession.vim\n# temporary\n.netrwhist\n*~\n# auto-generated tag files\ntags\n.tags1\n\n### GDB ###\n.gdb_history\n\n### Linux ###\n*~\n\n# temporary files which can be created if a process still has a handle open of a deleted file\n.fuse_hidden*\n\n# KDE directory preferences\n.directory\n\n# Linux trash folder which might appear on any partition or disk\n.Trash-*\n.idea/markdown-navigator.xml\n.idea/markdown-navigator/profiles_settings.xml\n.idea/modules.xml\n.idea/misc.xml\n.idea/sos-kernel.iml\n.idea/vcs.xml\n.idea/workspace.xml\n.vscode/tasks.json\n"
  },
  {
    "path": ".gitmodules",
    "content": ""
  },
  {
    "path": ".travis.yml",
    "content": "language: rust\nrust: nightly\n\n# matrix:\n#   allow_failures:\n#     - os: osx\n#   fast_finish: true\n\ncache:\n  cargo: true\n  directories:\n    - /usr/local/bin/x86_64-pc-elf-*\n    - /usr/local/bin/grub*\n\nnotifications:\n  webhooks:\n    urls:\n    - https://webhooks.gitter.im/e/59a4cbad9f4177de9a91\n    on_success: change\n    on_failure: always\n    on_start: never\n  email:\n    on_success: never\n    on_failure: change\n  slack:\n    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=\n\naddons:\n  apt:\n    packages:\n    - nasm\n    - build-essential\n    - xorriso\n    # - libssh2-1\n\nbefore_install: |\n  objcopy=$(which objcopy) &&\n  strip=$(which strip) &&\n  mkdir -p $HOME/bin &&\n  ln -s $objcopy $HOME/bin/x86_64-elf-objcopy &&\n  ln -s $strip $HOME/bin/x86_64-elf-strip\n\ninstall:\n  ### install the \"rust-src\" rustup component ###############################\n  # xargo uses this for building sysroots\n  # before installing rust-src we need to get `rustup`\n  - curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain nightly\n  - source ~/.cargo/env\n  # add the rust-src component\n  - rustup component add rust-src\n  ### install `xargo` ######################################################\n  - cargo install xargo --force\n  - export PATH=\"$PATH:$(rustc --print sysroot)/cargo/bin:$HOME/.cargo/bin\"\n\nscript: make test\n\njobs:\n  include:\n    - stage: build\n      script: make kernel\n      deploy:\n        provider: releases\n        api_key:\n          secure: DQ6EChkuPdDbCkPQIOVmq7SBxTG04GeoUXeguCb3RcX+lT5FqTG/2bAnElAxE+KHkLpxBav+CIaHyPQzT93LN70PSV0Vny8Oo3OCOprSn3gph12ZXPeebFk+EFArju3N/Du/cxlNK6zQ71Sw1Jr+nmutjpCGkN2ki04A6iY5f0cLmgsUXZxVBzMY4mb2tihAvH+0HgR96mmQ6xEvWU3mXnHvgpJhSwSHJlZao7C51vq0sr5bKPNVVHfwN7OlqG3uJYWcnFIlrkGbZyVtNZ//CjtGPhKufn+l1JOdQo47/Lh+iHPUNrWGsvNiy7yXrBdsVKI0oJwfssHrMPrXyWphk9wrD8ID1wpKXPxDikVB3uSU1OfQbSSsH+aF7i3mNwJSG4ORTjZeuBQpC4F9ZUAr2uS6RR+bW9tnb6/ZRQA0vqQVS1oi5miIHLe9FbMccOZLWYyHM6Lts3cd4zEldZTvPUmO7M5oP4Woo0DPRWvq48f7QW9x0ewjVRjfUkPZ8+H5BfFfqXQXZYtDRfTruVaYtS/We3QggvLaNZJOmq+jJQqrSARK5tB/HD8YZvu9Z1XU8UTcm6ORvlEsAMIk7+orUU1L4ibO/Tr1wEU9fgS2k9rCDPhfMljgn2EqBRfULnwqbzSwPrZmKyJlVZ6GsJtCAC1XQQCbZIMVShVbvL6JEKU=\n        file: build/os-x86_64.iso\n        skip_cleanup: true\n        on:\n          tags: true\n          repo: hawkw/sos-kernel\n    - stage: docs\n      install: skip\n      script: cargo doc\n      deploy:\n        provider:  pages\n        skip_cleanup: true\n        github_token: $GH_TOKEN # Set in travis-ci.org dashboard\n        target_branch: gh-pages\n        local_dir: target/doc\n        on:\n          branch: master\n          repo: hawkw/sos-kernel\n\nenv:\n  global:\n    # override the default `--features unstable` used for the nightly branch (optional)\n    - TRAVIS_CARGO_NIGHTLY_FEATURE=\"\"\n    - PATH=\"$PATH:$HOME/bin\"\n    - secure: Vv4bFCkxM3o7FpKjcxTzQRWdkp5aSfrkmFcxSRLYFhm8tyeh+TRiC2+ucNfscFeOzPTC/hTwatbbpdTIaAZKpyrD/gB4hNiGFdKV1x1pw23KQkiPmQdFKxAHtIS20jeIa44q6kPltTQtZXXuM8s0xc6r+C14Q6igd4HkD0nLhAlKIQpcS/srXoeMheL3vNIroasHUwFgpv1LLJnMqYhCHzNk2Y6CaxYygg5Cy2gS9G1nfxdNVfF4iaUXYZKgU0s3C1GL0ApTtUxW0uT/NS0UBZwttsq9NvwmZSZQIXpfTnn0wHd4cl8MhokUQNEumFouU5rlEIcFS9ulohxaHnn50cqfos+seblKs2E+MJoX8rBO5Kz3dNE3+otZw9CpImskO4EKA2MYwtTC3Ds4uVoleS9PskCMz32jKXqp6WqZkJgpimHrdv0jNBy2ucTMdw91XjRXLA557GPRa/28TPpKkMYrSB02c2IadftexWKDP5Q9uMsfTEgIpXzx/XRQvPoxtJo+rOn9hTbyHWexKEMAuic12FBoYFOMSbRKtpT8kjtd8WeBzc1RmXZYpg5td5EN3v/2fmvM6F6Sz/db4HgNZIccC/j/fWvXN7njRl8bgMC002/tkQs0Ugl1aE5onaK9DTMHquqCLnd9CADwXdQf1YsfxryjhhBfd1WIfuqe1Ww=\n"
  },
  {
    "path": "BUILDING.md",
    "content": "setting up a build environment\n============================\n\nUnfortunately, 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.\n\nIn 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:\n```\n$ make env\n```\nOnce you've run `make env`, you should have a correctly configured build environment, and you should be ready to build SOS.\n\nIf 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:\n\ninstalling Rust\n---------------\n\nIn 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.\n\nThe 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:\n```\n$ curl https://sh.rustup.rs -sSf | sh\n```\n\nOnce Rustup is installed, run\n```\n$ rustup update nightly\n```\n\nto ensure the nightly release branch is up to date.\n\nIf you've set the stable or beta Rust release channels as the global default, you should run\n```\n$ rustup override nightly\n```\nin the SOS root directory, to set the nightly release channel as the default for SOS.\n\ninstalling build dependencies\n-----------------------------\n\nOnce you have Rust installed, you will need the following additional dependencies:\n+ `ld`\n+ `grub-mkrescue` & `xorriso`\n+ `qemu` for running the kernel under emulation\n+ `mtools`\n\nDepending on your OS, you'll want to install these dependencies somewhat differently.\n\n### linux\n\nOn Debian you can install them with\n\n```\n$ sudo apt-get install xorriso qemu mtools build-essential\n```\nOn Arch Linux you can install them with\n```\n$ sudo pacman -S --needed binutils grub libisoburn qemu mtools\n```\nAnd on Fedora with\n```\n$ sudo dnf instal xorriso qemu\n```\nOn Gentoo it's\n```\n$ sudo emerge app-emulation/qemu dev-libs/libisoburn sys-boot/grub\n```\n\nYou will also need `x86_64-elf-objcopy` and `x86_64-elf-strip` executables.\nOn x86_64 Linux you can simply symlink them to your regular `objcopy` and `strip`.\n\nIf you are using Gentoo but on another architecture you can build a cross-compiled version of `binutils` (which contains `objcopy` and `strip`) with\n```\n$ sudo emerge sys-devel/crossdev\n$ sudo crossdev -s0 --target x86_64-elf\n```\n\n### macOS\n\nInstalling 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.\n\nYou 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:\n\n```\n$ brew update\n$ brew tap Homebrew/bundle\n$ brew bundle\n```\n\nOnce you've installed the `Brewfile`, you'll need to cross-compile `binutils`.\n\nI've included a script to automatically download and cross-compile `binutils`, which you can run by typing:\n```\n$ ./scripts/install-mac.sh\n```\n\nAlternatively, if you want to do it manually, Phil Oppermann has a tutorial [here](http://os.phil-opp.com/cross-compile-binutils.html).\n\n### windows\nSeriously?\nWindows isn't supported; I can't possibly advise it.\n\ninstalling `xargo`\n-----------------\n\nOnce 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\n```\n$ cargo install xargo\n```\n"
  },
  {
    "path": "Brewfile",
    "content": "# for making a bootable ISO\nbrew 'xorriso'\n\n# for running the OS\nbrew 'qemu'\n\n# x86_64-pc-elf cross-compile toolchain\ntap 'hawkw/x86_64-pc-elf'\nbrew 'x86_64-pc-elf-gcc'\n\n# GRUB\ntap 'hawkw/grub'\nbrew 'grub', args: ['with-x86_64-pc-elf', 'HEAD']\n"
  },
  {
    "path": "CHANGES.md",
    "content": "<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_slice offset is T-aligned ([e7df6620](e7df6620))\n  *  fix arbitrary lifetime in elf::extract_from_slice ([60ed6a15](60ed6a15))\n  *  fix a typo in elf::file::Class ([99332049](99332049))\n  *  fix validation of elf section word size ([15eb3664](15eb3664))\n  *  make section header name offset a Word ([1583b718](1583b718))\n  *  fix a typo in elf::file::Class ([cbb9ca9d](cbb9ca9d))\n  *  fix validation of elf section word size ([cec0a13b](cec0a13b))\n  *  make section header name offset a Word ([89c4edd3](89c4edd3))\n* **x86_64:**  make kernel_init use re-written section headers ([19f75fe9](19f75fe9))\n\n#### Features\n\n* **elf:**\n  *  rewrite SectionHeader to be trait-based ([9d2eb03c](9d2eb03c), closes [#93](93))\n  *  add default type parameters for Image, default word type ([4c09e7ad](4c09e7ad))\n  *  changed extract_from_slice() to return a Result ([5e359b01](5e359b01))\n  *  start on convert::TryFrom<&'a [u8]> for elf image ([34fba817](34fba817))\n  *  add program headers slice ref to elf image ([caaf3245](caaf3245))\n  *  add struct representing 32-bit program header ([cc3f38af](cc3f38af))\n  *  add struct representation of 64-bit program header ([ee718532](ee718532))\n  *  begin implementing elf program header ([00d49e41](00d49e41))\n  *  add getters for more file header fields ([888d99fa](888d99fa))\n  *  add getters for returning file header fields as usize ([e2cf28dc](e2cf28dc))\n  *  add function to get the section header string table ([48036533](48036533))\n  *  ELF String Table made indexable ([c03e36f0](c03e36f0))\n  *  first pass on parsing ELF string tables ([5c266f0f](5c266f0f), closes [#83](83))\n  *  nicer handling of ELF sections with invalid type fields ([9083e9ba](9083e9ba))\n  *  add fmt::Display implementation for ELF sections ([4eb34a3a](4eb34a3a))\n  *  add getters for more file header fields ([ae29fe71](ae29fe71))\n  *  add getters for returning file header fields as usize ([3b6078fd](3b6078fd))\n  *  add function to get the section header string table ([a8002040](a8002040))\n  *  ELF String Table made indexable ([966d683b](966d683b))\n  *  first pass on parsing ELF string tables ([9e5b195d](9e5b195d), closes [#83](83))\n  *  nicer handling of ELF sections with invalid type fields ([8c07e373](8c07e373))\n  *  add fmt::Display implementation for ELF sections ([50c04cea](50c04cea))\n* **multiboot2:**  add IntoIter implementations for tags ([4a546e7a](4a546e7a))\n* **x86_all:**\n  *  multiboot2 mem areas iterator doesn't skip ACPI areas ([3310f1fc](3310f1fc))\n  *  multiboot2 mem areas iterator doesn't skip ACPI areas ([2487f494](2487f494))\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, we as\ncontributors and maintainers pledge to making participation in our project and\nour community a harassment-free experience for everyone, regardless of age, body\nsize, disability, ethnicity, gender identity and expression, level of experience,\nnationality, personal appearance, race, religion, or sexual identity and\norientation.\n\n## Our Standards\n\nExamples of behavior that contributes to creating a positive environment\ninclude:\n\n* Using welcoming and inclusive language\n* Being respectful of differing viewpoints and experiences\n* Gracefully accepting constructive criticism\n* Focusing on what is best for the community\n* Showing empathy towards other community members\n\nExamples of unacceptable behavior by participants include:\n\n* The use of sexualized language or imagery and unwelcome sexual attention or\nadvances\n* Trolling, insulting/derogatory comments, and personal or political attacks\n* Public or private harassment\n* Publishing others' private information, such as a physical or electronic\n  address, without explicit permission\n* Other conduct which could reasonably be considered inappropriate in a\n  professional setting\n\n## Our Responsibilities\n\nProject maintainers are responsible for clarifying the standards of acceptable\nbehavior and are expected to take appropriate and fair corrective action in\nresponse to any instances of unacceptable behavior.\n\nProject maintainers have the right and responsibility to remove, edit, or\nreject comments, commits, code, wiki edits, issues, and other contributions\nthat are not aligned to this Code of Conduct, or to ban temporarily or\npermanently any contributor for other behaviors that they deem inappropriate,\nthreatening, offensive, or harmful.\n\n## Scope\n\nThis Code of Conduct applies both within project spaces and in public spaces\nwhen an individual is representing the project or its community. Examples of\nrepresenting a project or community include using an official project e-mail\naddress, posting via an official social media account, or acting as an appointed\nrepresentative at an online or offline event. Representation of a project may be\nfurther defined and clarified by project maintainers.\n\n## Enforcement\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be\nreported by contacting the project team at [eliza@elizas.website]. All\ncomplaints will be reviewed and investigated and will result in a response that\nis deemed necessary and appropriate to the circumstances. The project team is\nobligated to maintain confidentiality with regard to the reporter of an incident.\nFurther details of specific enforcement policies may be posted separately.\n\nProject maintainers who do not follow or enforce the Code of Conduct in good\nfaith may face temporary or permanent repercussions as determined by other\nmembers of the project's leadership.\n\n## Attribution\n\nThis Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,\navailable at [http://contributor-covenant.org/version/1/4][version]\n\n[homepage]: http://contributor-covenant.org\n[version]: http://contributor-covenant.org/version/1/4/\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "Contributing to SOS\n===================\n\n**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.\n\n### Table of Contents\n\n+ [What do I need to know before contributing?](#what-do-i-need-to-know-before-contributing)\n    - [Code of Conduct](#code-of-conduct)\n    - [Licensing](#licensing)\n    - [Setting Up a Dev Environment](#setting-up-a-dev-environment)\n+ [Project Goals & Objectives](#project-goals--objectives)\n+ [Conventions & Style Guides](#conventions--style-guides)\n    - [Git Conventions](#git-conventions)\n        * [Pull Requests](#pull-requests)\n        * [Commit Messages](#commit-messages)\n    - [Coding Style](#coding-style)\n        * [Tools to assist with coding style](#tools-to-assist-with-coding-style)\n\nWhat do I need to know before contributing?\n===========================================\n\n### Code of Conduct\n\nThis project adheres to the Contributor Covenant [code of conduct](CODE_OF_CONDUCT.md).\nBy participating, you are expected to uphold this code.\nPlease report unacceptable behavior to [eliza@elizas.website](mailto:eliza@elizas.website).\n\n### Licensing\n\nSOS 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.\n\n### Setting Up a Dev Environment\n\nBuilding 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.\n\nIn 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.\n\nProject Goals & Objectives\n==========================\n\n+ Minimise assembly language code\n    + Ideally, files ending in `.asm` should be used ONLY for the boot sequence\n    + 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.\n    + This has the following advantages:\n        + It requires less linker configuration and makes building SOS much less of a pain.\n        + It makes it much easier for Rust code to call code written in assembly language without mucking around with FFI.\n        + 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.\n+ Eventually, be able to boot on x86, x86_64, and ARMv7 machines.\n+ Move as much out of kernel space as seems reasonable.\n\n\nConventions & Style Guides\n==========================\n\nGit Conventions\n---------------\n\n### Pull requests\n\nIn order to be accepted and merged, a pull request must meet the following conditions.\n\n##### Pull requests MUST\n\n+ Build successfully on [Travis](https://travis-ci.org/hawkw/sos-kernel)\n+ Include RustDoc comments for any public-facing API functions or types\n+ Include tests for any added features\n+ Reference any closed issues with the text \"Closes #XX\" or \"Fixes #XX\" in the pull request description\n\n##### Pull requests MUST NOT\n\n+ Include any failing tests\n+ Decrease overall project test coverage\n+ Have any outstanding changes requested by a reviewer.\n\n### Commit messages\n\nCommit 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.\n\nIt 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:\n\n##### Commit messages MUST\n\n+ Be in present tense\n+ Follow the form `<type>(<scope>): <subject>`\n    + where `<type>` is one of:\n        * **feat**: A new feature\n        * **fix**: A bug fix\n        * **docs**: Documentation only changes\n        * **style**: Changes that do not affect the meaning of the code (white-space, formatting, missing\n        semi-colons, etc)\n        * **refactor**: A code change that neither fixes a bug or adds a feature\n        * **perf**: A code change that improves performance\n        * **test**: Adding missing tests\n        * **chore**: Changes to the build process or auxiliary tools and libraries such as documentation\n        generation\n    + and `<scope>` (optionally) specifies the specific element or component of the project that was changed.\n\n##### Commit messages MUST NOT\n\n+ Include lines exceeding 100 characters\n\n##### Commit messages MAY\n\n+ Include the text `[skip ci]` if changing non-Rustdoc documentation.\n    + This will cause Travis CI to skip building that commit.\n    + 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`\n    + Commits which change configuration files for tools not used by Travis may also skip the CI build, at the discretion of the committer.\n\n\nCode Style\n----------\n\nRust code should:\n+ 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.\n    + In particular, it should...\n        + ...be indented with 4 spaces\n        + ...not end files with trailing whitespace\n        + ...follow the [Rust naming conventions](https://github.com/rust-lang/rust/tree/master/src/doc/style/style/)\n    + An `.editorconfig` file is available for [compatible text editors](http://editorconfig.org/#download).\n+ Use [comma-first style](https://gist.github.com/isaacs/357981) for all comma-delimited constructs.\n+ Not exceed 80 characters per line.\n\nThe following deviations from the style guide are permitted:\n+ [Comma-first style](https://gist.github.com/isaacs/357981) _may_ be used for all comma-delimited constructs. For example:\n\n    ```rust\n    let a_list = [ a\n                 , b\n                 , c\n                 ];\n    ```\n\n    and\n\n    ```rust\n    let a_list = [ a, b, c, d\n                 , e, f, g, h\n                 ];\n    ```\n    are considered good style.\n\n+ When wrapping `where` clauses, place them at the same indentation level as the corresponding `fn` or `impl` statement. For example:\n    ```rust\n    // Considered good style\n    fn foo<A>(a: A) where A: Something {\n        ...\n    }\n    ```\n    and\n    ```rust\n    // Considered good style\n    fn bar<A, B>(a: A) -> B\n    where A: Something\n        , B: Something + SomethingElse {\n        ...\n    }\n    ```\n    are considered good style, while\n    ```rust\n    // NOT considered good style\n    fn baz<A, B>(a: A) -> B\n        where A: Something\n            , B: SomethingElse {\n                ...\n            }\n    ```\n    is not.\n\n\n### Tools to Assist With Coding Style\n\n#### EditorConfig\n\nAn [`.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.\n\n#### rustfmt\n\n[`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.\n\n`rustfmt` may be installed by running\n\n```bash\n$ cargo install rustfmt\n```\n\nand invoked on a crate by running\n\n```bash\n$ cargo fmt\n```\n\nAdditionally, there are `rustfmt` plugins [available](https://github.com/rust-lang-nursery/rustfmt#running-rustfmt-from-your-editor) for many popular editors and IDEs.\n\n`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.\n"
  },
  {
    "path": "Cargo.toml",
    "content": "[package]\nname = \"sos_kernel\"\nversion = \"0.1.0\"\nauthors = [ # hacked around by\n            \"Eliza Weisman <eliza@elizas.website>\"\n          , # based on code by\n            \"Philipp Oppermann <dev@phil-opp.com>\"\n          ]\n\nbuild = \"build.rs\"\n# build = false\n# [[bin]]\n# name = \"sos_kernel_full\"\n\n# [lib]\n# crate-type = [\"staticlib\"]\n#\n\n[profile.dev]\nopt-level = 3\ndebug = true\nrpath = false\nlto = false\ndebug-assertions = true\ncodegen-units = 1\npanic = \"abort\"\n\n[profile.release]\nopt-level = 3\ndebug = true\nrpath = false\nlto = false\npanic = \"abort\"\n\n[features]\ndefault = []\ntrace = []\n\n[dependencies]\nrlibc = \"0.1.4\"\nspin = \"0.4.6\"\nonce = \"0.3.2\"\nbitflags = \"0.7\"\ncpu = { path = \"cpu\" }\nmemory = { path = \"memory\" }\nutil = { path = \"util\" }\nelf = { path = \"elf\" }\npaging = { path = \"paging\" }\nparams = { path = \"params\" }\n\n[dependencies.log]\nversion = \"0.3.6\"\ndefault-features = false\nfeatures = [\"release_max_level_info\"]\n\n[dependencies.lazy_static]\nversion = \"0.2.11\"\nfeatures = [\"spin_no_std\"]\n\n[dependencies.vga]\npath = \"vga\"\nfeatures = [\"kinfo\", \"system_term\"]\n\n[dependencies.sos_alloc]\npath = \"sos_alloc\"\nfeatures = [\"buddy\", \"system\", \"borrow\", \"buddy_as_system\"]\n\n[dependencies.clippy]\nversion = \"0.0.60\"\noptional = true\n"
  },
  {
    "path": "LICENSE-APACHE",
    "content": "                              Apache License\n                        Version 2.0, January 2004\n                     http://www.apache.org/licenses/\n\nTERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n1. Definitions.\n\n   \"License\" shall mean the terms and conditions for use, reproduction,\n   and distribution as defined by Sections 1 through 9 of this document.\n\n   \"Licensor\" shall mean the copyright owner or entity authorized by\n   the copyright owner that is granting the License.\n\n   \"Legal Entity\" shall mean the union of the acting entity and all\n   other entities that control, are controlled by, or are under common\n   control with that entity. For the purposes of this definition,\n   \"control\" means (i) the power, direct or indirect, to cause the\n   direction or management of such entity, whether by contract or\n   otherwise, or (ii) ownership of fifty percent (50%) or more of the\n   outstanding shares, or (iii) beneficial ownership of such entity.\n\n   \"You\" (or \"Your\") shall mean an individual or Legal Entity\n   exercising permissions granted by this License.\n\n   \"Source\" form shall mean the preferred form for making modifications,\n   including but not limited to software source code, documentation\n   source, and configuration files.\n\n   \"Object\" form shall mean any form resulting from mechanical\n   transformation or translation of a Source form, including but\n   not limited to compiled object code, generated documentation,\n   and conversions to other media types.\n\n   \"Work\" shall mean the work of authorship, whether in Source or\n   Object form, made available under the License, as indicated by a\n   copyright notice that is included in or attached to the work\n   (an example is provided in the Appendix below).\n\n   \"Derivative Works\" shall mean any work, whether in Source or Object\n   form, that is based on (or derived from) the Work and for which the\n   editorial revisions, annotations, elaborations, or other modifications\n   represent, as a whole, an original work of authorship. For the purposes\n   of this License, Derivative Works shall not include works that remain\n   separable from, or merely link (or bind by name) to the interfaces of,\n   the Work and Derivative Works thereof.\n\n   \"Contribution\" shall mean any work of authorship, including\n   the original version of the Work and any modifications or additions\n   to that Work or Derivative Works thereof, that is intentionally\n   submitted to Licensor for inclusion in the Work by the copyright owner\n   or by an individual or Legal Entity authorized to submit on behalf of\n   the copyright owner. For the purposes of this definition, \"submitted\"\n   means any form of electronic, verbal, or written communication sent\n   to the Licensor or its representatives, including but not limited to\n   communication on electronic mailing lists, source code control systems,\n   and issue tracking systems that are managed by, or on behalf of, the\n   Licensor for the purpose of discussing and improving the Work, but\n   excluding communication that is conspicuously marked or otherwise\n   designated in writing by the copyright owner as \"Not a Contribution.\"\n\n   \"Contributor\" shall mean Licensor and any individual or Legal Entity\n   on behalf of whom a Contribution has been received by Licensor and\n   subsequently incorporated within the Work.\n\n2. Grant of Copyright License. Subject to the terms and conditions of\n   this License, each Contributor hereby grants to You a perpetual,\n   worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n   copyright license to reproduce, prepare Derivative Works of,\n   publicly display, publicly perform, sublicense, and distribute the\n   Work and such Derivative Works in Source or Object form.\n\n3. Grant of Patent License. Subject to the terms and conditions of\n   this License, each Contributor hereby grants to You a perpetual,\n   worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n   (except as stated in this section) patent license to make, have made,\n   use, offer to sell, sell, import, and otherwise transfer the Work,\n   where such license applies only to those patent claims licensable\n   by such Contributor that are necessarily infringed by their\n   Contribution(s) alone or by combination of their Contribution(s)\n   with the Work to which such Contribution(s) was submitted. If You\n   institute patent litigation against any entity (including a\n   cross-claim or counterclaim in a lawsuit) alleging that the Work\n   or a Contribution incorporated within the Work constitutes direct\n   or contributory patent infringement, then any patent licenses\n   granted to You under this License for that Work shall terminate\n   as of the date such litigation is filed.\n\n4. Redistribution. You may reproduce and distribute copies of the\n   Work or Derivative Works thereof in any medium, with or without\n   modifications, and in Source or Object form, provided that You\n   meet the following conditions:\n\n   (a) You must give any other recipients of the Work or\n       Derivative Works a copy of this License; and\n\n   (b) You must cause any modified files to carry prominent notices\n       stating that You changed the files; and\n\n   (c) You must retain, in the Source form of any Derivative Works\n       that You distribute, all copyright, patent, trademark, and\n       attribution notices from the Source form of the Work,\n       excluding those notices that do not pertain to any part of\n       the Derivative Works; and\n\n   (d) If the Work includes a \"NOTICE\" text file as part of its\n       distribution, then any Derivative Works that You distribute must\n       include a readable copy of the attribution notices contained\n       within such NOTICE file, excluding those notices that do not\n       pertain to any part of the Derivative Works, in at least one\n       of the following places: within a NOTICE text file distributed\n       as part of the Derivative Works; within the Source form or\n       documentation, if provided along with the Derivative Works; or,\n       within a display generated by the Derivative Works, if and\n       wherever such third-party notices normally appear. The contents\n       of the NOTICE file are for informational purposes only and\n       do not modify the License. You may add Your own attribution\n       notices within Derivative Works that You distribute, alongside\n       or as an addendum to the NOTICE text from the Work, provided\n       that such additional attribution notices cannot be construed\n       as modifying the License.\n\n   You may add Your own copyright statement to Your modifications and\n   may provide additional or different license terms and conditions\n   for use, reproduction, or distribution of Your modifications, or\n   for any such Derivative Works as a whole, provided Your use,\n   reproduction, and distribution of the Work otherwise complies with\n   the conditions stated in this License.\n\n5. Submission of Contributions. Unless You explicitly state otherwise,\n   any Contribution intentionally submitted for inclusion in the Work\n   by You to the Licensor shall be under the terms and conditions of\n   this License, without any additional terms or conditions.\n   Notwithstanding the above, nothing herein shall supersede or modify\n   the terms of any separate license agreement you may have executed\n   with Licensor regarding such Contributions.\n\n6. Trademarks. This License does not grant permission to use the trade\n   names, trademarks, service marks, or product names of the Licensor,\n   except as required for reasonable and customary use in describing the\n   origin of the Work and reproducing the content of the NOTICE file.\n\n7. Disclaimer of Warranty. Unless required by applicable law or\n   agreed to in writing, Licensor provides the Work (and each\n   Contributor provides its Contributions) on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n   implied, including, without limitation, any warranties or conditions\n   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n   PARTICULAR PURPOSE. You are solely responsible for determining the\n   appropriateness of using or redistributing the Work and assume any\n   risks associated with Your exercise of permissions under this License.\n\n8. Limitation of Liability. In no event and under no legal theory,\n   whether in tort (including negligence), contract, or otherwise,\n   unless required by applicable law (such as deliberate and grossly\n   negligent acts) or agreed to in writing, shall any Contributor be\n   liable to You for damages, including any direct, indirect, special,\n   incidental, or consequential damages of any character arising as a\n   result of this License or out of the use or inability to use the\n   Work (including but not limited to damages for loss of goodwill,\n   work stoppage, computer failure or malfunction, or any and all\n   other commercial damages or losses), even if such Contributor\n   has been advised of the possibility of such damages.\n\n9. Accepting Warranty or Additional Liability. While redistributing\n   the Work or Derivative Works thereof, You may choose to offer,\n   and charge a fee for, acceptance of support, warranty, indemnity,\n   or other liability obligations and/or rights consistent with this\n   License. However, in accepting such obligations, You may act only\n   on Your own behalf and on Your sole responsibility, not on behalf\n   of any other Contributor, and only if You agree to indemnify,\n   defend, and hold each Contributor harmless for any liability\n   incurred by, or claims asserted against, such Contributor by reason\n   of your accepting any such warranty or additional liability.\n\nEND OF TERMS AND CONDITIONS\n\nAPPENDIX: How to apply the Apache License to your work.\n\n   To apply the Apache License to your work, attach the following\n   boilerplate notice, with the fields enclosed by brackets \"[]\"\n   replaced with your own identifying information. (Don't include\n   the brackets!)  The text should be enclosed in the appropriate\n   comment syntax for the file format. We also recommend that a\n   file or class name and description of purpose be included on the\n   same \"printed page\" as the copyright notice for easier\n   identification within third-party archives.\n\nCopyright [yyyy] [name of copyright owner]\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n"
  },
  {
    "path": "LICENSE-MIT",
    "content": "Copyright (c) 2015 The SOS Developers\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "Makefile",
    "content": "arch ?= x86_64\ntarget ?= $(arch)-sos-kernel-gnu\n\nboot_target := x86_32-sos-bootstrap-gnu\nboot_outdir := boot/target/$(boot_target)\n\niso := target/$(target)/debug/sos-$(arch).iso\nkernel := target/$(target)/debug/sos_kernel\nisofiles := target/$(target)/debug/isofiles\nboot := $(boot_outdir)/debug/libboot.a\n\n\nrelease_iso := target/$(target)/release/sos-$(arch).iso\nrelease_kernel := target/$(target)/release/sos_kernel\nrelease_isofiles := target/$(target)/release/isofiles\nrelease_boot := $(boot_outdir)/release/libboot.a\n\ngrub_cfg := src/arch/$(arch)/grub.cfg\n\nTIMESTAMP := $(shell /bin/date \"+%Y-%m-%d-%H:%M:%S\")\n\n# wildcard paths\nwild_iso := target/$(target)/%/sos-$(arch).iso\nwild_kernel := target/$(target)/%/sos_kernel\nwild_isofiles := target/$(target)/%/isofiles\n\n#COLORS\nGREEN  := $(shell tput -Txterm setaf 2)\nWHITE  := $(shell tput -Txterm setaf 7)\nYELLOW := $(shell tput -Txterm setaf 3)\nRESET  := $(shell tput -Txterm sgr0)\n\n# Add the following 'help' target to your Makefile\n# And add help text after each target name starting with '\\#\\#'\n# A category can be added with @category\nHELP_FUN = \\\n    %help; \\\n    while(<>) { push @{$$help{$$2 // 'options'}}, [$$1, $$3] if /^([a-zA-Z\\-]+)\\s*:.*\\#\\#(?:@([a-zA-Z\\-]+))?\\s(.*)$$/ }; \\\n    print \"usage: make [target]\\n\\n\"; \\\n    for (sort keys %help) { \\\n    print \"${WHITE}$$_:${RESET}\\n\"; \\\n    for (@{$$help{$$_}}) { \\\n    $$sep = \" \" x (20 - length $$_->[0]); \\\n    print \"  ${YELLOW}$$_->[0]${RESET}$$sep${GREEN}$$_->[1]${RESET}\\n\"; \\\n    }; \\\n    print \"\\n\"; }\n\n.PHONY: all clean kernel run iso cargo help gdb test doc release-iso release-run release-kernel\n\nexception: $(iso) ##@build Run the kernel, dumping the state from QEMU if an exception occurs\n\t@qemu-system-x86_64 -s -hda $(iso) -d int -no-reboot -serial file:$(CURDIR)/target/$(target)/serial-$(TIMESTAMP).log\n\ncargo:\n\ndoc: ##@utilities Make RustDoc documentation\n\t@xargo doc\n\nhelp: ##@miscellaneous Show this help.\n\t@perl -e '$(HELP_FUN)' $(MAKEFILE_LIST)\n\nall: help\n\nenv: ##@utilities Install dev environment dependencies\n\t./scripts/install-env.sh\n\nclean: ##@utilities Delete all build artefacts.\n\t@xargo clean\n\t@cd boot && xargo clean\n\nkernel: $(kernel).bin ##@build Compile the debug kernel binary\n\niso: $(iso) ##@build Compile the kernel binary and make an ISO image\n\nrun: run-debug ##@build Make the kernel ISO image and boot QEMU from it.\n\nrelease-kernel: $(release_kernel).bin ##@release Compile the release kernel binary\n\nrelease-iso: $(release_iso) ##@release Compile the release kernel binary and make an ISO image\n\nrelease-run: run-release ##@release Make the release kernel ISO image and boot QEMU from it.\n\ndebug: $(iso) ##@build Run the kernel, redirecting serial output to a logfile.\n\t@qemu-system-x86_64 -s -S -hda $(iso) -serial file:$(CURDIR)/target/$(target)/serial-$(TIMESTAMP).log\n\ntest: ##@build Test crate dependencies\n\t@cargo test -p sos_intrusive\n\t# @xargo test -p alloc\n\t@cd alloc && cargo test\n\nrun-%: $(wild_iso)\n\t@qemu-system-x86_64 -s -hda $<\n\n$(wild_iso): $(wild_kernel).bin $(wild_isofiles) $(grub_cfg)\n\t@cp $< $(word 2,$^)/boot/\n\t@cp $(grub_cfg) $(word 2,$^)/boot/grub\n\tgrub-mkrescue -o $@ $(word 2,$^)/\n\t@rm -r $(word 2,$^)\n\n$(wild_isofiles):\n\t@mkdir -p $@/boot/grub\n\n$(boot):\n\t@cd boot && RUST_TARGET_PATH=\"$(PWD)/targets\" xargo rustc \\\n\t\t--target $(boot_target) \\\n\t\t-- --crate-type=staticlib\n\t# Place 32-bit bootstrap code into a 64-bit ELF\n\t@x86_64-pc-elf-objcopy -O elf64-x86-64 \\\n\t\t$(boot_outdir)/debug/libboot32.a \\\n\t\t$(boot_outdir)/debug/libboot.a\n\t@x86_64-pc-elf-objcopy --strip-debug -G _start \\\n\t\t$(boot_outdir)/debug/libboot.a\n\t# @cd $(boot_outdir)/debug && ar -crus libboot.a boot.o\n\n$(release_boot):\n\t@cd boot && RUST_TARGET_PATH=\"$(PWD)/targets\" xargo rustc \\\n\t\t--target $(boot_target) \\\n\t\t-- --release \\\n\t\t--crate-type=staticlib\n\t# Place 32-bit bootstrap code into a 64-bit ELF\n\t@x86_64-pc-elf-objcopy -O elf64-x86-64 \\\n\t\t$(boot_outdir)/release/libboot32.a \\\n\t\t$(boot_outdir)/release/libboot.a\n\t@x86_64-pc-elf-objcopy --strip-debug -G _start \\\n\t\t$(boot_outdir)/release/libboot.a\n\n$(release_kernel): $(release_boot)\n\t@RUST_TARGET_PATH=\"$(PWD)/targets\" xargo build --target $(target) --release\n\n$(release_kernel).bin: $(release_kernel)\n\t@cp $(release_kernel) $(release_kernel).bin\n\n$(release_iso): $(release_kernel).bin $(grub_cfg)\n\t@mkdir -p $(release_isofiles)/boot/grub\n\t@cp $(release_kernel).bin $(release_isofiles)/boot/\n\t@cp $(grub_cfg) $(release_isofiles)/boot/grub\n\t@grub-mkrescue -o $(release_iso) $(release_isofiles)/\n\t@rm -r $(release_isofiles)\n\n$(kernel): $(boot)\n\t@RUST_TARGET_PATH=\"$(PWD)/targets\" xargo build --target $(target)\n\n$(kernel).debug: $(kernel)\n\t@x86_64-elf-objcopy --only-keep-debug $(kernel) $(kernel).debug\n\n$(kernel).bin: $(kernel) $(kernel).debug\n\t@x86_64-elf-strip -g -o $(kernel).bin $(kernel)\n\t@x86_64-elf-objcopy --add-gnu-debuglink=$(kernel).debug $(kernel)\n\ngdb: $(kernel).bin $(kernel).debug ##@utilities Connect to a running QEMU instance with gdb.\n\t@rust-os-gdb -ex \"target remote tcp:127.0.0.1:1234\" $(kernel)\n"
  },
  {
    "path": "Notes.md",
    "content": "Notes\n=====\n\nOn designing a userland\n-----------------------\n\n+ provide user code written in Rust with a fluent Rust API\n+ [capability-based security](https://en.wikipedia.org/wiki/Capability-based_security)\n\n#### prior art\n+ `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.\n+ `kqueue` is good\n"
  },
  {
    "path": "README.md",
    "content": "# Stupid Operating System \n[![Build Status](https://travis-ci.org/hawkw/sos-kernel.svg?branch=master)](https://travis-ci.org/hawkw/kernel) \n[![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) \n[![Gitter](https://img.shields.io/gitter/room/sos-os/kernel.svg)](https://gitter.im/sos-os)\n\nSOS is a simple, tiny toy OS implemented in Rust.\n\nI'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.\n\nInspiration, 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).\n\ndesign goals\n------------\n\n + **POSIX compliance is not a goal** (though it would be cool)\n + **Hybrid/loosely microkernel** (i.e., move code to user space *when convenient/practical*)\n + Possibly provide the **Rust stdlib** at the OS level.\n + **JVM-style** memory allocation?\n + Possibly experiment with a **[Plan 9-esque](https://en.wikipedia.org/wiki/9P_(protocol)) networking stack** eventually?\n\n\nbuilding & running\n------------------\n\nI'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.\n\n### setting up your build environment\nIn 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.\n\n+ `$ make env` will install and configure build dependencies\n\nIf 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).\n\n### building & running the OS\n  + `$ make kernel` compiles & links the kernel binary\n  + `$ make iso` makes the kernel and builds a bootable ISO image\n  + `$ make run` compiles the kernel, makes the ISO, and boots QEMU from the ISO\n"
  },
  {
    "path": "Vagrantfile",
    "content": "# -*- mode: ruby -*-\n# vi: set ft=ruby :\n\nVagrant.configure(2) do |config|\n  config.vm.box = \"hashicorp/precise64\"\n\n  config.vm.provision \"shell\", inline: <<-SHELL\n    sudo apt-get update\n    sudo apt-get install -y build-essential\n    sudo apt-get install -y curl\n    sudo apt-get install nasm -y\n    sudo apt-get install xorriso -y\n    sudo apt-get install git -y\n    sudo apt-get install vim -y\n    sudo apt-get install -y qemu\n    su - vagrant -c 'curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain nightly'\n    ex +'$s@$@\\rexport PATH=~/.cargo/bin/:$PATH@' -cwq /etc/bash.bashrc\n  SHELL\n\n  config.ssh.forward_x11 = true\nend\n"
  },
  {
    "path": "Xargo.toml",
    "content": "[target.x86_64-sos-kernel-gnu.dependencies]\nalloc = {}\n# std = {}\n"
  },
  {
    "path": "boot/Cargo.toml",
    "content": "[package]\nname = \"boot32\"\nversion = \"0.1.0\"\nauthors = [\"Eliza Weisman <eliza@elizas.website>\"]\n\n[lib]\ncrate-type = [\"staticlib\"]\n\n# [[bin]]\n# name = \"libboot32.a\"\n\n[features]\ndefault = [\"log\"]\nlog = []\n\n[profile.dev]\nopt-level = 3\ndebug = true\nrpath = false\nlto = false\ndebug-assertions = true\ncodegen-units = 1\npanic = \"abort\"\n\n[profile.release]\nopt-level = 3\ndebug = true\nrpath = false\nlto = false\npanic = \"abort\"\n\n[dependencies]\nrlibc = \"0.1.4\"\n"
  },
  {
    "path": "boot/README.md",
    "content": "# SOS x86_64 bootstrap\n\nthis 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.\n\nthis 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.\n\nthis boot crate is only necessary for x86_64. for other architectures, all boot code can live in the main kernel crate.\n"
  },
  {
    "path": "boot/src/lib.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2016-2017 Eliza Weisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\n//! # SOS x86_64 bootstrap\n//!\n//! This crate contains code for the 32-bit protected mode boot routine for\n//! x86_64 CPUs. When we boot up an x86_64 system using GRUB & multiboot, we\n//! end up with the CPU running in 32-bit 'protected mode', rather than 64-bit\n//! 'long mode'. Before we can jump into long mode, we have to perform a\n//! handful of setup tasks in protected mode.\n//!\n//! This boot routine lives in a separate crate, with a 32-bit `target.json`.\n//! When building SOS for x86_64, we have to compile this crate separately and\n//! then link the resulting 32-bit object with the rest of the 64-bit kernel\n//! object.\n//!\n//! This boot crate is only necessary for x86_64. For other architectures, all\n//! boot code can live in the main kernel crate.\n//!\n//! For more information, refer to:\n//! + the [intermezzOS book]\n//! + the [OSDev Wiki] article on long mode\n//! + Philipp Oppermann's [blog post]\n//!\n//! [intermezzOS book]: http://intermezzos.github.io/book/transitioning-to-long-mode.html\n//! [OSDev Wiki]: http://wiki.osdev.org/Long_Mode#Long_Mode\n//! [blog post]: http://os.phil-opp.com/entering-longmode.html\n\n#![crate_name = \"boot32\"]\n#![feature(asm)]\n#![feature(lang_items)]\n#![feature(naked_functions)]\n#![feature(linkage)]\n#![feature(struct_field_attributes)]\n#![feature(stmt_expr_attributes)]\n#![no_std]\n\nextern crate rlibc;\n\nconst TABLE_LENGTH: usize = 512;\n/// The size of a \"huge\" page\nconst HUGE_PAGE_SIZE: u64 = 2 * 1024 * 1024; // 2 MiB\n/// Page table entry flags for a page that is present and writable.\nconst ENTRY_FLAGS_PW: u64 = 0b11;\n\n/// A page table is an array of page table entries.\ntype Table = [TableEntry; TABLE_LENGTH];\n\ntrait PageTable: Sized {\n    /// Install this page table as the top-level page table.\n    #[inline(always)]\n    unsafe fn set_top_level(&'static self) {\n        asm!(\"mov cr3, $0\" :: \"r\"(self) :: \"intel\");\n    }\n}\n\nimpl PageTable for Table { }\n\n/// A page table entry is a 64-bit unsigned integer.\n///\n/// We represent this as a [newtype] rather than a type alias, because we want\n/// to implement specific functionality on it.\n///\n/// [newtype]: https://aturon.github.io/features/types/newtype.html\n#[repr(C)]\nstruct TableEntry(u64);\n\nimpl TableEntry {\n    /// Set this table entry to map to a lower-level page table.\n    // TODO: use a marker type to ensure this always maps to a _lower-level_\n    //       table?\n    #[inline(always)]\n    unsafe fn map_to_table(&mut self, to: &'static Table) {\n        *self = TableEntry(to as *const _ as u64 | ENTRY_FLAGS_PW);\n    }\n\n    /// Set this table entry to map to a huge page with the given number.\n    #[inline(always)]\n    unsafe fn map_to_page(&mut self, number: usize) {\n        // Page table entry flags for a page that is huge, present, and writable.\n        const ENTRY_FLAGS_HUGE: u64 = 0b10000011;\n        // the start address is the page number times the page's size\n        let addr = number as u64 * HUGE_PAGE_SIZE;\n        *self = TableEntry(addr | ENTRY_FLAGS_HUGE);\n    }\n\n}\n\nuse core::convert;\n\nmacro_rules! set_flags {\n    (%$register:ident $( |= $body:expr);+ ) => {\n        let mut $register: usize;\n        asm!( concat!(\"mov $0, \", stringify!($register))\n            : \"=r\"($register)\n            ::: \"intel\");\n        $($register |= $body;)+\n        asm!( concat!(\"mov \", stringify!($register), \", $0\")\n            :: \"r\"($register)\n            :: \"intel\");\n    }\n}\n\n#[repr(C, packed)]\npub struct Gdt { _null: u64\n               , code: u64\n               }\n\n#[repr(C, packed)]\npub struct GdtPointer { /// the length of the GDT\n                        pub limit: u16\n                      , /// pointer to the GDT\n                        pub base: &'static Gdt\n                      }\n\nimpl GdtPointer {\n    #[cold] #[inline(always)]\n    unsafe fn load (&self) {\n        asm!(\"lgdt ($0)\" :: \"r\"(self) : \"memory\");\n    }\n}\n\nimpl convert::From<&'static Gdt> for GdtPointer {\n    #[cold] #[inline(always)]\n    fn from(gdt: &'static Gdt) -> Self {\n        use core::mem::size_of_val;\n        GdtPointer { limit: size_of_val(gdt) as u16 - 1\n                   , base: gdt }\n    }\n}\n\n#[link_name = \".gdt64\"]\n#[link_section = \".gdt\"]\n#[no_mangle]\npub static GDT: Gdt\n    = Gdt { _null: 0\n          , code: (1<<44) | (1<<47) | (1<<41) | (1<<43) | (1<<53)\n          };\n\n#[inline(always)]\nfn boot_write(s: &[u8]) {\n    unsafe {\n        use core::ptr::write_volatile;\n        let vga_buf = 0xb8000 as *mut u16;\n    \tfor (n, c) in s.iter().enumerate() {\n    \t\twrite_volatile(vga_buf.offset(n as isize), 0x0200 + *c as u16);\n    \t}\n\n    }\n\n}\n\nextern \"C\" {\n    static mut pml4_table: Table;\n    static mut pdp_table: Table;\n    static mut pd_table: Table;\n}\n\n#[cold]\n#[inline(always)]\n#[naked]\nunsafe fn create_page_tables() {\n    //-- map the PML4 and PDP tables -----------------------------------------\n    // recursive map last PML4 entry\n    pml4_table[511].map_to_table(&pml4_table);\n    // map first PML4 entry to PDP table\n    pml4_table[0].map_to_table(&pdp_table);\n    // map first PDPT entry to PD table\n    pdp_table[0].map_to_table(&pd_table);\n\n    boot_write(b\"3.1\");\n\n    //-- map the PD table ----------------------------------------------------\n    for (page_number, entry) in pd_table.iter_mut().enumerate() {\n        entry.map_to_page(page_number);\n    }\n\n    boot_write(b\"3.2\");\n}\n\n#[cold]\n#[inline(always)]\nunsafe fn set_long_mode() {\n    // load PML4 addr to cr3\n    &pml4_table.set_top_level();\n    boot_write(b\"3.3\");\n\n    // // enable PAE flag in cr4\n    // set_flags!(%cr4 |= 1 << 5 );\n    asm!(\"mov eax, cr4\n          or eax, 1 << 5\n          mov cr4, eax\" ::: \"memory\" : \"intel\", \"volatile\");\n    boot_write(b\"3.4\");\n\n    // set the long mode bit in EFER MSR (model specific register)\n    asm!( \"mov   ecx, 0xC0000080\n           rdmsr\n           or    eax, 1 << 8\n           wrmsr\"\n        :::\"memory\": \"intel\", \"volatile\");\n    boot_write(b\"3.5\");\n\n    // enable paging in cr0\n    // set_flags!(%cr0 |= 1 << 31;\n    //                 |= 1 << 16 );\n\n    asm!(\"mov eax, cr0\n          or eax, 0x80000000\n          mov cr0, eax\" :::\"memory\": \"intel\", \"volatile\");\n    boot_write(b\"3.6\")\n}\n\n/// Test whether or not this system supports Multiboot 2\n#[cold]\n#[inline(always)]\nunsafe fn is_multiboot_supported() -> bool {\n    const MULTIBOOT_MAGIC: usize = 0x36d76289;\n    let eax: usize;\n    asm!(\"mov eax, $0\" : \"=r\"(eax) ::: \"intel\");\n    eax == MULTIBOOT_MAGIC\n}\n\n\n#[cold]\n#[no_mangle]\n#[naked]\npub unsafe extern \"C\" fn _start() {\n    boot_write(b\"0\");\n    asm!(\"cli\");\n\n\n    // 1. Move Multiboot info pointer to edi\n    asm!(\"mov edi, ebx\" :::: \"intel\");\n    boot_write(b\"1\");\n\n    // 2. make sure the system supports SOS\n    // TODO: port this from boot.asm\n    if !is_multiboot_supported() {\n        loop { boot_write(b\"ERROR: multiboot not supported!\"); }\n    }\n    boot_write(b\"2\");\n\n    // 3. if everything is okay, create the page tables and start long mode\n    create_page_tables();\n    set_long_mode();\n\n    // 4. load the 64-bit GDT\n    GdtPointer::from(&GDT).load();\n    boot_write(b\"4\");\n\n    // 6. jump to the 64-bit boot subroutine.\n    asm!(\"ljmpl $$8, $$long_mode_init\");\n\n}\n\n#[cold]\n#[lang = \"panic_fmt\"]\nfn panic_fmt() -> ! {\n    loop {\n        boot_write(b\"panic! panic! panic!\");\n    }\n}"
  },
  {
    "path": "build.rs",
    "content": "use std::env;\n\nfn main() {\n    let profile = env::var(\"PROFILE\").unwrap();\n    if profile != \"test\" {\n        // target triple\n        let target\n            = env::var(\"TARGET\").unwrap();\n        // extract the architecture name from the target triple\n        let arch_name\n            = target.split(\"-\").next()\n                    .expect(\"Couldn't parse target triple!\");\n\n\n        let boot_path = if arch_name == \"x86_64\" {\n            format!(\"boot/target/x86_32-sos-bootstrap-gnu/{}/\", profile)\n        } else {\n            panic!(\"target arch {} not yet supported, sorry!\", arch_name);\n        };\n        println!(\"cargo:rustc-link-search=native={}\", boot_path);\n        println!(\"cargo:rustc-link-lib=static=boot\");\n    }\n\n\n}\n"
  },
  {
    "path": "cpu/Cargo.toml",
    "content": "[package]\nname = \"cpu\"\nversion = \"0.0.1\"\nauthors = [ \"Eliza Weisman <eliza@elizas.website>\" ]\n\n[profile.dev]\nopt-level = 3\ndebug = true\nrpath = false\nlto = false\ndebug-assertions = true\ncodegen-units = 1\npanic = \"abort\"\n\n[profile.release]\nopt-level = 3\ndebug = true\nrpath = false\nlto = false\npanic = \"abort\"\n\n[dependencies]\nutil = { path = \"../util\" }\nbitflags = \"0.7\"\nspin = \"0.4.6\"\n\n[dependencies.vga]\npath = \"../vga\"\nfeatures = [\"kinfo\", \"system_term\"]\n\n[dependencies.memory]\npath = \"../memory\"\n\n[dependencies.log]\nversion = \"0.3.6\"\ndefault-features = false\nfeatures = [\"release_max_level_info\"]\n\n[dependencies.lazy_static]\nversion = \"0.2.11\"\nfeatures = [\"spin_no_std\"]\n"
  },
  {
    "path": "cpu/src/armv7/mod.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza Weisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\n//!  ARM v7 architecture-specific implementation\n//  TODO: NYI\n\npub const ARCH_BITS: u8 = 64;\n"
  },
  {
    "path": "cpu/src/lib.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2016 Eliza eisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\n#![crate_name = \"cpu\"]\n#![crate_type = \"lib\"]\n#![feature(const_fn)]\n#![feature(asm)]\n#![feature(naked_functions)]\n#![feature(slice_patterns)]\n#![feature(linkage)]\n#![feature(stmt_expr_attributes)]\n#![cfg_attr(target_arch = \"x86_64\", feature(abi_x86_interrupt))]\n#![no_std]\n\n//-- non-SOS dependencies ----------------------------------------------------\nextern crate spin;\n#[macro_use] extern crate log;\n#[macro_use] extern crate bitflags;\n\n//-- SOS dependencies --------------------------------------------------------\nextern crate util;\nextern crate memory;\n#[macro_use] extern crate vga;\n\nuse core::marker::PhantomData;\n\n//-- re-exports --------------------------------------------------------------\n// 64-bit x86_64 (long mode)\n#[cfg(target_arch=\"x86_64\")] mod x86_64;\n#[cfg(target_arch=\"x86_64\")] pub use self::x86_64::*;\n\n// 32-bit x86 (protected mode)\n// TODO: NYI\n#[cfg(target_arch = \"x86\")] mod x86;\n#[cfg(target_arch = \"x86\")] pub use self::x86::*;\n\n// ARM v7\n// TODO: NYI\n#[cfg(target_arch = \"armv7\")] mod armv7;\n#[cfg(target_arch = \"armv7\")] pub use self::x86::*;\n\n/// A CPU I/O port.\n///\n/// This is a typed wrapper around an [`UnsafePort`](struct.UnsafePort.html).\n/// Unlike an `UnsafePort`, this\npub struct Port<T> { raw_port: UnsafePort\n                   , typ: PhantomData<T>\n                   }\n\nmacro_rules! make_ports {\n    ( $( $t:ty, $read:ident, $out:ident ),+ ) => {\n        $(\n            impl Port<$t> {\n                #[inline]\n                pub const fn new(number: u16) -> Self {\n                    // TODO: can we check if the port number is valid\n                    unsafe {\n                        Port { raw_port: UnsafePort::new(number)\n                             , typ: PhantomData::<$t>\n                             }\n                    }\n                }\n\n                #[inline]\n                pub fn read(&self) -> $t {\n                    unsafe { self.raw_port.$read() }\n                }\n\n                #[inline]\n                pub fn write(&self, data: $t) {\n                    unsafe { self.raw_port.$out(data) }\n                }\n            }\n        )+\n    }\n}\n\nmake_ports! { u8, in8, out8\n            , u16, in16, out16\n            , u32, in32, out32\n            }\n\n#[cfg(arch=\"x86_64\")]\nmake_ports! { u64, in64, out64 }\n"
  },
  {
    "path": "cpu/src/x86/cpu.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza Weisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\n//! Code for interacting with the `x86` CPU.\n//!\n//! Currently this module contains a quick implementation of CPU port\n//! input and output, and little else.\n\n#[path = \"../x86_all/cpu/mod.rs\"] mod cpu_all;\npub use self::cpu_all::*;\n\n#[path = \"../x86_all/interrupts/mod.rs\"]\npub mod interrupts;\n"
  },
  {
    "path": "cpu/src/x86/mod.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza Weisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\n//! `x86` architecture-specific implementation.\n//!\n//! This module contains code for `x86` 32-bit protected-mode systems.\npub mod cpu;\npub mod memory;\n// pub mod keyboard;\n\npub const ARCH_BITS: u8 = 32;\n"
  },
  {
    "path": "cpu/src/x86_64/context.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza Weisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\n//! `x86_64` execution contexts.\n//!\n//! This is inteded to be general-purpose and composable, so that the same\n//! code can be reused for interrupts and for multithreading.\n\nuse core::mem;\nuse core::fmt;\nuse super::flags::{Flags as RFlags};\nuse super::segment;\n\n/// Registers pushed to the stack when handling an interrupt or context switch.\n#[repr(C, packed)]\n#[derive(Copy, Clone)]\npub struct Registers { pub rsi: u64\n                     , pub rdi: u64\n                     , pub r11: u64\n                     , pub r10: u64\n                     , pub r9:  u64\n                     , pub r8:  u64\n                     , pub rdx: u64\n                     , pub rcx: u64\n                     , pub rax: u64\n                     }\n\n impl Registers {\n     /// Transform this struct into an array of `u64`s\n     /// (if you would ever want to do this)\n     /// TODO: rewrite this to be a `convert::Into` implementation.\n     //         - eliza, 03/09/2017\n     pub unsafe fn to_array(&self) -> [u64; 9] {\n        //  [ self.rsi, self.rdi, self.r11\n        //  , self.r10, self.r9, self.r8\n        //  , self.rdx, self.rcx, self.rax\n        //  ]\n        // using transmute is probably faster and we're already unsafe...\n        mem::transmute(*self)\n     }\n\n     /// Create a new empty set of Registers\n     pub const fn empty() -> Self {\n         Registers { rsi: 0, rdi: 0, r11: 0\n                   , r10: 0, r9:  0, r8:  0\n                   , rdx: 0, rcx: 0, rax: 0\n                   }\n     }\n\n     /// Push the caller-saved registers to the stack\n     /// (such as when handling a context switch or interrupt).\n     ///\n     /// THIS FUNCTION IS NAKED. DO NOT CALL IT NORMALLY.\n     #[naked]\n     #[inline(always)]\n     pub unsafe fn push() {\n         asm!( \"push rax\n                push rcx\n                push rdx\n                push r8\n                push r9\n                push r10\n                push r11\n                push rdi\n                push rsi\"\n             :::: \"intel\"\n                , \"volatile\");\n     }\n\n     /// Push the caller-saved registers off the stack\n     /// (such as when handling a context switch or interrupt).\n     ///\n     /// THIS FUNCTION IS NAKED. DO NOT CALL IT NORMALLY.\n     #[naked]\n     #[inline(always)]\n     pub unsafe fn pop() {\n         asm!( \"pop rsi\n                pop rdi\n                pop r11\n                pop r10\n                pop r9\n                pop r8\n                pop rdx\n                pop rcx\n                pop rax\"\n             :::: \"intel\"\n                , \"volatile\");\n     }\n }\n\nimpl fmt::Debug for Registers {\n     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n         write!( f\n               , \"    RSI: {:#018x} RDI: {:#018x} R11: {:#018x}\\n    \\\n                      R10: {:#018x} R9:  {:#018x} R8:  {:#018x}\\n    \\\n                      RDX: {:#018x} RCX: {:#018x} RAX: {:#018x}\"\n              , self.rsi, self.rdi, self.r11\n              , self.r10, self.r9,  self.r8\n              , self.rdx, self.rcx, self.rax)\n     }\n}\n\n\n\n#[repr(C, packed)]\npub struct InterruptFrame {\n    //  this is the actual value of the interrupt stack frame context,\n    //  not the old one (which is wrong). note that the old one seems to cause\n    //  stack misalignment.\n    //          -- eliza, october 4th, 2016\n    /// Value of the instruction pointer (`$rip`) register\n    pub rip: *const u8\n  , /// Value of the code segment (`$cs`) register\n    pub cs: segment::Selector\n  , __pad_1: u32\n  , __pad_2: u16\n  , /// Value of the CPU flags (`$rflags`) register\n    pub rflags: RFlags\n  , /// Value of the stack pointer (`$rsp`) register\n    //  TODO: should this actually be a pointer?\n    pub rsp: *const u8\n  , /// Value of the stack segment (`$ss`) register\n    pub ss: segment::Selector\n  , __pad_3: u32\n  , __pad_4: u16\n}\n\n#[cfg(test)]\nmod test {\n    #[test]\n    fn test_interrupt_frame_correct_size() {\n        use core::mem::size_of;\n        use super::InterruptFrame;\n\n        assert_eq!(size_of::<InterruptFrame>(), 32);\n    }\n}\n\nimpl fmt::Debug for InterruptFrame {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        write!( f\n              , \"Interrupt Frame: \\\n                \\n   instruction pointer: {:p} \\\n                \\n   code segment:        {} \\\n                \\n   rflags:              {:?} \\\n                \\n   stack pointer:       {:p} \\\n                \\n   stack segment:       {}\"\n             , self.rip\n            //  , self.__pad_1, self.__pad_2\n             , self.cs\n             , self.rflags\n             , self.rsp\n            //  , self.__pad_3, self.__pad_4\n             , self.ss)\n    }\n}\n\n/// Thread execution context\n#[repr(C, packed)]\npub struct Context { /// Value of the stack pointer (`rsp`) register\n                     pub rsp: *mut u8\n                   , /// Value of the caller-saved registers\n                     pub registers: Registers\n                   , /// Value of the instruction pointer (`rip`) register\n                     pub rip: *mut u8\n                 //, pub stack: [u8] // TODO: should be box\n                   }\n\nimpl Context {\n    pub fn empty() -> Self {\n        unsafe {\n            Context { rsp: mem::transmute(0u64)\n                    , registers: Registers::empty()\n                    , rip: mem::transmute(0u64)\n                  //, stack: [0u8; 8]\n                    }\n        }\n    }\n}\n"
  },
  {
    "path": "cpu/src/x86_64/mod.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2016 Eliza Weisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\n//! Code for interacting with the `x86_64` CPU.\n//!\n//! This module contains code for interrupts, paging, context switches,\n//! CPU I/O (from `x86_all`), and reading/writing the x86 control registers.\n//!\n\n#[path = \"../x86_all/mod.rs\"] mod cpu_all;\n\npub mod context;\npub mod task;\npub mod msr;\n\npub use self::context::Registers;\npub use self::cpu_all::*;\n"
  },
  {
    "path": "cpu/src/x86_64/msr.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Hawk Weisman (hi@hawkweisman.me)\n//\n//  Copyright (c) 2015 Hawk Weisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\n//! Code for interacting with the Model-Specific Registers (MSRs).\n\n/// Extended Feature Enable Register (EFER) on IA-32\npub const IA32_EFER: u32 = 0xc0000080;\n\n/// Write `value` to the specified `msr`\n///\n/// # Arguments\n/// + `msr`: which MSR to write to\n/// + `value`: the  bits to write\npub unsafe fn write(msr: u32, value: u64) {\n    let low = value as u32;\n    let high = (value >> 32) as u32;\n    asm!(   \"wrmsr\"\n         :: \"{ecx}\" (msr), \"{eax}\" (low), \"{edx}\" (high)\n         :  \"memory\"\n         : \"volatile\" );\n}\n\n/// Read 64 bits from the specified `msr`\npub unsafe fn read(msr: u32) -> u64 {\n    let low: u32;\n    let high: u32;\n    asm!( \"rdmsr\"\n        : \"={eax}\" (low), \"={edx}\" (high)\n        : \"{ecx}\" (msr)\n        : \"memory\"\n        : \"volatile\" );\n    ((high as u64) << 32) | (low as u64)\n}\n\n\n/// Enable the NXE (No Execute) in the IA-32 EFER register.\n///\n/// This allows us to set the NXE bit on pages.\npub unsafe fn enable_nxe() {\n    let nxe_bit = 1 << 11;\n    let efer = read(IA32_EFER) | nxe_bit;\n    write(IA32_EFER, efer);\n}\n"
  },
  {
    "path": "cpu/src/x86_64/task.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza Weisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\n//! Tasking\nuse ::segment;\nuse memory::VAddr;\n\n/// A 64-bit Task State Descriptor\n#[repr(packed)]\npub struct StateDescriptor { pub upper: segment::Descriptor\n                           , pub lower: u64\n                           }\n\n\n/// A 64-bit Task State Segment\n#[repr(C, packed)]\n#[derive(Debug)]\npub struct StateSegment {\n    _reserved_1: u32\n  , /// 64-bit values of the stack pointers (`%rsp`) for privilege rings 0-2\n    //  TODO: should this be an array or just three u64s?\n    pub rsp: [VAddr; 3]\n  , _reserved_2: u32\n  , /// 64-bit values of the interrupt stack table registers\n    pub ist: [VAddr; 7]\n  , _reserved_3: u64\n  , _reserved_4: u16\n  , /// the base offset of the IO map\n    pub iomap_base_offset: u16\n}\n\nimpl StateSegment {\n\n    /// Returns a new, empty TSS\n    pub const fn new() -> Self {\n        StateSegment { _reserved_1: 0\n                     , rsp: [ VAddr::new(0); 3]\n                     , _reserved_2: 0\n                     , ist: [ VAddr::new(0); 7 ]\n                     , _reserved_3: 0\n                     , _reserved_4: 0\n                     , iomap_base_offset: 0\n                     }\n    }\n}\n"
  },
  {
    "path": "cpu/src/x86_all/control_regs/cr0.rs",
    "content": "use core::fmt;\n\nbitflags! {\n    /// Flag present in `%cr0`.\n    ///\n    /// See [the OS Dev Wiki](http://wiki.osdev.org/CR0#CR0) for more\n    /// information.\n    pub flags Flags: usize {\n        /// Protected Mode Enable\n        ///\n        /// If 1, system is in protected mode. Otherwise, the system is in real\n        /// mode.\n        const PE = 1 << 0\n      , /// Monitor co-processor\n        ///\n        /// Controls interaction of `WAIT`/`FWAIT` instructions with `TS` flag\n        /// in `%cr0`.\n        const MP = 1 << 1\n      , /// FPU Emulation\n        ///\n        /// If set, no x87 floating point unit present, if clear, x87 FPU\n        /// present.\n        const EM = 1 << 2\n      , /// Task Switched\n        ///\n        /// Allows saving x87 task context upon a task switch only after x87\n        /// instruction used.\n        const TS = 1 << 3\n      , /// Extension Type\n        ///\n        /// On a 386 CPU, indicated whether the math coprocessor was an 80287\n        /// or an 80387.\n        const ET = 1 << 4\n      , /// Numeric Error\n        ///\n        /// Enable internal x87 floating point error reporting when set, else\n        /// enables PC style x87 error detection.\n        const NE = 1 << 5\n      , /// Write Protect\n        ///\n        /// When set, the CPU can't write to read-only pages when privilege\n        /// level is 0.\n        const WP = 1 << 16\n      , /// Alignment Mask\n        ///\n        /// Alignment check enabled if `AM` set, `AC` flag (in `%eflags`\n        /// register) set, and privilege level is 3\n        const AM = 1 << 18\n      , /// Not Write-Through\n        ///\n        /// Globally enables/disable write-through caching\n        const NW = 1 << 29\n      , /// Cache Disable\n        ///\n        /// Globally enables/disable the memory cache\n        const CD = 1 << 30\n      , /// Paging\n        ///\n        /// If 1, enable paging and use the `%cr3` register, else disable\n        /// paging.\n        const PG = 1 << 31\n    }\n}\n\ncpu_flag! {\n    doc=\"If set, enable paging; if unset, disable paging.\",\n    PG, is_paging_enabled, enable_paging\n}\ncpu_flag! {\n    doc=\"If set, enable the write protect bit; if unset, disable write \\\n        protect.\",\n    WP, is_write_protected, enable_write_protect\n}\n\n///// Set the write protect bit in `%cr0`.\n//pub fn enable_write_protect() {\n//    let mut flags: Flags = read();\n//    if !flags.contains(WP) {\n//        flags.insert(WP);\n//        unsafe { write(flags) }\n//    }\n//}\n//\n///// Unset the write protect bit in `%cr0`.\n//pub fn disable_write_protect() {\n//    let mut flags: Flags = read();\n//    if flags.contains(WP) {\n//        flags.remove(WP);\n//        unsafe { write(flags) }\n//    }\n//}\n//\n///// Set the paging bit in `%cr0`.\n//pub fn enable_paging() {\n//    let mut flags: Flags = read();\n//    if !flags.contains(WP) {\n//        flags.insert(WP);\n//        unsafe { write(flags) }\n//    }\n//}\n//\n///// Unset the paging bit in `%cr0`.\n//pub fn disable_paging() {\n//    let mut flags: Flags = read();\n//    if flags.contains(PG) {\n//        flags.remove(PG);\n//        unsafe { write(flags) }\n//    }\n//}\n\n/// Read the current value from `%cr0`.\n///\n/// # Safety\n/// + Reading from control registers while not in kernel mode will cause\n///   a general protection fault.\npub unsafe fn read() -> Flags {\n    let result: usize;\n    asm!(   \"mov $0, cr0\"\n        :   \"=r\"(result)\n        ::: \"intel\" );\n    Flags { bits: result }\n}\n\n/// Write a value to `%cr0`.\n///\n/// # Safety\n/// + Control registers should generally not be modified during normal\n///   operation.\npub unsafe fn write(flags: Flags) {\n    asm!(  \"mov cr0, $0\"\n        :: \"r\"(flags.bits)\n        :: \"intel\");\n}\n\nimpl fmt::LowerHex for Flags {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        write!(f, \"{:#08x}\", self.bits)\n    }\n}\n"
  },
  {
    "path": "cpu/src/x86_all/control_regs/cr4.rs",
    "content": "use core::fmt;\n\n/// Read the current value from `$cr4`.\n///\n/// # Safety\n/// + Reading from control registers while not in kernel mode will cause\n///   a general protection fault.\npub unsafe fn read() -> Flags {\n    let result: usize;\n    asm!(   \"mov $0, cr4\"\n        :   \"=r\"(result)\n        ::: \"intel\" );\n    Flags { bits: result }\n}\n\n/// Write a value to `$cr4`.\n///\n/// # Safety\n/// + Control registers should generally not be modified during normal\n///   operation.\npub unsafe fn write(flags: Flags) {\n    asm!(  \"mov cr4, $0\"\n        :: \"r\"(flags.bits)\n        :: \"intel\");\n}\n\n\nbitflags! {\n    /// Bitflags present in `$cr4`\n    ///\n    /// Documentation taken from\n    /// [wikipedia](https://en.wikipedia.org/wiki/Control_register#CR4).\n    pub flags Flags: usize {\n        /// Virtual 8086 Mode Extensions\n        ///\n        /// If set, enables support for the virtual interrupt flag (VIF) in\n        /// virtual-8086 mode.\n        const VME = 1 << 0\n      , /// Protected-mode Virtual Interrupts\n        ///\n        /// If set, enables support for the virtual interrupt flag (VIF) in\n        /// protected mode.\n        const PVI = 1 << 1\n      , /// Time Stamp Disable\n        ///\n        /// If 1, the `RTDSC` instruction can only be executed in Ring 0\n        const TSD = 1 << 2\n      , /// Debugging Extensions\n        ///\n        /// If set, enables debug register based breaks on I/O space access\n        const DE = 1 << 3\n      , /// Page Size Extension\n        ///\n        /// If unset, page size is 4 KiB, else page size is increased to 4 MiB\n        /// (if PAE is enabled or the processor is in Long Mode this bit is\n        /// ignored).\n        const PSE = 1 << 4\n      , /// Physical Address Extension\n        ///\n        /// If set, changes page table layout to translate 32-bit virtual\n        /// addresses into extended 36-bit physical addresses.\n        const PAE = 1 << 5\n      , /// Machine Check Exception\n        ///\n        /// If set, Machine Check exceptions are enabled.\n        const MCE = 1 << 6\n      , /// Page Global Enabled\n        ///\n        /// If set, address translations (PDE or PTE records) may be shared\n        /// between address spaces.\n        const PGE = 1 << 7\n      , /// Performance-Monitoring Counter enable\n        ///\n        /// If set, the `RDPMC` instruction can be executed at any privilege\n        /// level, else `RDPMC` can only be used in ring 0.\n        const PCE = 1 << 8\n      , /// Operating system support for `FXSAVE` and `FXRSTOR` instructions\n        ///\n        /// If set, enables SSE instructions and fast FPU save and restore.\n        const OSFXSR = 1 << 9\n      , /// Operating System Support for Unmasked SIMD Floating-Point Exceptions\n        ///\n        /// If set, enables unmasked SSE exceptions.\n        const OSXMMEXCPT = 1 << 10\n      , /// Virtual Machine Extensions Enable\n        const VMXE = 1 << 13\n      , /// Safer Mode Extensions Enable\n        const SMXE = 1 << 14\n      , /// Enables the instructions RDFSBASE, RDGSBASE, WRFSBASE, and WRGSBASE.\n        const FSGSBASE = 1 << 16\n      , /// PCID Enable\n        ///\n        /// If set, enables process-context identifiers (PCIDs).\n        const PCIDE = 1 << 17\n      , /// `XSAVE` and Processor Extended States Enable\n        const OSXSAVE = 1 << 18\n      , /// Supervisor Mode Execution Protection Enable\n        ///\n        /// If set, execution of code in a higher ring generates a fault\n        const SMEP = 1 << 20\n      , /// Supervisor Mode Access Protection Enable\n        ///\n        /// If set, access of data in a higher ring generates a faul\n        const SMAP = 1 << 21\n      , /// Protection Key Enable\n        const PKE = 1 << 22\n    }\n}\n\nimpl fmt::LowerHex for Flags {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        write!(f, \"{:#08x}\", self.bits)\n    }\n}\n\ncpu_flag! {\n    doc=\"If disabled, the `RTDSC` instruction can only be executed in Ring 0.\",\n    TSD, is_timestamp_disabled, disable_timestamp\n}\n"
  },
  {
    "path": "cpu/src/x86_all/control_regs/mod.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza Weisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\n//! `x86` and `x86_64` control registers\n#![warn(missing_docs)]\nuse core::fmt;\n\n/// `%cr0` contains flags that modify basic processor operation.\npub mod cr0;\n\n/// `%cr4` contains flags that control protected mode execution.\npub mod cr4;\n\n/// A struct bundling together a snapshot of the control registers state.\n#[derive(Copy,Clone,Debug)]\npub struct CrState { /// `%cr0` contains flags that control the CPU's operations\n                     pub cr0: cr0::Flags\n                   , /// `%cr2` contains the page fault linear address\n                     pub cr2: usize\n                   , /// `%cr3` contains the page table root pointer\n                     ///\n                     /// TODO: can this be rewritten as a pointer?\n                     pub cr3: usize\n                   , /// `%cr4` contains flags that control operations in\n                     ///  protected mode\n                     pub cr4: cr4::Flags\n                   }\n\nimpl fmt::Display for CrState {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n         write!( f, \"CR0: {:#08x} CR2: {:#08x} CR3: {:#08x} CR4: {:#08x}\"\n                , self.cr0, self.cr2, self.cr3, self.cr4)\n    }\n}\n\n/// Dump the current contents of the control registers to a `CrState`.\npub fn dump() -> CrState {\n    let cr0_: usize; let cr2_: usize;\n    let cr3_: usize; let cr4_: usize;\n    unsafe {\n        asm!(  \"mov $0, cr0\n                mov $1, cr2\n                mov $2, cr3\n                mov $3, cr4\"\n            :   \"=r\"(cr0_)\n              , \"=r\"(cr2_)\n              , \"=r\"(cr3_)\n              , \"=r\"(cr4_)\n            ::: \"intel\"\n              , \"volatile\");\n    }\n    CrState { cr0: cr0::Flags::from_bits_truncate(cr0_)\n            , cr2: cr2_, cr3: cr3_\n            , cr4: cr4::Flags::from_bits_truncate(cr4_)\n            }\n\n}\n\n/// `$cr2` contains the page fault linear address\npub mod cr2 {\n\n    /// Read the current value from `$cr2`.\n    ///\n    /// # Safety\n    /// + Reading from control registers while not in kernel mode will cause\n    ///   a general protection fault.\n    pub unsafe fn read() -> usize {\n        let result: usize;\n        asm!(   \"mov $0, cr2\"\n            :   \"=r\"(result)\n            ::: \"intel\" );\n        result\n    }\n\n    /// Write a value to `$cr2`.\n    ///\n    /// # Safety\n    /// + Control registers should generally not be modified during normal\n    ///   operation.\n    pub unsafe fn write(value: usize) {\n        asm!(  \"mov cr2, $0\"\n            :: \"r\"(value)\n            :: \"intel\");\n    }\n}\n\n/// `%cr3` contains the page table root pointer\npub mod cr3 {\n    use memory::{PAddr, PhysicalPage};\n\n    // #[cfg(target_arch = \"x86_64\")]\n    // use paging::table::{Table, PML4Level};\n\n    /// Read the current value from `$cr3`.\n    ///\n    /// # Safety\n    /// + Reading from control registers while not in kernel mode will cause\n    ///   a general protection fault.\n    #[cfg(target_arch = \"x86_64\")]\n    pub unsafe fn read() -> PAddr {\n        let result: u64;\n        asm!(   \"mov $0, cr3\"\n            :   \"=r\"(result)\n            ::: \"intel\" );\n        PAddr::from(result)\n    }\n\n    /// Read the current value from `$cr3`.\n    ///\n    /// # Safety\n    /// + Reading from control registers while not in kernel mode will cause\n    ///   a general protection fault.\n    #[cfg(target_arch = \"x86\")]\n    pub unsafe fn read() -> PAddr {\n        let result: u32;\n        asm!(   \"mov $0, cr3\"\n            :   \"=r\"(result)\n            ::: \"intel\" );\n        PAddr::from(result)\n    }\n\n    /// Write a value to `$cr3`.\n    ///\n    /// # Safety\n    /// + Control registers should generally not be modified during normal\n    ///   operation.\n    #[cfg(target_arch = \"x86_64\")]\n    pub unsafe fn write(addr: PAddr) {\n        let value: u64 = addr.into();\n        asm!(  \"mov cr3, $0\"\n            :: \"r\"(value)\n            :  \"memory\"\n            :  \"intel\");\n    }\n\n    /// Write a value to `$cr3`.\n    ///\n    /// # Safety\n    /// + Control registers should generally not be modified during normal\n    ///   operation.\n    #[cfg(target_arch = \"x86\")]\n    pub unsafe fn write(addr: PAddr) {\n        let value: u32 = addr.into();\n        asm!(  \"mov cr3, $0\"\n            :: \"r\"(value)\n            :: \"intel\");\n    }\n\n    /// Returns the current Page Directory base frame.\n    ///\n    /// # Safety\n    /// + Reading from control registers while not in kernel mode will cause\n    ///   a general protection fault.\n    pub unsafe fn current_pagetable_frame() -> PhysicalPage {\n        PhysicalPage::containing_addr(read())\n    }\n\n    /// Returns the current Page Directory base frame.\n    ///\n    /// # Safety\n    /// + Reading from control registers while not in kernel mode will cause\n    ///   a general protection fault.\n    #[inline]\n    pub unsafe fn set_pagetable_frame(frame: PhysicalPage) {\n        write(frame.base_addr())\n    }\n}\n"
  },
  {
    "path": "cpu/src/x86_all/dtable.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza Weisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//! `x86` and `x86_64` descriptor tables (IDT, GDT, or LDT)\n//!\n//! For more information, refer to the _Intel® 64 and IA-32 Architectures\n//! Software Developer’s Manual_, Vol. 3A, section 3.2, \"Using Segments\", and\n//! section 6.10, \"Interrupt Descriptor Table (IDT)\".\n\n#![deny(missing_docs)]\n// use memory::PAddr;\nuse core::mem::size_of;\n\n/// A pointer to a descriptor table.\n/// This is a format suitable\n#[repr(C, packed)]\npub struct Pointer<T: DTable> { /// the length of the descriptor table\n                     pub limit: u16\n                   , /// pointer to the region in memory\n                     /// containing the descriptor table.\n                     pub base: *const T\n                   }\nunsafe impl<T: DTable> Sync for Pointer<T> { }\n/// A descriptor table (IDT or GDT).\n///\n/// The IA32 architecture uses two descriptor table structures, the GDT\n/// (Global Descriptor Table), which is used for configuring segmentation,\n/// and the IDT (Interrupt Descriptor Table), which tells the CPU where\n/// interrupt service routines are located.\n///\n/// As SOS relies on paging rather than segmentation for memory protection on\n/// both 32-bit and 64-bit systems, we use the GDT only minimally. However, the\n/// CPU still requires a correctly configured GDT to run in protected mode, even\n/// if it is not actually used.\n///\n/// This trait specifies base functionality common to both types of descriptor\n/// table.\npub trait DTable: Sized {\n    /// The type of an entry in this descriptor table.\n    ///\n    /// For an IDT, these are\n    /// interrupt [`Gate`](../interrupts/idt/gate/struct.Gate.html)s,\n    /// while for a GDT or LDT, they are segment\n    /// [`Descriptor`](../segment/struct.Descriptor.html)s.\n    //  TODO: can there be a trait for DTable entries?\n    //      - eliza, 10/06/2016\n    type Entry: Sized;\n\n    /// Get the IDT pointer struct to pass to `lidt` or `lgdt`\n    ///\n    /// This expects that the object implementing `DTable` not contain\n    /// additional data before or after the actual `DTable`, if you wish\n    /// to attach information to a descriptor table besides the array of\n    /// entries that it consists of, it will be necessary to encose the\n    /// descriptor table in another `struct` or `enum` type.\n    //  TODO: can we have an associated `Entry` type + a function to get the\n    //        number of entries in the DTable, instead? that way, we could\n    //        calculate the limit using that information, allowing Rust code\n    //        to place more variables after the array in the DTable structure.\n    //\n    //        If we wanted to be really clever, we could probably also have a\n    //        method to get a pointer to a first entry (or enforce that the\n    //        DTable supports indexing?) and then we could get a pointer only\n    //        to the array segment of the DTable, while still allowing variables\n    //        to be placed before/after the array.\n    //\n    //        I'm not sure if we actually want to support this – is there really\n    //        a use-case for it? I suppose it would also make our size calc.\n    //        more correct in case Rust ever puts additional data around a\n    //        DTable rray, but I imagine it will probably never do that...\n    //              – eliza, 06/03/2016\n    //\n    #[inline]\n    fn get_ptr(&self) -> Pointer<Self> {\n        Pointer {\n            limit: (size_of::<Self::Entry>() * self.entry_count()) as u16\n          , base: self as *const _\n        }\n    }\n\n    /// Returns the number of Entries in the `DTable`.\n    ///\n    /// This is used for calculating the limit.\n    fn entry_count(&self) -> usize;\n\n    /// Load the descriptor table with the appropriate load instruction\n    fn load(&'static self);\n}\n"
  },
  {
    "path": "cpu/src/x86_all/flags.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza Weisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\n//! Flags present in the `%eflags`/`%rflags` register on x86 CPUs.\nuse super::PrivilegeLevel;\n\nbitflags! {\n    /// Contents of the `%eflags`/`%rflags` register.\n    ///\n    /// Note that on early x86 systems, this is a 16-bit register (`%flags`),\n    /// but we only support the 32-bit `%eflags` and 64-bit `%rflags`, since\n    /// SOS is a protected mode/long mode OS only.\n    pub flags Flags: usize {\n        /// Carry flag\n        const CF = 1 << 0\n      , /// Parity flag\n        const PF = 1 << 2\n      , /// Adjust flag\n        const AF = 1 << 4\n      , /// Zero flag\n        const ZF = 1 << 6\n      , /// Sign flag\n        const SF = 1 << 7\n      , /// Trap flag (single step)\n        ///\n        /// If 1, IT'S A TRAP!\n        const TF = 1 << 8\n      , /// Interrupt enable flag\n        const IF = 1 << 9\n      , /// Direction flag\n        const DF = 1 << 10\n      , /// Overflow flag\n        const OF = 1 << 11\n\n      , const IOPL_RING_0 = 0 << 12\n      , const IOPL_RING_1 = 1 << 12\n      , const IOPL_RING_2 = 2 << 12\n      , const IOPL_RING_3 = 3 << 12\n      , /// I/0 Privilege Level\n        ///\n        /// This flag is always one on the 8086 and 186.\n        const IOPL = IOPL_RING_0.bits | IOPL_RING_1.bits |\n                     IOPL_RING_2.bits | IOPL_RING_3.bits\n\n      , /// Nested task flag\n        ///\n        /// Always 1 on 8086 and 186s.\n        const NT = 1 << 14\n\n      , /// Should always be 1\n        const RESERVED = 1 << 15\n\n      , /// Resume flag\n        ///\n        /// Present on 386 and later.\n        const RF = 1 << 16\n      , /// Virtual 8086 Mode flag\n        ///\n        /// Of course, this is only present on 386 and later.\n        const VM = 1 << 17\n      , /// Alignment Check\n        ///\n        /// Present on 486SX and later.\n        const AC = 1 << 18\n      , /// Virtual Interrupt flag\n        ///\n        /// Present on Pentium and later.\n        const VIF = 1 << 19\n      , /// Virtual Interrupt Pending\n        ///\n        /// Present on Pentium and later.\n        const VIP = 1 << 20\n      , /// Able to use `CPUID` instruction.\n        ///\n        /// Present on Pentium and later.\n        const ID = 1 << 21\n    }\n}\n\nimpl Flags {\n    pub fn iopl(&self) -> PrivilegeLevel {\n        use core::mem::transmute;\n        let bits = (*self & IOPL).bits >> 12;\n        unsafe { transmute(bits as u16) }\n    }\n}\n\n/// Read the current value from `$eflags`/`%rflags`.\npub fn read() -> Flags {\n    let result: usize;\n    unsafe {\n        asm!(   \"pushf\n                 pop $0\"\n            :   \"=r\"(result)\n            ::: \"intel\" );\n    }\n    Flags { bits: result }\n}\n"
  },
  {
    "path": "cpu/src/x86_all/interrupts/idt/gate32.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza Weisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\n//! 32-bit IDT gate implementation\nuse ::segment;\nuse super::{GateFlags};\nuse super::super::{InterruptHandler, ErrorCodeHandler};\nuse core::mem::transmute;\n\nextern {\n    /// Offset of the 32-bit GDT main code segment.\n    /// Exported by `boot.asm`\n    #[link_name=\"gdt32_offset\"]\n    static GDT_OFFSET: u16;\n}\n\n/// An IDT entry is called a gate.\n///\n/// Based on [code](http://wiki.osdev.org/Interrupt_Descriptor_Table#Structure)\n/// from the OS Dev Wiki.\n#[repr(C, packed)]\n#[derive(Copy,Clone, Default)]\npub struct Gate { /// bits 0 - 15 of the offset\n                 pub offset_lower: u16\n               , /// code segment selector (GDT or LDT)\n                 pub selector: segment::Selector\n               , /// always zero\n                 _zero: u8\n               , /// indicates the gate's type and attributes.\n                 /// the second half indicates the type:\n                 /// + `0b1100`: Call gate\n                 /// + `0b1110`: Interrupt gate\n                 /// + `0b1111`: Trap Gate\n                 pub flags: GateFlags\n               , /// bits 16 - 31 of the offset\n                 pub offset_upper: u16\n               }\n\nimpl GateFlags {\n\n   /// Returns a new trap gate\n   pub const fn new_trap() -> Self {\n       GateFlags { bits: super::TRAP_GATE_16.bits | super::PRESENT.bits }\n   }\n\n   /// Returns a new interrupt gate\n   pub const fn new_interrupt() -> Self {\n       GateFlags { bits: super::INT_GATE_16.bits | super::PRESENT.bits }\n   }\n\n}\n\nimpl Gate {\n\n   /// Creates a new IDT gate marked as `absent`.\n   ///\n   /// This is basically just for filling the new IDT table\n   /// with valid (but useless) gates upon init.\n   ///\n   /// Actually triggering an absent interrupt will send a General Protection\n   /// fault (13).\n    pub const fn absent() -> Self {\n       Gate { offset_lower: 0\n            , selector: 0\n            , _zero: 0\n            , flags: GateFlags { bits: 0 }\n            , offset_upper: 0\n            }\n    }\n\n}\n\nimpl convert::From<ErrorCodeHandler> for Gate {\n\n    /// Creates a new IDT gate pointing at the given handler function.\n    ///\n    /// The `handler` function must have been created with valid interrupt\n    /// calling conventions.\n    fn from(handler: ErrorCodeHandler) -> Self {\n        unsafe {\n            let (low, mid): (u16, u16) = mem::transmute(handler);\n\n            Gate { offset_lower: low\n                 , selector: segment::Selector::from_raw(GDT_OFFSET)\n                 , _zero: 0\n                 , type_attr: GateFlags::new_interrupt()\n                 , offset_upper: high\n                 , _reserved: 0\n                 }\n        }\n    }\n}\n\nimpl convert::From<InterruptHandler> for Gate {\n\n    /// Creates a new IDT gate pointing at the given handler function.\n    ///\n    /// The `handler` function must have been created with valid interrupt\n    /// calling conventions.\n    fn from(handler: ErrorCodeHandler) -> Self {\n        unsafe {\n            let (low, mid): (u16, u16) = mem::transmute(handler);\n\n            Gate { offset_lower: low\n                 , selector: segment::Selector::from_raw(GDT_OFFSET)\n                 , _zero: 0\n                 , type_attr: GateFlags::new_interrupt()\n                 , offset_upper: high\n                 , _reserved: 0\n                 }\n        }\n    }\n}\n"
  },
  {
    "path": "cpu/src/x86_all/interrupts/idt/gate64.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza Weisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\n//! 64-bit IDT gate implementation\nuse ::segment;\nuse super::{GateFlags};\nuse super::super::{InterruptHandler, ErrorCodeHandler};\n\nuse core::{convert, mem, ops};\nuse core::marker::PhantomData;\n\nimpl GateFlags {\n\n    /// Returns a new trap gate\n    pub const fn new_trap() -> Self {\n        GateFlags { bits: super::TRAP_GATE_32.bits | super::PRESENT.bits }\n    }\n\n    /// Returns a new call gate\n    pub const fn new_task() -> Self {\n        GateFlags { bits: super::TASK_GATE_32.bits | super::PRESENT.bits }\n    }\n\n    /// Returns a new interrupt gate\n    pub const fn new_interrupt() -> Self {\n        GateFlags { bits: super::INT_GATE_32.bits | super::PRESENT.bits }\n    }\n\n}\n\n\n/// An IDT entry is called a gate.\n///\n/// Based on [code](http://wiki.osdev.org/Interrupt_Descriptor_Table#Structure)\n/// from the OS Dev Wiki.\n///\n/// Refer also to \"6.14.1 64-Bit Mode IDT\"  and \"Table 3-2. System-Segment and\n/// Gate-Descriptor Types\" in the _Intel® 64 and IA-32 Architectures\n/// Software Developer’s Manual_\n#[repr(C, packed)]\n#[derive(Copy, Clone)]\npub struct Gate<H = InterruptHandler>\n    { /// bits 0 - 15 of the offset\n      pub offset_lower: u16\n    , /// code segment selector (GDT or LDT)\n      pub selector: segment::Selector\n    , /// always zero\n      _zero: u8\n    , /// indicates the gate's type and attributes.\n      /// the second half indicates the type:\n      ///   + `0b1100`: Call gate\n      ///   + `0b1110`: Interrupt gate\n      ///   + `0b1111`: Trap Gate\n      pub flags: GateFlags\n    , /// bits 16 - 31 of the offset\n      pub offset_mid: u16\n    , /// bits 32 - 63 of the offset\n      pub offset_upper: u32\n    , /// always zero (according to the spec, this is \"reserved\")\n      _reserved: u32\n    , _handler_type: PhantomData<H>\n    }\n\nimpl<H> Gate<H> {\n\n    /// Creates a new IDT gate marked as `absent`.\n    ///\n    /// This is basically just for filling the new IDT table\n    /// with valid (but useless) gates upon init.\n    ///\n    /// Actually triggering an absent interrupt will send a General Protection\n    /// fault (13).\n    pub const fn absent() -> Self {\n       Gate { offset_lower: 0\n            , selector: segment::Selector::from_raw(0)\n            , _zero: 0\n            , flags: GateFlags { bits:  0b1000_1110 }\n            , offset_mid: 0\n            , offset_upper: 0\n            , _reserved: 0\n            , _handler_type: PhantomData\n            }\n    }\n\n    /// Set the handler function corresponding to this gate.\n    #[inline]\n    pub fn set_handler<F>(&mut self, handler: F) -> &mut Self\n    where Self: convert::From<F> {\n        *self = Self::from(handler);\n        self\n    }\n\n    /// Sets the TRAP GATE flag to true\n    #[inline]\n    pub fn set_trap(&mut self) -> &mut Self {\n        self.flags.insert(super::TRAP_GATE_32);\n        self\n    }\n\n}\n\n\nimpl<H> Default for Gate<H> {\n    fn default() -> Self {\n        Gate { offset_lower: 0\n             , selector: segment::Selector::from_raw(0)\n             , _zero: 0\n             , flags: GateFlags { bits: 0b1000_1110 }\n             , offset_mid: 0\n             , offset_upper: 0\n             , _reserved: 0\n             , _handler_type: PhantomData\n             }\n    }\n}\n\nimpl<H> ops::Deref for Gate<H> {\n    type Target = GateFlags;\n\n    #[inline] fn deref(&self) -> &Self::Target { &self.flags }\n}\n\nimpl<H> ops::DerefMut for Gate<H> {\n    #[inline] fn deref_mut(&mut self) -> &mut Self::Target { &mut self.flags }\n}\n\nimpl convert::From<InterruptHandler> for Gate<InterruptHandler> {\n\n    /// Creates a new IDT gate pointing at the given handler function.\n    ///\n    /// The `handler` function must have been created with valid interrupt\n    /// calling conventions.\n    fn from(handler: InterruptHandler) -> Self {\n        unsafe { // trust me on this, `mem::transmute()` is glorious black magic\n                let (low, mid, high): (u16, u16, u32) = mem::transmute(handler);\n\n            Gate { offset_lower: low\n                 , offset_mid: mid\n                 , offset_upper: high\n                 , selector: segment::Selector::from_cs()\n                 , flags: GateFlags::new_interrupt()\n                 , ..Default::default()\n                 }\n        }\n    }\n}\n\nimpl convert::From<ErrorCodeHandler> for Gate<ErrorCodeHandler> {\n\n    /// Creates a new IDT gate pointing at the given handler function.\n    ///\n    /// The `handler` function must have been created with valid interrupt\n    /// calling conventions.\n    fn from(handler: ErrorCodeHandler) -> Self {\n        unsafe { // trust me on this, `mem::transmute()` is glorious black magic\n                let (low, mid, high): (u16, u16, u32) = mem::transmute(handler);\n\n            Gate { offset_lower: low\n                 , offset_mid: mid\n                 , offset_upper: high\n                 , selector: segment::Selector::from_cs()\n                 , flags: GateFlags::new_interrupt()\n                 , ..Default::default()\n                 }\n        }\n    }\n}\n\nimpl convert::From<*const u8> for Gate {\n\n    /// Creates a new IDT gate pointing at the given handler function.\n    ///\n    /// The `handler` function must have been created with valid interrupt\n    /// calling conventions.\n    ///\n    /// This should probably not be used, if it can possibly be avoided.\n    //  TODO: it would be really nice if we didn't need this any more.\n    //        after the Revolution, once handlers are created in Rust-land with\n    //        naked functions...\n    fn from(handler: *const u8) -> Self {\n        unsafe {\n            let (low, mid, high): (u16, u16, u32) = mem::transmute(handler);\n\n            Gate { offset_lower: low\n                 , offset_mid: mid\n                 , offset_upper: high\n                 , selector: segment::Selector::from_cs()\n                 , flags: GateFlags::new_interrupt()\n                 , ..Default::default()\n                 }\n        }\n    }\n}\n"
  },
  {
    "path": "cpu/src/x86_all/interrupts/idt/mod.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza Weisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\n//! Common functionality for the `x86` and `x86_64` Interrupt Descriptor Table.\n#![warn(missing_docs)]\nuse core::{mem, convert, ops};\n\nuse ::dtable::DTable;\nuse ::PrivilegeLevel;\n\n/// Number of entries in the system's Interrupt Descriptor Table.\npub const ENTRIES: usize = 256;\n\n#[cfg(test)] mod tests;\n\n//==------------------------------------------------------------------------==\n// IDT Gates\n#[cfg(target_arch = \"x86\")]    #[path = \"gate32.rs\"] pub mod gate;\n#[cfg(target_arch = \"x86_64\")] #[path = \"gate64.rs\"] pub mod gate;\npub use self::gate::*;\n\nbitflags! {\n    /// Bitflags field in an IDT gate.\n    ///\n    /// The structure of the flags field is as follows:\n    ///\n    /// ```ignore\n    ///   7                           0\n    /// +---+---+---+---+---+---+---+---+\n    /// | P |  DPL  | S |    GateType   |\n    /// +---+---+---+---+---+---+---+---+\n    /// ```\n    ///\n    /// Fields have the following meanings:\n    ///\n    ///  + `P`: One bit, indicating if the ISR is present. Set to 0 for unused\n    ///         interrupts.\n    ///  + `DPL`: Two bits, indicating the escriptor's priveliege level as an\n    ///           integer, with zero being Ring 0.\n    ///  + `S`: One bit, set if the descriptor refers to an interrupt in the\n    ///         storage segment.\n    ///  + `GateType`: Four bits, indicating the type of the interrupt with the\n    ///               following values (architecture-dependent):\n    ///    - `0101`: 80386 32-bit task gate\n    ///    - `0110`: 80286 16-bit interrupt gate\n    ///    - `0111`: 80286 16-bit trap gate\n    ///    - `1110`: 80386 32-bit interrupt gate\n    ///    - `1111`: 80386 32-bit trap gate\n    ///\n    /// For more information, refer to the _Intel® 64 and IA-32 Architectures\n    /// Software Developer’s Manual_, Vol. 3A, section 6.11, \"IDT Descriptors\";\n    /// and to the OS Dev Wiki\n    /// [article](http://wiki.osdev.org/Interrupts_Descriptor_Table)\n    /// \"Interrupts Descriptor Table\".\n    pub flags GateFlags: u8 {\n        /// Set to 0 for unused interrupts.\n        ///\n        /// Indicates whether or not this gate is present.\n        /// An interrupt on a non-present gate will trigger a\n        /// General Protection Fault.\n        const PRESENT       = 0b1000_0000\n\n      , /// Bit indicating that the descriptor priveliege level is Ring 0\n        const DPL_RING_0    = 0b0000_0000\n      , /// Bit indicating that the descriptor priveliege level is Ring 1\n        const DPL_RING_1    = 0b0010_0000\n      , /// Bit indicating that the descriptor priveliege level is Ring 2\n        const DPL_RING_2    = 0b0100_0000\n      , /// Bit indicating that the descriptor priveliege level is Ring 3\n        const DPL_RING_3    = 0b0110_0000\n      , /// Descriptor priveliege level bitfield.\n        const DPL           = DPL_RING_0.bits | DPL_RING_1.bits |\n                              DPL_RING_2.bits | DPL_RING_3.bits\n\n      , /// Storage segment flag.\n        ///\n        /// Set to 0 for interrupt gates.\n        const SEGMENT       = 0b0001_0000\n      , /// Set if this `Gate` points to a 32-bit ISR.\n        const LONG_MODE     = 0b0000_1000\n\n      , /// Set if this is an interrupt gate.\n        const INT_GATE_16   = 0b0000_0110\n      , /// Set if this is an interrupt gate and points to a 32-bit ISR.\n        const INT_GATE_32   = INT_GATE_16.bits | LONG_MODE.bits\n      , /// Set if this is a trap gate.\n        const TRAP_GATE_16  = 0b0000_0111\n      , /// Set if this is a trap gate that points to a 32-bit ISR\n        const TRAP_GATE_32  = TRAP_GATE_16.bits | LONG_MODE.bits\n      , /// Set if this is a 32-bit task gate.\n        const TASK_GATE_32  = 0b0000_0101 | LONG_MODE.bits\n    }\n}\n\nimpl GateFlags {\n    /// Returns true if this `Gate` is a trap gate\n    #[inline] pub fn is_trap(&self) -> bool {\n        self.contains(TRAP_GATE_16)\n    }\n\n    /// Returns true if this `Gate` points to a present ISR\n    #[inline] pub fn is_present(&self) -> bool {\n        self.contains(PRESENT)\n    }\n\n    /// Sets the present bit for this gate\n    #[inline] pub fn set_present(&mut self, present: bool) -> &mut Self {\n        if present { self.insert(PRESENT) }\n        else { self.remove(PRESENT) }\n        self\n    }\n\n    /// Checks the gate's privilege\n    #[inline] pub fn get_dpl(&self) -> PrivilegeLevel {\n        unsafe { mem::transmute((*self & DPL).bits as u16 >> 5) }\n    }\n\n    /// Sets the privilege level of the gate\n    pub fn set_dpl(&mut self, dpl: PrivilegeLevel) -> &mut Self {\n        self.insert(GateFlags::from_bits_truncate((dpl as u8) << 5));\n        self\n    }\n\n}\n\n\nimpl Default for GateFlags {\n    fn default() -> Self { GateFlags { bits: 0 } }\n}\n\n//==------------------------------------------------------------------------==\nuse super::ErrorCodeHandler;\n//  IDT implementation\n/// An Interrupt Descriptor Table\n///\n/// The IDT is either 64-bit or 32-bit.\n#[repr(C)]\npub struct Idt {\n    pub divide_by_zero: Gate\n  , /// debug interrupt handler - reserved\n    pub debug: Gate\n  , pub nmi: Gate\n  , pub breakpoint: Gate\n  , pub overflow: Gate\n  , pub bound_exceeded: Gate\n  , pub undefined_opcode: Gate\n  , pub device_not_available: Gate\n  , pub double_fault: Gate<ErrorCodeHandler>\n  , _coprocessor_segment_overrun: Gate<ErrorCodeHandler>\n  , pub invalid_tss: Gate<ErrorCodeHandler>\n  , pub segment_not_present: Gate<ErrorCodeHandler>\n  , pub stack_segment_fault: Gate<ErrorCodeHandler>\n  , pub general_protection_fault: Gate<ErrorCodeHandler>\n  , pub page_fault: Gate<ErrorCodeHandler>\n  , _reserved: Gate\n  , pub floating_point_error: Gate\n  , pub alignment_check: Gate<ErrorCodeHandler>\n  , pub machine_check: Gate\n  , pub simd_fp_exception: Gate\n  , pub virtualization: Gate\n  , _reserved_2: [Gate; 9]\n  , pub security_exception: Gate<ErrorCodeHandler>\n  , _reserved_3: Gate\n  , /// user-defined interrupts\n    pub interrupts: [Gate; ENTRIES - super::NUM_EXCEPTIONS]\n}\n\nimpl Default for Idt {\n    #[inline]\n    fn default() -> Self {\n        Idt {\n            interrupts: [Default::default(); ENTRIES - super::NUM_EXCEPTIONS]\n            , ..Default::default()\n        }\n    }\n}\n\nimpl ops::Index<usize> for Idt {\n    type Output = Gate;\n\n    #[inline]\n    fn index(&self, index: usize) -> &Gate {\n        unsafe {\n            &mem::transmute::<&Self, &[Gate; ENTRIES]>(self)[index]\n        }\n    }\n}\n\nimpl ops::IndexMut<usize> for Idt {\n\n    #[inline]\n    fn index_mut(&mut self, index: usize) -> &mut Self::Output {\n        unsafe {\n            &mut mem::transmute::<&mut Self, &mut [Gate; ENTRIES]>(self)[index]\n        }\n    }\n}\n\nimpl Idt {\n\n    /// Construct a new IDT with all interrupt gates set to [`absent`].\n    ///\n    /// [`absent`]: struct.Gate.absent.html\n    pub const fn new() -> Self {\n        Idt { divide_by_zero: Gate::absent()\n            , debug: Gate::absent()\n            , nmi: Gate::absent()\n            , breakpoint: Gate::absent()\n            , overflow: Gate::absent()\n            , bound_exceeded: Gate::absent()\n            , undefined_opcode: Gate::absent()\n            , device_not_available: Gate::absent()\n            , double_fault: Gate::absent()\n            , _coprocessor_segment_overrun: Gate::absent()\n            , invalid_tss: Gate::absent()\n            , segment_not_present: Gate::absent()\n            , stack_segment_fault: Gate::absent()\n            , general_protection_fault: Gate::absent()\n            , page_fault: Gate::absent()\n            , _reserved: Gate::absent()\n            , floating_point_error: Gate::absent()\n            , alignment_check: Gate::absent()\n            , machine_check: Gate::absent()\n            , simd_fp_exception: Gate::absent()\n            , virtualization: Gate::absent()\n            , _reserved_2: [Gate::absent(); 9]\n            , security_exception: Gate::absent()\n            , _reserved_3: Gate::absent()\n            , interrupts: [Gate::absent(); ENTRIES - super::NUM_EXCEPTIONS]\n            }\n    }\n\n    /// Enable interrupts\n    pub unsafe fn enable_interrupts() { asm!(\"sti\") }\n    /// Disable interrupts\n    pub unsafe fn disable_interrupts() { asm!(\"cli\") }\n\n    /// Add a new interrupt gate pointing to the given handler\n    #[inline]\n    pub fn add_handler<Handler>( &mut self\n                               , idx: usize\n                               , handler: Handler)\n                               -> &mut Self\n    where Gate: convert::From<Handler> {\n        self.add_gate(idx, Gate::from(handler))\n    }\n\n    /// Add a [`Gate`](struct.Gate.html) to the IDT.\n    #[inline]\n    pub fn add_gate(&mut self, idx: usize, gate: Gate) -> &mut Self {\n        self[idx] = gate;\n        self\n    }\n\n}\n\nimpl DTable for Idt {\n    type Entry = Gate;\n\n    #[inline] fn entry_count(&self) -> usize { ENTRIES }\n\n    #[inline] fn load(&'static self) {\n        unsafe {\n            asm!(  \"lidt ($0)\"\n                :: \"r\"(&self.get_ptr())\n                :  \"memory\" );\n        }\n        kinfoln!(dots: \" . . \", target: \"Loading IDT\", \"[ OKAY ]\");\n    }\n}\n"
  },
  {
    "path": "cpu/src/x86_all/interrupts/idt/tests.rs",
    "content": "#[test] fn test_task_gate_32() { assert_eq!(super::TASK_GATE_32.bits, 5)}\n#[test] fn test_int_gate_32() { assert_eq!(super::INT_GATE_32.bits, 14)}\n\n#[test] fn test_trap_gate_32() { assert_eq!(super::TRAP_GATE_32.bits, 16)}\n"
  },
  {
    "path": "cpu/src/x86_all/interrupts/mod.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza Weisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\n//! Intterupt handling on x86 machines.\n//!\n//! This module provides support for interrupt handling on both `x86` and\n//! `x86_64` as a black box. Code that depends on this can use the same API\n//! regardless of system word size.\n#![warn(missing_docs)]\npub mod idt;\npub mod pics;\n\nuse vga::{CONSOLE, Color};\n\nuse core::fmt;\nuse core::fmt::Write;\n\nuse context::InterruptFrame;\n\n/// Number of interrupt vectors corresponding to CPU exceptions.\n///\n/// These are the first 32 vectors in the IDT.\npub const NUM_EXCEPTIONS: usize = 32;\n\n/// An ISR that handles a regular interrupt\npub type InterruptHandler = extern \"x86-interrupt\" fn (&InterruptFrame);\n/// An ISR that handles an error with an error code\npub type ErrorCodeHandler = extern \"x86-interrupt\" fn (&InterruptFrame, usize);\n\n/// A description of a CPU exception\n#[derive(Debug)]\npub struct ExceptionInfo { /// The name of the exception\n                           pub name: &'static str\n                         , /// The mnemomic code for the exception\n                           pub mnemonic: &'static str\n                         , /// The type of IRQ for this exception\n                           /// - fault\n                           /// - trap\n                           /// - interrupt\n                           pub irq_type: &'static str\n                         , /// The source triggering the exception.\n                           ///\n                           /// Typically this refers to what opcode(s) can\n                           /// cause this exception.\n                           pub source: &'static str\n                         }\n\nbitflags! {\n   flags PageFaultErrorCode: u32 {\n       /// If 1, the error was caused by a page that was present.\n       /// Otherwise, the page was non-present.\n       const PRESENT = 1 << 0\n     , /// If 1, the error was caused by a read. If 0, the cause was a write.\n       const READ_WRITE = 1 << 1\n     , /// If 1, the error was caused during user-mode execution.\n       /// If 0, the processor was in kernel mode.\n       const USER_MODE = 1 << 2\n     , /// If 1, the fault was caused by reserved bits set to 1 during a fetch.\n       const RESERVED = 1 << 3\n     , /// If 1, the fault was caused during an instruction fetch.\n       const INST_FETCH = 1 << 4\n     , /// If 1, there was a protection key violation.\n       const PROTECTION = 1 << 5\n   }\n}\n\nimpl fmt::Display for PageFaultErrorCode {\n   fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n       write!( f, \"Caused by {}{}{} during a {}{} executing in {} mode.\"\n             , if self.contains(PRESENT) { \"a present page\" }\n               else { \"a non-present page\" }\n             , if self.contains(PROTECTION) { \" protection-key violation\" }\n               else { \"\" }\n             , if self.contains(RESERVED) { \" reserved bits set to one \"}\n               else { \"\" }\n             , if self.contains(READ_WRITE) { \"read\" } else { \"write\" }\n             , if self.contains(INST_FETCH) { \" in an instruction fetch\"}\n               else { \"\" }\n             , if self.contains(USER_MODE) { \"user\" } else { \"kernel\" }            )\n   }\n}\n\n/// Handler for the system timer interrupt\npub extern \"x86-interrupt\" fn timer(_frame: &InterruptFrame) {\n    // do nothing, just signal the pics to end the IRQ\n    // println!(\"timer!\");\n    unsafe { pics::end_pic_interrupt(0x20); }\n}\n\n\n\n/// Handles page fault exceptions\n#[no_mangle] #[inline(never)]\npub extern \"x86-interrupt\" fn page_fault( frame: &InterruptFrame, error_code: usize) {\n   let _ = write!( CONSOLE.lock()\n                      .set_colors(Color::White, Color::Blue)\n                   //   .clear()\n             , \"IT'S NOT MY FAULT: Page Fault at {:p} \\\n                \\nError code: {:#x}\\n\\n{}\\n{:?}\"\n             , (*frame).rip\n             , error_code\n             , PageFaultErrorCode::from_bits_truncate(error_code as u32)\n             , *frame\n             );\n   // TODO: stack dumps please\n\n   loop { }\n}\n\n/// Test interrupt handler for ensuring that the IDT is configured correctly.\n#[no_mangle] #[inline(never)]\npub extern \"x86-interrupt\" fn test(_frame: &InterruptFrame) {\n   // assert_eq!(state.int_id, 0x80);\n   kinfoln!(dots: \" . . \", target: \"Testing interrupt handling:\", \"[ OKAY ]\");\n   // send the PICs the end interrupt signal\n   unsafe {\n       pics::end_pic_interrupt(0xff);\n   }\n}\n"
  },
  {
    "path": "cpu/src/x86_all/interrupts/pics.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza Weisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\n//! Support for the 8259 Programmable Interrupt Controller.\n//!\n//! The 8259 PIC controls all of our IO IRQs. The PIC recieves IRQ requests\n//! and feeds them to the CPU in order. An x86 system typically has two PICs,\n//! PIC1 and PIC2, each of which provides 8 IRQs. Two PICs provide us with 15\n//! unique IRQs, because one interrupt on the leader PIC is linked to interrupts\n//! on the follower PIC.\n//!\n//! Mistakes were made, and Intel boneheadedly decided that it was a good idea\n//! to map the vector offset of PIC1 to 8, so that it maps to interrupts\n//! 8 ... 15 in the IDT. This conflicts with some of the interrupt numbers\n//! used by CPU exceptions. Therefore, we must remap the PIC vectors so that\n//! PIC1 starts at 32 and PIC2 at 40.\n\nuse Port;\nuse spin::Mutex;\n\nuse core::mem::transmute;\n\n/// Starting offset for PIC1\nconst OFFSET: u8 = 0x20;\n/// Command port for the follower PIC (PIC2)\nconst FOLLOWER_CMD_PORT: u16 = 0xA0;\n/// Command port for the leader PIC (PIC1)\nconst LEADER_CMD_PORT: u16 = OFFSET as u16;\n\n/// Commands to send to the PIC\n#[repr(u8)]\n#[derive(Eq, PartialEq, Ord, PartialOrd, Copy, Clone)]\nenum Command { /// Command to set the PIC to 8086 mode\n               Mode8086 = 0x01\n             , /// Command to initialize a PIC\n               Init     = 0x11\n             , /// Command that ends an interrupt request\n               EndIRQ   = 0x20\n             , /// Command to read the Interrupt Request Register\n               ReadIRR  = 0x0a\n             , /// Command to read the Interrupt Service Register\n               ReadISR  = 0x0b\n             }\n\n/// List of IRQs on the x86.\n///\n/// See [here](https://en.wikibooks.org/wiki/X86_Assembly/Programmable_Interrupt_Controller) for more info.\n#[repr(u8)]\n#[derive(Eq, PartialEq, Ord, PartialOrd, Copy, Clone)]\npub enum IRQ { /// System timer IRQ\n               Timer        = OFFSET\n             , /// PS/2 keyboard controller\n               PS2Keyboard  = 1 + OFFSET\n             , /// PIC2 cascade IRQ\n               Cascade      = 2 + OFFSET\n             , /// COM2 serial port\n               COM2         = 3 + OFFSET\n             , /// COM1 serial port\n               COM1         = 4 + OFFSET\n             , /// Line printer 2\n               LPT2         = 5 + OFFSET\n             , /// Floppy disc controller\n               Floppy       = 6 + OFFSET\n             , /// Line printer 1\n               LPT1         = 7 + OFFSET\n             , /// CMOS clock\n               RTCTimer     = 8 + OFFSET\n             , /// PS/2 mouse controller\n               PS2Mouse     = 12 + OFFSET\n             , /// Floating-point Coprocessor\n               FPU          = 13 + OFFSET\n             , /// ATA channel 1\n               PrimaryATA   = 14 + OFFSET\n             , /// ATA channel 2\n               SecondaryATA = 15 + OFFSET\n             }\n\n\n/// A 8259 Programmable Interrupt Controller.\npub struct PIC {\n    /// The base offset to which interrupts on this PIC are mapped\n    offset: u8\n  , /// The port on the CPU that sends commands to this PIC.\n    command_port: Port<u8>\n  , /// The port that sends and recieves data from the PIC\n    data_port: Port<u8>\n}\n\nimpl PIC {\n\n    /// Construct a new leader PIC\n    pub const fn leader() -> PIC {\n        PIC { offset: OFFSET\n            , command_port: Port::<u8>::new(LEADER_CMD_PORT)\n            , data_port: Port::<u8>::new(LEADER_CMD_PORT + 1)\n            }\n    }\n\n    /// Construct a new follower PIC\n    pub const fn follower() -> PIC {\n        PIC { offset: OFFSET + 8\n            , command_port: Port::<u8>::new(FOLLOWER_CMD_PORT)\n            , data_port: Port::<u8>::new(FOLLOWER_CMD_PORT + 1)\n            }\n    }\n\n    /// Returns true if this PIC is the leader PIC\n    #[inline]\n    pub fn is_leader(&self) -> bool {\n        self.offset == OFFSET\n    }\n\n    /// Send a command to the PIC\n    #[inline]\n    fn send_command(&self, command: Command) {\n        self.command_port\n            .write(command as u8)\n    }\n\n    /// Send a byte of data to the PIC\n    #[inline]\n    pub fn send_data(&self, data: u8) {\n        self.data_port\n            .write(data)\n    }\n\n    /// Send the \"initialize\" command to this PIC\n    #[inline]\n    pub fn initialize(&self) {\n         self.send_command(Command::Init)\n    }\n\n    /// Read the contents of the ISR (Interrupt Service Register) from this PIC\n    #[inline]\n    pub fn read_isr(&self) -> u8 {\n            self.send_command(Command::ReadISR);\n            self.data_port.read()\n    }\n\n/// Read the contents of the IRR (Interrupt Request Register) from this PIC\n    #[inline]\n    pub fn read_irr(&self) -> u8 {\n        self.send_command(Command::ReadIRR);\n        self.data_port.read()\n    }\n\n}\n\n/// Trait for something which is capable of handling a PIC IRQ\ntrait IRQHandler {\n    /// Returns whether or not this handler handles the given IRQ\n    fn handles(&self, irq: IRQ) -> bool;\n    /// End an interrupt request\n    fn end_interrupt(&self, irq: IRQ);\n}\n\nimpl IRQHandler for PIC {\n\n    fn handles(&self, irq: IRQ) -> bool {\n        self.offset <= (irq as u8) && (irq as u8) < self.offset + 8\n    }\n\n    fn end_interrupt(&self, _: IRQ) {\n        let _ = self.send_command(Command::EndIRQ);\n    }\n}\n\n/// A pair of PICs in cascade mode.\n///\n/// This is the standard configuration on all modern x86 systems.\nstruct BothPICs (PIC, PIC);\n\nimpl BothPICs {\n\n    /// Constructs the system's pair of PICs\n    const fn new() -> Self {\n        BothPICs (PIC::leader(), PIC::follower())\n    }\n\n    /// Initialize the system's PICs.\n    pub unsafe fn initialize(&mut self) {\n        let wait_port = Port::<u8>::new(0x80);\n        let wait = || { wait_port.write(0); };\n        // helper macro to avoid writing repetitive code\n        macro_rules! send {\n            (pic0 => $data:expr) => {\n                self.0.send_data($data);\n                wait();\n            };\n            (pic1 => $data:expr) => {\n                self.1.send_data($data);\n                wait();\n            };\n        }\n\n        // Read the default interrupt masks from PIC1 and PIC2\n        let (saved_mask1, saved_mask2)\n            = (self.0.data_port.read(), self.1.data_port.read());\n\n        // Send both PICs the 'initialize' command.\n        self.0.initialize(); wait();\n        self.1.initialize(); wait();\n\n        // Each PIC then expects us to send it the following:\n        // 1. the PIC's new vector offset\n        send!(pic0 => self.0.offset);\n        send!(pic1 => self.1.offset);\n        // 2. number to configure PIC cascading\n        send!(pic0 => 0x04);\n        send!(pic1 => 0x02);\n        // 3. command for 8086 mode\n        send!(pic0 => Command::Mode8086 as u8);\n        send!(pic1 => Command::Mode8086 as u8);\n        // 4. finally, the mask we saved earlier\n        send!(pic0 => saved_mask1);\n        send!(pic1 => saved_mask2);\n    }\n}\n\nimpl IRQHandler for BothPICs {\n\n    fn handles(&self, irq: IRQ) -> bool {\n        self.0.handles(irq) ||\n        self.1.handles(irq)\n    }\n\n    fn end_interrupt(&self, irq: IRQ) {\n        if self.1.handles(irq) {\n            self.1.end_interrupt(irq);\n        }\n        self.0.end_interrupt(irq);\n    }\n\n}\n\n/// Global PIC instance and mutex\nstatic PICS: Mutex<BothPICs>\n    = Mutex::new(BothPICs::new());\n\n/// Initialize the system's Programmable Interrupt Controller\n///\n/// # Safety\n///  - This should only ever be called by the kernel boot process.\n///    Initializing the PICs once they have already been inicialized\n///    will probably cause Bad Things to take place.\npub unsafe fn initialize() {\n    PICS.lock()\n        .initialize();\n    kinfoln!(dots: \" . . \", target: \"Initializing PICs\", \"[ OKAY ]\");\n\n}\n\n/// If an interrupt is being handled by the PICs, end that interrupt.\n///\n/// This is called by the interrupt handler at the end of all interrupts.\n/// If the interrupt is not a PIC interrupt, it silently does nothing.\n///\n/// # Safety\n///  - This should only be called by interrupt handler functions.\npub unsafe fn end_pic_interrupt(interrupt_id: u8) {\n    let pics = PICS.lock();\n    let irq: IRQ = transmute(interrupt_id);\n\n    if pics.handles(irq) {\n        pics.end_interrupt(irq)\n    }\n}\n"
  },
  {
    "path": "cpu/src/x86_all/mod.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza Weisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\n//! Common functionality for `x86` and `x86_64` CPUs\n//!\n//! Note that while we support both the `x86` and `x86_64` platforms,\n//! we only support 32-bit `x86` machines. SOS is a protected mode or\n//! long mode OS, and will not run on early x86 machines such as 286s.\nuse util::{io, Void};\n\nmacro_rules! cpu_flag {\n    ($doc:meta, $flag:ident, $get:ident, $set:ident) => {\n        #[$doc]\n        pub unsafe fn $get() -> bool {\n            read().contains($flag)\n        }\n        #[$doc]\n        pub unsafe fn $set(set: bool) {\n            let mut flags: Flags = read();\n            if set {\n                flags.insert($flag);\n            } else {\n                flags.remove($flag);\n            }\n            write(flags)\n        }\n    };\n    ($doc:meta, $flag:ident, $get:ident) => {\n        #[$doc]\n        pub unsafe fn $get() -> bool {\n            read().contains($flag)\n        }\n    }\n}\n\npub mod control_regs;\npub mod segment;\npub mod dtable;\npub mod flags;\npub mod timer;\npub mod interrupts;\n\n/// Represents an x86 privilege level.\n#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Ord, Eq)]\n#[repr(u16)]\npub enum PrivilegeLevel { /// Ring 0 is the most privileged ring\n                          KernelMode = 0\n                        , Ring1 = 1\n                        , Ring2 = 2\n                        , /// Ring 3 is the least privileged ring\n                          UserMode = 3\n\n}\n\nimpl PrivilegeLevel {\n    /// Returns the current I/O Privilege Level from `%eflags`/`%rflags`.\n    #[inline] pub fn current_iopl() -> Self { flags::read().iopl() }\n}\n\npub struct UnsafePort(u16);\n\nimpl UnsafePort {\n\n    pub const unsafe fn new(number: u16) -> UnsafePort { UnsafePort(number) }\n\n    /// Read a byte (8 bits) from this port\n    pub unsafe fn in8(&self) -> u8 {\n        let result: u8;\n        asm!(  \"in al, dx\"\n            :  \"={al}\"(result)\n            :  \"{dx}\"(self.0)\n            :: \"intel\"\n             , \"volatile\" );\n        result\n    }\n    /// Read a word (16 bits) from this port\n    pub unsafe fn in16(&self) -> u16 {\n        let result: u16;\n        asm!(  \"in ax, dx\"\n            :  \"={ax}\"(result)\n            :  \"{dx}\"(self.0)\n            :: \"intel\"\n             , \"volatile\" );\n        result\n    }\n\n    /// Read a long word (32 bits) from this port\n    pub unsafe fn in32(&self) -> u32 {\n        let result: u32;\n        asm!(  \"in eax, dx\"\n            :  \"={eax}\"(result)\n            :  \"{dx}\"(self.0)\n            :: \"intel\"\n             , \"volatile\" );\n        result\n    }\n\n    pub unsafe fn out8(&self, value: u8) {\n         asm!(  \"out dx, al\"\n             :: \"{dx}\"(self.0)\n              , \"{al}\"(value)\n             :: \"intel\"\n              , \"volatile\" );\n    }\n\n    pub unsafe fn out16(&self, value: u16) {\n         asm!(  \"out dx, ax\"\n             :: \"{dx}\"(self.0)\n              , \"{ax}\"(value)\n             :: \"intel\"\n              , \"volatile\" );\n    }\n\n    pub unsafe fn out32(&self, value: u32) {\n         asm!(  \"out dx, eax\"\n             :: \"{dx}\"(self.0)\n              , \"{eax}\"(value)\n             :: \"intel\"\n              , \"volatile\" );\n    }\n}\n\n\nimpl io::Read for UnsafePort {\n    type Error = Void;\n\n    /// Reads a single byte into the given buffer\n    fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {\n        unsafe {\n            Ok(match &mut *buf {\n                // if the length of the buffer is 0, then obviously\n                // no bytes were read\n                &mut []                  => 0\n                // otherwise, read one byte into the head of the buffer\n              , &mut [ref mut head, _..] => { *head = self.in8(); 1 }\n            })\n        }\n    }\n\n    /// Reads a new byte into each position in the buffer.\n    fn read_all(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {\n        let mut read_bytes = 0;\n        for idx in buf.iter_mut() {\n            // for each index in the buffer, read another byte from the port\n            unsafe { *idx = self.in8(); }\n            // and increment the number of bytes read (this should be faster\n            // than calling `buf.len()` later; as we only need 1 loop)\n            read_bytes += 1;\n        }\n        Ok(read_bytes)\n    }\n\n}\n\nimpl io::Write for UnsafePort {\n    type Error = Void;\n\n    fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {\n        let mut written_bytes = 0;\n        for byte in buf {\n            // write each byte in the buffer to the port\n            unsafe { self.out8(*byte); }\n            // and increment the number of bytes written (this should be faster\n            // than calling `buf.len()` later; as we only need 1 loop)\n            written_bytes += 1;\n        }\n        Ok(written_bytes)\n    }\n}\n"
  },
  {
    "path": "cpu/src/x86_all/segment.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2016 Eliza Weisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\n//! Code for using the `x86` and `x86_64` segmentation hardware.\n//!\n//! For more information, refer to the _Intel® 64 and IA-32 Architectures\n//! Software Developer’s Manual_, Vol. 3A, section 3.2, \"Using Segments\".\n//! Some of the documentation present in this module was taken from the Intel\n//! manual.\n//!\n\n// because some extern types have bitflags members, which cannot\n// be marked repr(C) but should compile down to an unsigned integer\n#![allow(improper_ctypes)]\n#![deny(missing_docs)]\n\nuse core::{fmt, mem};\nuse super::{PrivilegeLevel, dtable};\n/// The number of entries in the GDT\n#[cfg(target_arch = \"x86_64\")]\npub const GDT_SIZE: usize = 2;\n\n/// Structure representing a Global Descriptor Table\n#[cfg(target_arch = \"x86_64\")]\n#[repr(C, packed)]\npub struct Gdt { _null: Descriptor\n               , /// The code segment descriptor\n                 pub code: Descriptor\n            //    , /// The data segment descriptor\n            //      pub data: Descriptor\n               }\n\n/// The number of entries in the GDT\n#[cfg(target_arch = \"x86\")]\npub const GDT_SIZE: usize = 512;\n\n#[cfg(target_arch = \"x86\")]\npub type Gdt = [Descriptor; GDT_SIZE];\n\nimpl dtable::DTable for Gdt {\n    type Entry = Descriptor;\n\n    /// Returns the number of Entries in the `DTable`.\n    ///\n    /// This is used for calculating the limit.\n    #[inline(always)] fn entry_count(&self) -> usize { GDT_SIZE }\n\n    /// Load the GDT table with the `lgdt` instruction.\n    #[inline] fn load(&self) {\n        unsafe {\n            asm!(  \"lgdt ($0)\"\n            :: \"r\"(&self.get_ptr())\n            :  \"memory\" );\n        }\n    }\n}\n\n\nextern {\n\n    /// A Global Descriptor Table (GDT)\n    ///\n    /// This is used for configuring segmentation. Since we use paging rather than\n    /// segmentation for memory protection, we never actually _use_ the GDT, but\n    /// x86 requires that it be properly configured nonetheless. So, here it is.\n    #[cfg(target_arch = \"x86_64\")]\n    #[link_section = \".gdt64\"]\n    pub static GDT: Gdt;\n}\n\nbitflags! {\n    /// A segment selector is a 16-bit identifier for a segment.\n    ///\n    /// It does not point directly to the segment, but instead points to the\n    /// segment descriptor that defines the segment.\n    ///\n    /// A segment selector contains the following items:\n    ///\n    /// + *Requested Privilege Level (RPL)*: bits 0 and 1.\n    ///    Specifies the privelege level of the selector.\n    /// + *Table Indicator*: bit 2. Specifies which descriptor table to use.\n    /// + *Index*: bits 3 through 15. Selects one of 8192 descriptors in the\n    ///    GDT or LDT. The processor multiplies the index value by 8 (the number\n    ///    of bytes in a segment descriptor) and adds the result to the base\n    ///    address of the GDT or LDT (from the `%gdtr` or `%ldtr` register,\n    ///    respectively).\n    #[repr(C)]\n    pub flags Selector: u16 { /// Set if the RPL is in Ring 0\n                              const RPL_RING_0 = 0b00\n                            , /// Set if the RPL is in Ring 1\n                              const RPL_RING_1 = 0b01\n                            , /// Set if the RPL is in Ring 2\n                              const RPL_RING_2 = 0b10\n                            , /// Set if the RPL is in Ring 3\n                              const RPL_RING_3 = 0b11\n\n                            , /// Requested Privelege Level (RPL) bits\n                              const RPL = RPL_RING_0.bits\n                                        | RPL_RING_1.bits\n                                        | RPL_RING_2.bits\n                                        | RPL_RING_3.bits\n\n                            , /// If the Table Indicator (TI) is 0, use the GDT\n                              const TI_GDT = 0 << 3\n\n                            , /// If the TI is 1, use the LDT\n                              const TI_LDT = 1 << 3\n                            }\n}\n\nimpl Selector {\n    /// Create a new `Selector`\n    ///\n    /// # Arguments\n    ///   - `index`: the index in the GDT or LDT\n    pub const fn new(index: u16) -> Self {\n        Selector { bits: index << 3 }\n    }\n\n    /// Create a new `Selector` from raw bits\n    pub const fn from_raw(bits: u16) -> Self {\n        Selector { bits: bits }\n    }\n\n    /// Returns the current value of the code segment register.\n    pub fn from_cs() -> Self {\n        let cs: u16;\n        unsafe {\n            asm!( \"mov $0, cs\"\n                : \"=r\"(cs)\n                ::: \"intel\" )\n        };\n        Selector::from_bits_truncate(cs)\n    }\n\n    /// Extracts the index from a segment selector\n    #[inline] pub fn index(&self) -> u16 {\n        self.bits >> 3\n    }\n\n    /// Sets this segment selector to be a GDT segment.\n    ///\n    /// If the segment is already a GDT segment, this will quietly do nothing.\n    #[inline] pub fn set_global(&mut self) -> &mut Self {\n        self.remove(TI_LDT);\n        self\n    }\n\n    /// Sets this segment selector to be an LDT segment.\n    ///\n    /// If the segment is already an LDT segment, this will quietly do nothing.\n    #[inline] pub fn set_local(&mut self) -> &mut Self {\n        self.insert(TI_GDT);\n        self\n    }\n\n    /// Sets the Requested Priveliege Level (RPL)\n    ///\n    /// The RPL must be in the range between 0 and 3.\n    #[inline] pub fn set_rpl(&mut self, rpl: PrivilegeLevel) -> &mut Self {\n        self.bits &= rpl as u16;\n        self\n    }\n\n    /// Checks the segment's privelige.\n    #[inline] pub fn get_rpl(&self) -> PrivilegeLevel {\n        unsafe { mem::transmute(*self & RPL) }\n    }\n\n\n    /// Load this selector into the stack segment register (`ss`).\n    pub unsafe fn load_ss(&self) {\n        asm!(  \"mov ss, $0\"\n            :: \"r\"(self.bits)\n            :  \"memory\"\n            :  \"intel\");\n    }\n\n    /// Load this selector into the data segment register (`ds`).\n    pub unsafe fn load_ds(&self) {\n        asm!(  \"mov ds, $0\"\n            :: \"r\"(self.bits)\n            :  \"memory\"\n            :  \"intel\");\n    }\n\n    /// Load this selector into the `es` segment register.\n    pub unsafe fn load_es(&self) {\n        asm!(  \"mov es, $0\"\n            :: \"r\"(self.bits)\n            :  \"memory\"\n            :  \"intel\");\n    }\n\n    /// Load this selector into the `fs` segment register.\n    pub unsafe fn load_fs(&self) {\n        asm!(  \"mov fs, $0\"\n            :: \"r\"(self.bits)\n            :  \"memory\"\n            :  \"intel\");\n    }\n\n    /// Load this selector into the `gs` segment register.\n    pub unsafe fn load_gs(&self) {\n        asm!(  \"mov gs, $0\"\n            :: \"r\"(self.bits)\n            :  \"memory\"\n            :  \"intel\");\n    }\n\n\n    /// Load this selector into the code segment register.\n    ///\n    /// N.B. that as we cannot `mov` directly to `cs`, we have to do this\n    /// differently. We push the selector and return value onto the stack,\n    /// and use `lret` to reload `cs`.\n    #[cfg(target_arch = \"x86_64\")]\n    pub unsafe fn load_cs(&self) {\n        asm!(  \"push $0\n                lea rax, [rip + 1]\n                push rax\n                iret\n                1:\"\n            :: \"r\"(self.bits as u64)\n            :  \"rax\", \"memory\"\n            :  \"intel\");\n    }\n\n}\n\n\nimpl Default for Selector {\n    #[inline] fn default() -> Self { Selector::from_cs() }\n}\n\nimpl fmt::Display for Selector {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        // TODO: this could be much less ugly.\n        let ring = if self.contains(RPL_RING_3) { \"3\" }\n                   else if self.contains(RPL_RING_2) { \"2\" }\n                   else if self.contains(RPL_RING_1) { \"1\" }\n                   else if self.contains(RPL_RING_0) { \"0\" }\n                   else { unreachable!() };\n        let table = if self.contains(TI_GDT) { \"GDT\" }\n                    else { \"LDT\" };\n        write!(f, \"{}[{}], Ring {}\", table, self.index(), ring)\n    }\n}\n\n/// A segment descriptor is an entry in an IDT or GDT.\n///\n/// A segment descriptor is a data structure in a GDT or LDT that provides the\n/// processor with the size and location of a segment, as well as access control\n/// and status information. Segment descriptors are typically created by\n/// compilers, linkers, loaders, or the operating system or executive, but not\n/// application programs.\n///\n#[repr(C, packed)]\npub struct Descriptor { /// The last 8 bits of the base address\n                        pub base_high: u8\n                      , /// The next 16 bits are bitflags\n                        pub flags: Flags\n                      , /// The middle 8 bits of the base address\n                        pub base_mid: u8\n                      , /// The first 16 bits of the base address\n                        pub base_low: u16\n                      , /// the segment limit\n                        pub limit: u16\n                      }\n\nimpl Descriptor {\n\n    /// Constructs a new null `Descriptor`\n    pub const fn null() -> Self {\n        Descriptor { base_high: 0\n                   , flags: Flags::null()\n                   , base_mid: 0\n                   , base_low: 0\n                   , limit: 0\n                   }\n    }\n\n    /// Constructs a new `Descriptor` from a `limit` and a `base` address\n    pub fn new(base: u32, limit: u32) -> Self {\n        let (hi, mid, lo): (u8, u8, u16) = unsafe { mem::transmute(base) };\n        let (limit_lo, limit_hi): (u16, u16) = unsafe { mem::transmute(limit) };\n        // I hope this is right...\n        let flags = (limit_hi & 0b1111) << 8;\n\n        Descriptor { base_high: hi\n                   , flags: Flags::from_bits_truncate(flags)\n                   , base_mid: mid\n                   , base_low: lo\n                   , limit: limit_lo\n                   }\n    }\n\n    /// Extract the limit part from the flags and limit fields.\n    #[inline]\n    pub fn get_limit(&self) -> u32 {\n        // TODO: i hope this is right...\n        self.flags.get_limit_part() & self.limit as u32\n    }\n\n}\n\nimpl Default for Descriptor {\n    #[inline] fn default() -> Self { Descriptor::null() }\n}\n\nbitflags! {\n    /// Segment descriptor bitflags field.\n    ///\n    /// Some of the bitflags vary based on the type of segment. Currently\n    /// the API for this is a bit of a mess.\n    pub flags Flags: u16 {\n        /// 1 if this is a code or data segment that has been accessed\n        const CODE_DATA_ACC = 1 << 0\n      , /// Four bits that indcate the type of the segment\n        const SEGMENT_TYPE  = 0b0000_0000_0000_1111\n      , /// 1 if this is a data/code segment, 0 if this is a system segment\n        const DESCR_TYPE    = 1 << 4\n      , /// Two bits indicating the descriptor priveliege level\n        const DPL           = 0b0000_0000_0110_0000\n      , /// 1 if this segment is present.\n        const PRESENT       = 1 << 7\n      , /// bits 16...19 of the limit\n        const LIMIT         = 0b0000_1111_0000_0000\n      , /// 1 if this segment is available for use by system software\n        const AVAILABLE     = 1 << 12\n      , /// 0 if this is a 16- or 32-bit segment, 1 if it is a 64-bit segment\n        const LENGTH        = 1 << 13\n      , /// 0 if this is a 16-bit segment, 1 if it is a 32-bit segment\n        const DEFAULT_SIZE  = 1 << 14\n      , /// 0 if the limit of this segment is given in bytes, 1 if it is given\n        /// in 4092-byte pages\n        const GRANULARITY   = 1 << 15\n      , /// If this is a code or data segment and the accessed bit is set,\n        /// it has been accessed.\n        const ACCESSED      = DESCR_TYPE.bits & CODE_DATA_ACC.bits\n    }\n}\n\nimpl Flags {\n\n    /// Returns a new set of `Flag`s with all bits set to 0.\n    pub const fn null() -> Self {\n        Flags { bits: 0 }\n    }\n\n    /// Returns a new set of `Flag`s from a raw `u16`\n    pub const fn from_raw(bits: u16) -> Self {\n        Flags { bits: bits }\n    }\n\n    /// Get the Descriptor Privilege Level (DPL) from the flags\n    #[inline] pub fn get_dpl(&self) -> PrivilegeLevel {\n        unsafe { mem::transmute((*self & DPL).bits >> 5) }\n    }\n\n    /// Returns true if this segment is a system segment.\n    ///\n    /// Returns false if it is a code or data segment.\n    #[inline] pub fn is_system(&self) -> bool {\n        !self.contains(DESCR_TYPE)\n    }\n\n    /// Returns false if this segment is present\n    #[inline] pub fn is_present(&self) -> bool {\n        !self.contains(PRESENT)\n    }\n\n    /// Returns false if this segment is available to system software\n    #[inline] pub fn is_available(&self) -> bool {\n        self.contains(AVAILABLE)\n    }\n\n    /// Returns true if this is a code or data segment that has been accessed.\n    ///\n    /// Returns false if it has not been accessed OR if it is a system segment.\n    #[inline] pub fn is_accessed(&self) -> bool {\n        self.contains(ACCESSED)\n    }\n\n    /// Returns the system type indicator, if this is a system segment.\n    ///\n    /// # Returns\n    /// + `Some(SysType)` if this is a system segment\n    /// + `None` if this is a code or data segment\n    pub fn get_system_type(&self) -> Option<SysType> {\n        if self.is_system() {\n            Some(unsafe { mem::transmute((*self & SEGMENT_TYPE).bits) })\n        } else {\n            None\n        }\n    }\n\n    /// Returns the code type indicator.\n    ///\n    /// # Returns\n    /// + `Some(CodeType)` if this is not a system segment\n    /// + `None` if this is a system segment\n    pub fn get_code_type(&self) -> Option<CodeFlags> {\n        if self.is_system() {\n            None\n        } else {\n            Some(CodeFlags::from_bits_truncate(self.bits))\n        }\n    }\n\n    /// Returns the data type indicator.\n    ///\n    /// # Returns\n    /// + `Some(DataType)` if this is not a system segment\n    /// + `None` if this is a system segment\n    pub fn get_data_type(&self) -> Option<DataFlags> {\n        if self.is_system() {\n            None\n        } else {\n            Some(DataFlags::from_bits_truncate(self.bits))\n        }\n    }\n\n    #[inline]\n    fn get_limit_part(&self) -> u32 {\n        ((*self & LIMIT).bits as u32) << 8\n    }\n\n}\n\n/// Possible ways to interpret the type bits of a segment selector.\n#[derive(Copy, Clone, Eq, PartialEq, Debug)]\npub enum Type { /// The type bits interpreted as a system segment\n                System(SysType)\n              , /// The type bits interpreted as a code segment\n                Code(CodeFlags)\n              , /// The type bits interpreted as a data segment\n                Data(DataFlags)\n              }\n\n/// Possible types of for a system segment.\n#[derive(Copy, Clone, Eq, PartialEq, Debug)]\n#[repr(u16)]\npub enum SysType { /// System segment used for storing a local descriptor table.\n                   Ldt           = 0b0010\n                 , /// An available translation stack segment.\n                   TssAvailable  = 0b1001\n                 , /// A busy translation stack segment\n                   TssBusy       = 0b1011\n                 , /// A call gate system segment\n                   CallGate      = 0b1100\n                 , /// An interrupt gate system segment\n                   InterruptGate = 0b1110\n                 , /// A trap gate system segment\n                   TrapGate      = 0b1111\n                 }\n\nbitflags! {\n    /// The type-specific section of a data segment's flags\n    pub flags DataFlags: u16 {\n        /// 0 if this segment hasn't been accessed, 1 if it has\n        const DATA_ACCESSED = 0b0001\n      , /// 0 if this segment is read-only, 1 if it is read-write\n        const WRITE         = 0b0010\n      , /// 1 if this segment expands down\n        const EXPAND_DOWN   = 0b0100\n    }\n}\n\nimpl DataFlags {\n    /// Returns true if the data segment is read-only\n    #[inline] pub fn is_read_only(&self) -> bool {\n        !self.contains(WRITE)\n    }\n\n    /// Returns true if the data segment has been accessed\n    #[inline] pub fn is_accessed(&self) -> bool {\n        self.contains(DATA_ACCESSED)\n    }\n\n    /// Returns true if the data segment expands down\n    #[inline] pub fn is_expand_down(&self) -> bool {\n        self.contains(EXPAND_DOWN)\n    }\n}\n\nbitflags! {\n    /// The type-specific section of a code segment's flags\n    pub flags CodeFlags: u16 {\n        /// 0 if this segment hasn't been accessed, 1 if it has\n        const CODE_ACCESSED = 0b0001\n      , /// 0 if this segment is read-only, 1 if it is read-write\n        const READ          = 0b0010\n      , /// 0 if this segment is not executable, 1 if it is executable\n        const EXECUTE       = 0b1000\n      , /// 0 if this segment is non-conforming, 1 if it is conforming\n        const CONFORMING    = 0b0100\n      , /// Whether this segment is execute-only\n        const EXEC_ONLY     = EXECUTE.bits & !READ.bits\n    }\n}\n\nimpl CodeFlags {\n    /// Returns true if the code segment is execute-only (not readable)\n    #[inline] pub fn is_exec_only(&self) -> bool {\n        self.contains(EXEC_ONLY)\n    }\n\n    /// Returns true if the code segment is readable\n    #[inline] pub fn is_readable(&self) -> bool {\n        self.contains(READ)\n    }\n\n    /// Returns true if the code segment has been accessed.\n    #[inline] pub fn is_accessed(&self) -> bool {\n        self.contains(CODE_ACCESSED)\n    }\n\n    /// Returns true if the code segment is conforming.\n    #[inline] pub fn is_conforming(&self) -> bool {\n        self.contains(CONFORMING)\n    }\n}\n"
  },
  {
    "path": "cpu/src/x86_all/timer.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2016 Eliza eisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\n//! Code for interacting with the system timer & timestamp register.\n#![warn(missing_docs)]\npub mod timestamp {\n    //! x86 Timestamp register\n    use core::mem;\n\n\n    /// Read the current value of the timestamp counter.\n    ///\n    /// # Safety\n    /// + This will cause a General Protection Fault if the TSD flag in register\n    ///   `%cr4` is set and the CPL is greater than 0.\n    pub unsafe fn rtdsc() -> u64 {\n        let (high, low): (u32, u32);\n        asm!( \"rdtsc\"\n            : \"={eax}\" (low), \"={edx}\" (high));\n        mem::transmute((high, low))\n    }\n\n    /// Read the current timestamp, after other instructions have been executed.\n    ///\n    /// # Safety\n    /// + This will cause a General Protection Fault if the TSD flag in register\n    ///   `%cr4` is set and the CPL is greater than 0.\n    pub unsafe fn rtdscp() -> u64 {\n        let (high, low): (u32, u32);\n        asm!( \"rdtscp\"\n            : \"={eax}\" (low), \"={edx}\" (high)\n            ::: \"volatile\");\n        mem::transmute((high, low))\n    }\n\n    /// Returns true if timestamps are currently available.\n    #[inline]\n    pub fn is_available() -> Result<(), &'static str> {\n        use ::control_regs::cr4;\n        use ::PrivilegeLevel;\n\n        if PrivilegeLevel::current_iopl() != PrivilegeLevel::KernelMode {\n            Err(\"Reading timestamp register requires kernel mode.\")\n        } else if\n            // it's safe to do this since we already know we are in kernel mode.\n            unsafe { cr4::is_timestamp_disabled() } {\n            Err(\"Timestamp Disable bit in %cr4 is set\")\n        } else { Ok(()) }\n    }\n\n    /// Returns the current timestamp, or an error\n    #[inline]\n    pub fn get_timestamp() -> Result<u64, &'static str> {\n        is_available().map(|_| unsafe { rtdsc() })\n    }\n\n    /// Returns the current timestamp or an error, after other instructions have\n    /// been executed.\n    #[inline]\n    pub fn wait_get_timestamp() -> Result<u64, &'static str> {\n        is_available().map(|_| unsafe { rtdscp() })\n    }\n}\n"
  },
  {
    "path": "elf/Cargo.toml",
    "content": "[package]\nname = \"elf\"\nversion = \"0.0.2\"\nauthors = [ \"Eliza Weisman <eliza@elizas.website>\" ]\n\n[profile.dev]\nopt-level = 3\ndebug = true\nrpath = false\nlto = false\ndebug-assertions = true\ncodegen-units = 1\npanic = \"abort\"\n\n[profile.release]\nopt-level = 3\ndebug = true\nrpath = false\nlto = false\npanic = \"abort\"\n\n[dependencies]\nbitflags = \"0.7\"\nmemory = { path = \"../memory\" }\n\n[dependencies.macro-attr]\ngit = \"https://github.com/DanielKeep/rust-custom-derive.git\"\nversion = \"0.2.1\"\ndefault-features = false\n"
  },
  {
    "path": "elf/README.md",
    "content": "elf: ELF parsing and loading\n============================\n\na library for parsing, navigating, and loading 32- and 64-bit [Executable and Linkable File](http://wiki.osdev.org/ELF)s.\n\n### why are we writing our own ELF lib?\n\nalthough 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:\n\n+ requirements specific to our use-case (no std, no allocation, &c)\n+ up to date with recent Rust language features (not all ELF libs are actively maintained)\n+ compatibility with SOS' types & representations without translation layers (e.g., uses our `PAddr` type.)\n+ it's fun & I want to do it myself!\n"
  },
  {
    "path": "elf/src/file.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza Weisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\n//! ELF file header\nuse super::{ElfResult, ElfWord, Section, section};\nuse super::ValidatesWord;\n\nuse section::Header as SectionHeader;\n\nuse core::{fmt, mem, convert};\nuse core::ops::Range;\n\n/// Trait representing an ELF File Header.\n///\n/// This trait allows [HeaderRepr] to provide a consistent API regardless\n/// of whether the header section uses 32- or 64-bit [ELF word]s. A number of\n/// field values in the header of various sizes are converted to `usize` by\n/// this API so that they can be used as indices, etc.\n///\n/// For more information on ELF File Headers, refer to:\n/// + the ELF [specification]\n/// + the [OS Dev Wiki]\n///\n/// [ELF word]: ../type.ElfWord.html\n/// [HeaderRepr]: struct.HeaderRepr.html\n/// [specification](http://www.sco.com/developers/gabi/latest/ch4.eheader.html)\n/// [OS Dev Wiki](http://wiki.osdev.org/ELF#Header)\npub trait Header: Sized {\n    type Word: ElfWord;\n\n    /// Attempt to extract an ELF file header from a slice of bytes.\n    fn from_slice<'a>(input: &'a [u8]) -> ElfResult<&'a Self>;\n\n    /// Attempt to extract a section header from a slice of bytes.\n    /// TODO: can/should the index be `usize`?\n    //          - eliza, 03/08/2017\n    fn parse_section<'a>(&'a self, input: &'a [u8], idx: u16)\n                            -> ElfResult<&'a Section<Self::Word>>;\n\n    fn sh_range(&self) -> Range<usize> {\n        let start = self.sh_offset();\n        start .. start + (self.sh_entry_size() * self.sh_count())\n    }\n\n    fn ph_range(&self) -> Range<usize> {\n        let start = self.ph_offset();\n        start .. start + (self.ph_entry_size() * self.ph_count())\n    }\n\n    /// Calculate the index for a [section header]\n    ///\n    /// TODO: should this check the index is reasonable & return a `Result`\n    //          - eliza, 03/10/2017\n    /// [section header]: ../section/struct.Header.html\n    fn section_index(&self, idx: usize) -> Range<usize> {\n        let size = self.sh_entry_size();\n        let start = self.sh_offset() + (idx * size);\n        start .. start + size\n    }\n\n    /// Calculate the index for a program header\n    ///\n    /// TODO: should this check the index is reasonable & return a `Result`\n    //          - eliza, 03/10/2017\n    fn program_header_index(&self, idx: usize) -> Range<usize> {\n        let size = self.ph_entry_size();\n        let start = self.ph_offset() + (idx * size);\n        start .. start + size\n    }\n\n    // Field accessors -------------------------------------------\n    fn ident(&self) -> Ident;\n    fn get_type(&self) -> Type;\n    fn machine(&self) -> Machine;\n    /// Offset of the program entry point\n    fn entry_point(&self) -> usize;\n    /// Offset of the start of program headers\n    fn ph_offset(&self) -> usize;\n    /// Number of program headers.\n    fn ph_count(&self) -> usize;\n    /// Size of a program header.\n    fn ph_entry_size(&self) -> usize;\n    /// Offset of the start of [section header]s.\n    ///\n    /// [section header]: ../section/struct.Header.html\n    fn sh_offset(&self) -> usize;\n    /// Number of [section header]s.\n    ///\n    /// [section header]: ../section/struct.Header.html\n    fn sh_count(&self) -> usize;\n    /// Size of a [section header].\n    ///\n    /// [section header]: ../section/struct.Header.html\n    fn sh_entry_size(&self) -> usize;\n    /// TODO: can this return the flags type?\n    //          - eliza, 03/08/2017\n    fn flags(&self) -> u32;\n    /// Index of the section header [string table].\n    ///\n    /// [string table]: ../section/struct.StrTable.html\"]\n    fn sh_str_idx(&self) -> usize;\n}\n\nmacro_rules! Header {\n    (($($size:ty),+) $(pub)* enum $name:ident $($tail:tt)* ) => {\n        Header! { @impl $name, $($size)+ }\n    };\n    (($($size:ty),+) $(pub)* struct $name:ident $($tail:tt)*) => {\n        Header! { @impl $name, $($size)+ }\n    };\n    (@impl $name:ident, $($size:ty)+) => {\n        $(impl Header for $name<$size> {\n            type Word = $size;\n            /// Attempt to extract an ELF file header from a slice of bytes.\n            fn from_slice<'a>(input: &'a [u8]) -> ElfResult<&'a Self> {\n                if input.len() < mem::size_of::<Self>() {\n                    Err(\"Input too short to extract ELF header\")\n                } else {\n                    unsafe {\n                        super::extract_from_slice::<Self>(input, 0, 1)\n                            .map(|x| &x[0]) }\n                }\n            }\n\n            /// Attempt to extract a [section header] from a slice of bytes.\n            ///\n            /// TODO: should this move to the `File` type since it owns the\n            ///       byte slice (which then wouldn't have to be passed as an\n            ///       argument)?\n            //          - eliza, 03/10/2017\n            ///\n            /// [section header]: ../section/struct.Header.html\n            fn parse_section<'a>(&'a self, input: &'a [u8], idx: u16)\n                                -> ElfResult<&'a Section<Self::Word>>\n            where section::HeaderRepr<Self::Word>: SectionHeader<Word = Self::Word> {\n                if idx < section::SHN_LORESERVE {\n                    Err(\"Cannot parse reserved section.\")\n                } else {\n                    // use ValidatesWord to check if this section's Class field\n                    // will let us interpret the section with the requested\n                    // word length. this is a bit of a hack around the type\n                    // system not letting me do this the way I wanted to to....\n                    let validator: &ValidatesWord<Self::Word>\n                        = &self.ident.class;\n                    validator.check()?;\n\n                    let raw = &input[self.section_index(idx as usize)];\n\n                    unsafe {\n                        Ok(&*(raw as *const [u8]\n                                  as *const _\n                                  as *const section::HeaderRepr<Self::Word>))\n                    }\n                }\n            }\n\n            #[inline] fn get_type(&self) -> Type { self.elftype.as_type() }\n\n            impl_getters! {\n                #[doc = \"Index for the start of [section header]s. \\\n                         [section header]: ../section/struct.Header.html\"]\n                fn sh_offset(&self) -> usize;\n                fn sh_entry_size(&self) -> usize;\n                fn sh_count(&self) -> usize;\n\n                #[doc = \"Index for the start of program headers\"]\n                fn ph_offset(&self) -> usize;\n                fn ph_entry_size(&self) -> usize;\n                fn ph_count(&self) -> usize;\n\n                #[doc = \"Index for the program entry point\"]\n                fn entry_point(&self) -> usize;\n                #[doc = \"Index of the section header [string table] \\\n                         [string table]: ../section/struct.StrTable.html\"]\n                fn sh_str_idx(&self) -> usize;\n                fn flags(&self) -> u32;\n                fn ident(&self) -> Ident;\n                fn machine(&self) -> Machine;\n            }\n        }\n\n        impl<'a> convert::TryFrom<&'a [u8]> for &'a $name<$size> {\n            type Error = &'static str;\n            #[inline]\n            fn try_from(slice: &'a [u8]) -> ElfResult<Self> {\n                <$name<$size> as Header>::from_slice(slice)\n            }\n        }\n        )+\n    }\n}\n\nmacro_attr! {\n    /// Raw representation of an ELF file header.\n    #[derive(Copy, Clone, Debug, Header!(u32, u64))]\n    #[repr(C, packed)]\n    pub struct HeaderRepr<W: ElfWord> {\n        /// the ELF [file identifier](struct.Ident.html)\n        pub ident: Ident\n      , elftype: TypeRepr\n      , pub machine: Machine\n      , /// Program entry point\n        entry_point: W\n      , /// Offset for start of program headers\n        ph_offset: W\n      , /// Offset for start of [section header]s.\n        /// [section header]: ../section/struct.Header.html\n        sh_offset: W\n      , pub flags: u32\n      , pub header_size: u16\n      , pub ph_entry_size: u16\n      , pub ph_count: u16\n      , pub sh_entry_size: u16\n      , pub sh_count: u16\n      , /// Index of the section header string table\n        sh_str_idx: u16\n    }\n}\n\n/// ELF header magic\npub const MAGIC: Magic = [0x7f, b'E', b'L', b'F'];\n\n/// Type of header magic\npub type Magic = [u8; 4];\n\n\n/// ELF identifier (`e_ident` in the ELF standard)\n#[derive(Copy, Clone, Debug)]\n#[repr(C, packed)]\npub struct Ident {\n    /// ELF magic numbers. Must be equal to the [ELF magic], `[0x7, E, L, F]`.\n    ///\n    /// [ELF magic]: constant.MAGIC.html\n    pub magic: Magic\n  , /// ELF [file class](enum.Class.html) (32- or 64-bit)\n    pub class: Class\n  , /// ELF [data encoding](enum.DataEncoding.html) (big- or little-endian)\n    pub encoding: DataEncoding\n  , /// ELF file [version](enum.Version.html)\n    pub version: Version\n  , /// What [operating system ABI] this file was compiled for.\n    ///\n    /// [operating system ABI]: enum.OsAbi.html\n    pub abi: OsAbi\n  , /// ABI version (often this is just padding)\n    pub abi_version: u8\n  , _padding: [u8; 7]\n}\n\nimpl Ident {\n    #[inline] pub fn check_magic(&self) -> bool { self.magic == MAGIC }\n\n    /// Returns true if the identifier section identifies a valid ELF file.\n    #[inline] pub fn is_valid(&self) -> bool {\n        // the ELF magic number is correct\n        self.check_magic() &&\n        // the file class is either 32- or 64-bits\n        self.class.is_valid() &&\n        // the data encoding is either big- or little-endian\n        self.encoding.is_valid()\n    }\n}\n\n/// Identifies the class of the ELF file\n#[derive(Copy, Clone, PartialEq, Debug)]\n#[repr(u8)]\npub enum Class {\n    /// Invalid ELF class file (`ELFCLASSNONE` in the standard)\n    None  = 0\n  , /// 32-bit ELF file (`ELFCLASS32` in the standard)\n    Elf32 = 1\n  , /// 64-bit ELF file (`ELFCLASS64` in the standard)\n    Elf64 = 2\n}\n\nimpl Class {\n    /// Returns true if the class field for this file is valid.\n    #[inline]\n    pub fn is_valid(&self) -> bool {\n        match *self { Class::None => false\n                    , _ => true\n                    }\n    }\n\n}\n\nimpl ValidatesWord<u64> for Class {\n    #[inline]\n    fn check(&self) -> ElfResult<()> {\n        use self::Class::*;\n        match *self {\n            None => Err(\"Invalid ELF type ELFCLASSNONE!\")\n          , Elf32 => Err(\"Cannot extract 64-bit section from 32-bit ELF\")\n          , Elf64 => Ok(())\n        }\n    }\n}\n\nimpl ValidatesWord<u32> for Class {\n    #[inline]\n    fn check(&self) -> ElfResult<()> {\n        use self::Class::*;\n        match *self {\n            None => Err(\"Invalid ELF type ELFCLASSNONE!\")\n          , Elf64 =>\n                // TODO: is this actually true?\n                //          - eliza, 03/08/2017\n                Err(\"Cannot extract 32-bit section from 64-bit ELF\")\n          , Elf32 => Ok(())\n        }\n    }\n}\n\n/// Identifies the data encoding of the ELF file\n#[derive(Copy, Clone, PartialEq, Debug)]\n#[repr(u8)]\npub enum DataEncoding {\n    /// Invalid data encoding (`ELFDATANONE` in the standard)\n    None  = 0\n  , /// Twos-complement little-endian data encoding\n    /// (`ELFDATA2LSB` in the standard)\n    LittleEndian = 1\n  , /// Twos-complement big-endian data encoding\n    /// (`ELFDATA2MSB` in the standard)\n    BigEndian = 2\n}\n\nimpl DataEncoding {\n    /// Returns true if the data encoding field for this file is valid.\n    #[inline]\n    pub fn is_valid(&self) -> bool {\n        match *self { DataEncoding::None => false\n                    , _ => true\n                    }\n    }\n}\n\n/// Operating system ABI\n#[derive(Copy, Clone, Debug)]\n#[repr(u8)]\npub enum OsAbi { /// Ox00 also represents \"none\"\n                 SystemV = 0x00\n               , HpUx    = 0x01\n               , NetBsd  = 0x02\n               , Linux   = 0x03\n               , Solaris = 0x06\n               , Aix     = 0x07\n               , Irix    = 0x08\n               , FreeBsd = 0x09\n               , OpenBsd = 0x0C\n               , OpenVms = 0x0D\n               }\n\n/// Identifies the version of the ELF file\n#[derive(Copy, Clone, PartialEq, Debug)]\n#[repr(u8)]\npub enum Version { None = 0, Current = 1 }\n\n#[derive(Clone, Copy, PartialEq)]\nstruct TypeRepr(u16);\n\nimpl TypeRepr {\n    /// TODO: rewrite this as a `convert::Into` implementation\n    ///         - eliza, 03/09/2017\n    pub fn as_type(&self) -> Type {\n        match self.0 {\n            0 => Type::None\n          , 1 => Type::Relocatable\n          , 2 => Type::Executable\n          , 3 => Type::SharedObject\n          , 4 => Type::Core\n          , anything => Type::Other(anything)\n        }\n    }\n}\n\nimpl fmt::Debug for TypeRepr {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        self.as_type().fmt(f)\n    }\n}\n\n#[derive(Clone, Copy, PartialEq, Debug)]\npub enum Type { None\n              , Relocatable\n              , Executable\n              , SharedObject\n              , Core\n              , Other(u16)\n              }\n\n#[allow(non_camel_case_types)]\n#[derive(Clone, Copy, PartialEq, Debug)]\n#[repr(u16)]\npub enum Machine { None    = 0\n                 , Sparc   = 0x02\n                 , X86     = 0x03\n                 , Mips    = 0x08\n                 , PowerPc = 0x14\n                 , Arm     = 0x28\n                 , SuperH  = 0x2A\n                 , Ia64    = 0x32\n                 , X86_64  = 0x3E\n                 , AArch64 = 0xB7\n                 }\n"
  },
  {
    "path": "elf/src/lib.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza Weisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\n//! Parsing and loading Executable and Linkable Format (ELF) 32- and 64-bit\n//! binaries.\n//!\n//! For more information on the ELF format, refer to:\n//!\n//!  + [Wikipedia](https://en.wikipedia.org/wiki/Executable_and_Linkable_Format)\n//!  + The [OS Dev Wiki](http://wiki.osdev.org/ELF)\n//!  + The [ELF Format Specification](elfspec)\n//!\n//! [elfspec]: http://www.skyfree.org/linux/references/ELF_Format.pdf\n#![feature(core_intrinsics)]\n#![feature(try_from)]\n#![no_std]\n\n#[macro_use] extern crate bitflags;\n#[macro_use] extern crate macro_attr;\n\nextern crate memory;\n\nuse core::{ ops, mem, slice, convert };\nuse core::convert::TryFrom;\n\nuse memory::{ FrameRange, PhysicalPage };\n\n\nmacro_rules! impl_getters {\n    ($(#[$attr:meta])* pub fn $name:ident(&self) -> PAddr; $($rest:tt)*) => {\n        $(#[$attr])* #[inline] pub fn $name(&self) -> ::memory::PAddr {\n            use ::memory::{PAddr, Addr};\n            PAddr::from(self.$name as <PAddr as Addr>::Repr)\n        }\n        impl_getters!{ $( $rest )* }\n    };\n    ($(#[$attr:meta])* fn $name:ident(&self) -> PAddr; $($rest:tt)*) => {\n        $(#[$attr])* #[inline] fn $name(&self) -> ::memory::PAddr {\n            use ::memory::{PAddr, Addr};\n            PAddr::from(self.$name as <PAddr as Addr>::Repr)\n        }\n        impl_getters!{ $( $rest )* }\n    };\n    ($(#[$attr:meta])* pub fn $name:ident(&self) -> PAddr;) => {\n        $(#[$attr])* #[inline] pub fn $name(&self) -> ::memory::PAddr {\n            use ::memory::{PAddr, Addr};\n            PAddr::from(self.$name as <PAddr as Addr>::Repr)\n        }\n        impl_getters!{ $( $rest )* }\n    };\n    ($(#[$attr:meta])* fn $name:ident(&self) -> PAddr;) => {\n        $(#[$attr])* #[inline] fn $name(&self) -> ::memory::PAddr {\n            use ::memory::{PAddr, Addr};\n            PAddr::from(self.$name as <PAddr as Addr>::Repr)\n        }\n        impl_getters!{ $( $rest )* }\n    };\n    ($(#[$attr:meta])* pub fn $name:ident(&self) -> $ty:ty; $($rest:tt)*) => {\n        $(#[$attr])* #[inline] pub fn $name(&self) -> $ty { self.$name as $ty }\n        impl_getters!{ $( $rest )* }\n    };\n    ($(#[$attr:meta])* fn $name:ident(&self) -> $ty:ty; $($rest:tt)*) => {\n        $(#[$attr])* #[inline] fn $name(&self) -> $ty { self.$name as $ty }\n        impl_getters!{ $( $rest )* }\n    };\n    ( $(#[$attr:meta])* pub fn $name: ident (&self)-> $ty:ty; ) => {\n        $(#[$attr])* #[inline] pub fn $name(&self) -> $ty { self.$name as $ty }\n    };\n    ( $(#[$attr:meta])* fn $name: ident (&self)-> $ty:ty; ) => {\n        $(#[$attr])* #[inline] fn $name(&self) -> $ty { self.$name as $ty }\n    };\n    () => {};\n}\n\npub mod section;\npub mod file;\npub mod program;\n\n/// An ELF section header.\npub type Section<W> = section::Header<Word = W>;\npub type ProgramHeader<W> = program::Header<Word = W>;\n/// An ELF header file.\npub type FileHeader<W> = file::HeaderRepr<W>;\n\n/// TODO: should ELF have its own error type?\npub type ElfResult<T> = Result<T, &'static str>;\n\npub trait ElfWord: Sized + Copy + Clone\n                         + ops::Add<Self> + ops::Sub<Self>\n                         + ops::Mul<Self> + ops::Div<Self>\n                         + ops::Shl<Self> + ops::Shr<Self> { }\nimpl ElfWord for u64 { }\nimpl ElfWord for u32 { }\n\n#[cfg(target_pointer_width = \"32\")]\ntype DefaultWord = u32;\n#[cfg(target_pointer_width = \"64\")]\ntype DefaultWord = u64;\n\n/// Hack to make the type-system let me do what I want\ntrait ValidatesWord<Word: ElfWord> {\n    fn check(&self) -> ElfResult<()>;\n}\n\n/// A handle on a parsed ELF binary\n///  TODO: do we want this to own a HashMap of section names to section headers,\n///        to speed up section lookup?\n//          - eliza, 03/08/2017\n#[derive(Debug)]\npub struct Image< 'bytes             // lifetime of the byte slice\n                , Word = DefaultWord // default to machine's pointer size\n                , ProgHeader = ProgramHeader<Word> // same word type\n                , SectHeader = Section<Word>\n                , Header = FileHeader<Word> // must have same word type\n                > // jesus christ\nwhere Word: ElfWord + 'bytes\n    , ProgHeader: program::Header<Word = Word> + Sized + 'bytes\n    , SectHeader: section::Header<Word = Word> + Sized + 'bytes\n    , Header: file::Header<Word = Word> + 'bytes\n    {\n    /// the binary's [file header](file/trait.Header.html)\n    pub header: &'bytes Header\n  , /// references to each [section header](section/struct.Header.html)\n    pub sections: &'bytes [SectHeader]\n  , /// references to each [program header](program/trait.Header.html)\n    pub program_headers: &'bytes [ProgHeader]\n  , /// the raw binary contents of the ELF binary.\n    /// note that this includes the _entire_ binary contents of the file,\n    /// so the file header and each section header is included in this slice.\n    binary: &'bytes [u8]\n}\n\nimpl <'a, Word, ProgHeader, SectHeader, Header>\nImage<'a, Word, ProgHeader, SectHeader, Header>\nwhere Word: ElfWord + 'a\n    , ProgHeader: program::Header<Word = Word> + Sized + 'a\n    , SectHeader: section::Header<Word = Word> + Sized + 'a\n    , Header: file::Header<Word = Word> + 'a\n    {\n    /// Returns the section header [string table].\n    ///\n    /// [string table]: section/struct.StrTable.html\n    pub fn sh_str_table(&'a self) -> section::StrTable<'a> {\n        // TODO: do we want to validate that the string table index is\n        //       reasonable (e.g. it's not longer than the binary)?\n        //          - eliza, 03/08/2017\n        // TODO: do we want to cache a ref to the string table?\n        //          - eliza, 03/08/2017\n        section::StrTable::from(&self.binary[self.header.sh_str_idx()..])\n    }\n\n}\n\nimpl<'a, Word, PH, SH, FH> TryFrom<&'a [u8]> for Image<'a, Word, PH, SH, FH>\nwhere Word: ElfWord + 'a\n    , PH: program::Header<Word = Word> + 'a\n    , SH: section::Header<Word = Word> + 'a\n    , FH: file::Header<Word = Word> + 'a\n    , &'a FH: convert::TryFrom<&'a [u8], Error = &'static str>\n    {\n\n    type Error = &'static str;\n\n    fn try_from(bytes: &'a [u8]) -> ElfResult<Self> {\n        let header: &'a FH = <&'a FH>::try_from(bytes)?;\n\n        let sections = unsafe { extract_from_slice::<SH>(\n            &bytes[header.sh_range()]\n          , 0\n          , header.sh_count()\n        )? };\n        let prog_headers = unsafe { extract_from_slice::<PH>(\n            &bytes[header.ph_range()]\n          , 0\n          , header.ph_count()\n        )? };\n        Ok(Image { header: header\n              , sections: sections\n              , program_headers: prog_headers\n              , binary: bytes\n        })\n    }\n}\n\n/// Extract `n` instances of type `T` from a byte slice.\n///\n/// This is essentially just a _slightly_ safer wrapper around\n/// [`slice::from_raw_parts`]. Unlike `from_raw_parts`, this function takes\n/// a valid byte slice, rather than a pointer. Therefore, some of the safety\n/// issues with `from_raw_parts` are avoided:\n///\n/// + the lifetime (`'slice`) of the returned slice should be the same as the\n///   lifetime of the input slice (`data`), rather than inferred arbitrarily.\n/// + this function will panic rather than reading past the end of the slice.\n///\n/// # Arguments\n///\n/// + `data`: the byte slice to extract a slice of `&[T]`s from\n/// + `offset`: a start offset into `data`\n/// + `n`: the number of instances of `T` which should be contained\n///        in `data[offset..]`\n///\n/// # Safety\n///\n/// While this function is safer than [`slice::from_raw_parts`],\n/// it is still unsafe for the following reasons:\n///\n/// + The contents of `data` may not be able to be interpreted as instances of\n///   type `T`.\n///\n/// # Caveats\n///\n/// + If `n` == 0, this will give you an `&[]`. Just a warning.\n//    thanks to Max for making  me figure this out.\n/// + `offset` must be aligned on a `T`-sized boundary.\n///\n/// # Panics\n///\n/// + If the index `offset` is longer than `T`\n///\n/// TODO: rewrite this as a `TryFrom` implementation (see issue #85)\n//          - eliza, 03/09/2017\n///       wait, possibly we should NOT do that. actually we should\n///       almost certainly not do that. since this function is unsafe,\n///       but `TryFrom` is not, and because this would be WAY generic.\n//          - eliza, 03/09/2017\n/// TODO: is this general enough to move into util?\n//          - eliza, 03/09/2017\n/// TODO: refactor this to take a `RangeArgument`?\n//          - eliza, 03/13/2017\n///       or, we could just remove the offset and expect the caller to\n///       offset the slice?\n//          - eliza, 03/14/2017\n///\n/// [`slice::from_raw_parts`]: https://doc.rust-lang.org/stable/std/slice/fn.from_raw_parts.html\nunsafe fn extract_from_slice<'slice, T: Sized>( data: &'slice [u8]\n                                              , offset: usize\n                                              , n: usize)\n                                              -> ElfResult<&'slice [T]> {\n    if offset % mem::align_of::<T>() != 0 {\n        // TODO: these error messages don't contain as much information as they\n        //       used to, since the return type is `&'static str` that can't be\n        //       dynamically formatted as the panic was. refactor this?\n        //       (e.g. should ELF get its own error type?)\n        //        - eliza, 03/15/2017\n        Err(\"extract_from_slice: Offset not aligned on type T sized boundary!\")\n        // assert!(\n        //        , \"Offset {} not aligned on a {}-sized boundary (must be \\\n        //           divisible by {}).\"\n        //        , offset, type_name::<T>(), mem::align_of::<T>()\n        //        );\n    } else if data.len() - offset < mem::size_of::<T>() * n {\n        Err(\"extract_from_slice: Slice too short to contain n instances of T!\")\n        // assert!(\n        //        , \"Slice too short to contain {} objects of type {}\"\n        //        , n, type_name::<T>()\n        //        );\n    } else {\n        Ok(slice::from_raw_parts(data[offset..].as_ptr() as *const T, n))\n    }\n}\n\nimpl<'a, W: ElfWord> convert::Into<FrameRange> for &'a Section<W> {\n    #[inline]\n    fn into(self) -> FrameRange {\n        use memory::Page;\n        let start = PhysicalPage::containing(self.address());\n        let end = PhysicalPage::containing(self.end_address());\n        start .. end\n    }\n}\n"
  },
  {
    "path": "elf/src/program.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza Weisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\n\nuse super::ElfWord;\n\n/// Trait representing an ELF Program Header.\n///\n/// This trait allows [HeaderRepr] to provide a consistent API regardless\n/// of whether the header section uses 32- or 64-bit [ELF word]s. A number of\n/// field values in the header of various sizes are converted to `usize` by\n/// this API so that they can be used as indices, etc.\n///\n/// For more information on ELF Program Headers, refer to:\n/// + the ELF [specification]\n/// + the [OS Dev Wiki]\n///\n/// [ELF word]: ../type.ElfWord.html\n/// [HeaderRepr]: struct.HeaderRepr.html\n/// [specification](http://www.sco.com/developers/gabi/latest/ch5.pheader.html)\n/// [OS Dev Wiki](http://wiki.osdev.org/ELF#Header)\npub trait Header: Sized {\n    type Word: ElfWord;\n\n    /// Returns the [type](enum.Type.html) of this program header.\n    ///\n    /// This member tells what kind of segment this header describes or how to\n    /// interpret the array element's information.\n    fn ty(&self) -> Type;\n\n    /// Returns this segment's start offset from the beginning of the binary.\n    fn offset(&self) -> usize;\n\n    /// Returns the virtual address of the first byte in this segment.\n    fn vaddr(&self) -> Self::Word;\n\n    /// Returns the physical address of the first byte in this segment.\n    fn paddr(&self) -> Self::Word;\n\n    /// Returns the number of bytes in the file image of the segment.\n    ///\n    /// This may be zero.\n    fn file_size(&self) -> usize;\n\n    /// Returns the number of bytes in the memory image of the segment.\n    ///\n    /// This may be zero.\n    fn mem_size(&self) -> usize;\n\n    /// Returns the [flags] for this segment.\n    ///\n    /// [flags]: struct.Flags.html\n    fn flags(&self) -> Flags;\n\n    fn align(&self) -> usize;\n\n}\n\n\nmacro_rules! Header {\n    (($($size:ty),+) $(pub)* enum $name:ident $($tail:tt)* ) => {\n        Header! { @impl $name, $($size)+ }\n    };\n    (($($size:ty),+) $(pub)* struct $name:ident $($tail:tt)*) => {\n        Header! { @impl $name, $($size)+ }\n    };\n    (@impl $name:ident, $size:ty) => {\n        impl Header for $name {\n            type Word = $size;\n\n            impl_getters! {\n                fn ty(&self) -> Type;\n                fn flags(&self) -> Flags;\n                fn offset(&self) -> usize;\n\n                fn vaddr(&self) -> Self::Word;\n                fn paddr(&self) -> Self::Word;\n\n                fn file_size(&self) -> usize;\n                fn mem_size(&self) -> usize;\n                fn align(&self) -> usize;\n            }\n        }\n    };\n}\n\n/// The type field of an ELF program header\n#[repr(u32)]\n#[derive(Copy, Clone, Debug)]\npub enum Type {\n    /// `PT_NULL`: Program header table entry unused\n    Null = 0\n  , /// `PT_LOAD`: Loadable program segment\n    Loadable = 1\n  , /// `PT_DYNAMIC`: Dynamic linking information\n    Dynamic = 2\n  , /// `PT_INTERP`: Program interpreter\n    Interpreter = 3\n  , /// `PT_NOTE`: Auxiliary information\n    Note = 4\n  , /// `PT_SHLIB`\n    ShLib = 5\n  , /// `PT_PHDR`: Program Header table\n    HeaderTable = 6\n  , /// `PT_TLS`: Thread-local storage\n    ThreadLocal = 7\n  , /// GCC `.eh_frame_hdr` segment\n    GnuEhFrame = 0x6474e550\n  , /// Indicates stack executability\n    GnuStack = 0x6474e551\n  , /// Read-only after relocation\n    GnuRelRo = 0x6474e552\n}\n\nbitflags! {\n    pub flags Flags: u32 {\n        const NONE = 0\n      , const EXECUTABLE = 1 << 0\n      , const WRITABLE = 1 << 1\n      , const READABLE = 1 << 2\n    }\n}\n\nmacro_attr! {\n    /// A 64-bit ELF Program Header\n    #[derive(Copy, Clone, Debug, Header!(u64))]\n    pub struct HeaderRepr64 {\n        pub ty: Type\n      , pub flags: Flags\n      , pub offset: u64\n      , pub vaddr: u64\n      , pub paddr: u64\n      , pub file_size: u64\n      , pub mem_size: u64\n      , pub align: u64\n    }\n}\n\nmacro_attr! {\n    /// A 32-bit ELF Program Header\n    #[derive(Copy, Clone, Debug, Header!(u32))]\n    pub struct HeaderRepr32 {\n        pub ty: Type\n      , pub offset: u32\n      , pub vaddr: u32\n      , pub paddr: u32\n      , pub file_size: u32\n      , pub mem_size: u32\n      , pub flags: Flags\n      , pub align: u32\n    }\n}\n"
  },
  {
    "path": "elf/src/section.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza Weisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\nuse super::{ElfResult, ElfWord};\n\nuse core::{convert, fmt, ops};\nuse core::iter::IntoIterator;\n\nuse memory::{Addr, PAddr};\n\n// Distinguished section indices.\npub const SHN_UNDEF: u16        = 0;\npub const SHN_LORESERVE: u16    = 0xff00;\npub const SHN_LOPROC: u16       = 0xff00;\npub const SHN_HIPROC: u16       = 0xff1f;\npub const SHN_LOOS: u16         = 0xff20;\npub const SHN_HIOS: u16         = 0xff3f;\npub const SHN_ABS: u16          = 0xfff1;\npub const SHN_COMMON: u16       = 0xfff2;\npub const SHN_XINDEX: u16       = 0xffff;\npub const SHN_HIRESERVE: u16    = 0xffff;\n\npub const SHT_LOOS: u32   = 0x60000000;\npub const SHT_HIOS: u32   = 0x6fffffff;\npub const SHT_LOPROC: u32 = 0x70000000;\npub const SHT_HIPROC: u32 = 0x7fffffff;\npub const SHT_LOUSER: u32 = 0x80000000;\npub const SHT_HIUSER: u32 = 0xffffffff;\n\n/// Represents an ELF section header\n///\n/// Refer to [Figure 4-8], \"Section Header\", from Chapter 4 of the ELF standard\n/// for more information.\n///\n/// [Figure 4-8]: (http://www.sco.com/developers/gabi/latest/ch4.sheader.html#section_header)\n// #[derive(Clone, Copy, Debug)]\n// pub enum Header<'a> {\n//     ThirtyTwo(&'a HeaderRepr<u32>)\n//   , SixtyFour(&'a HeaderRepr<u64>)\n// }\npub trait Header: fmt::Debug {\n    type Word: ElfWord;\n\n    // /// Returns the start address of this section\n    // fn addr(&self) -> PAddr;\n\n    /// Returns the end address of this section\n    /// TODO: refactor this to return a Range instead?\n    //          - eliza, 03/14/2017\n    #[inline] fn end_address(&self) -> PAddr {\n        self.address() + self.length() as <PAddr as Addr>::Repr\n    }\n\n    /// Returns true if this section is writable.\n    #[inline] fn is_writable(&self) -> bool {\n        self.flags().contains(SHF_WRITE)\n    }\n\n    /// Returns true if this section occupies memory during program execution.\n    #[inline] fn is_allocated(&self) -> bool {\n        self.flags().contains(SHF_ALLOC)\n    }\n\n    /// Returns true if this section contains executable instructions.\n    #[inline] fn is_executable(&self) -> bool {\n        self.flags().contains(SHF_EXECINSTR)\n    }\n\n    /// Returns true if this section can be merged.\n    #[inline] fn is_mergeable(&self) -> bool {\n        self.flags().contains(SHF_MERGE)\n    }\n\n    /// Returns true if this section contains data that is of a uniform size.\n    #[inline] fn is_uniform(&self) -> bool {\n        let flags = self.flags();\n        flags.contains(SHF_MERGE) &&\n        !flags.contains(SHF_STRINGS)\n    }\n\n    /// Look up the name of this section in the passed string table.\n    #[inline] fn get_name<'a>(&self, strtab: StrTable<'a>) -> &'a str {\n        unimplemented!()\n    }\n\n    // Field accessors -------------------------------------------------\n    fn name_offset(&self) -> u32;\n    /// This member categorizes the section's contents and semantics.\n    fn get_type(&self) -> ElfResult<Type>;\n    fn flags(&self) -> Flags;\n    fn address(&self) -> PAddr;\n    fn offset(&self) -> usize;\n    /// TODO: should offset + length make a Range?\n    //          - eliza, 03/14/2017\n    fn length(&self) -> usize;\n    fn link(&self) -> u32;\n    fn info(&self) -> u32;\n    fn address_align(&self) -> Self::Word;\n    fn entry_length(&self) -> usize;\n}\n\nmacro_rules! Header {\n    (($($size:ty),+) $(pub)* enum $name:ident $($tail:tt)* ) => {\n        Header! { @impl $name, $($size)+ }\n    };\n    (($($size:ty),+) $(pub)* struct $name:ident $($tail:tt)*) => {\n        Header! { @impl $name, $($size)+ }\n    };\n    (@impl $name:ident, $($size:ty)+) => {\n        $(impl Header for $name<$size> {\n            type Word = $size;\n\n            /// Returns the type of this section\n            #[inline] fn get_type(&self) -> ElfResult<Type> {\n                 self.ty.as_type()\n             }\n\n            impl_getters! {\n                fn name_offset(&self) -> u32;\n                fn flags(&self) -> Flags;\n                /// TODO: shold this return a PAddr?\n                //          - eliza, 03/14/2017\n                fn address(&self) -> PAddr;\n                fn offset(&self) -> usize;\n                /// TODO: should offset + length make a Range?\n                //          - eliza, 03/14/2017\n                fn length(&self) -> usize;\n                fn link(&self) -> u32;\n                fn info(&self) -> u32;\n                fn address_align(&self) -> Self::Word;\n                fn entry_length(&self) -> usize;\n            }\n        })+\n    };\n}\n\nimpl<Word> fmt::Display for Header<Word = Word>\nwhere Word: ElfWord\n    , Header<Word = Word>: fmt::Debug {\n    #[inline]\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        // TODO: do we want to actually get the section's name from the string\n        //       table and display it here?\n        //          - eliza, 03/05/2017\n        // TODO: do we want to print the header's flags, or would that make the //       format too long?\n        //          - eliza, 03/05/2017\n        if let Ok(ty) = self.get_type() {\n            // the ELF section was valid\n            write!(f, \"{:?} section at {:?} ... {:?}\"\n                  , ty, self.address(), self.end_address())\n        } else {\n            // we couldn't successfully extract a type from the ELF section!\n            write!(f, \"Bad ELF section {:?}\", self)\n        }\n    }\n}\n\nmacro_attr! {\n    /// Raw representation of an ELF section header in an ELF binary.\n    ///\n    /// Refer to [Figure 4-8], \"Section Header\", from Chapter 4 of the ELF\n    /// standard for more information.\n    ///\n    /// [Figure 4-8]: (http://www.sco.com/developers/gabi/latest/ch4.sheader.html#section_header)\n    //  TODO: add docs for all fields!\n    //          - eliza, 03/05/2017\n    #[derive(Debug, Header!(u32, u64))]\n    #[repr(C)]\n    pub struct HeaderRepr<Word> {\n        /// This member specifies the name of the section.\n        ///\n        /// Its value is an index into the section header string table section,\n        /// giving the location of a null-terminated string.\n        name_offset: u32\n      , /// This member categorizes the section's contents and semantics.\n        ty: TypeRepr\n      , flags: Flags\n      , address: Word\n      , offset: Word\n      , length: Word\n      , link: u32\n      , info: u32\n      , address_align: Word\n      , entry_length: Word\n    }\n}\n\n\nbitflags! {\n    // TODO: add documentation to the flags\n    //          - eliza, 03/05/2017\n    pub flags Flags: usize {\n        // Flags (SectionHeader::flags)\n        const SHF_WRITE            =        0x1\n      , const SHF_ALLOC            =        0x2\n      , const SHF_EXECINSTR        =        0x4\n      , const SHF_MERGE            =       0x10\n      , const SHF_STRINGS          =       0x20\n      , const SHF_INFO_LINK        =       0x40\n      , const SHF_LINK_ORDER       =       0x80\n      , const SHF_OS_NONCONFORMING =      0x100\n      , const SHF_GROUP            =      0x200\n      , const SHF_TLS              =      0x400\n      , const SHF_COMPRESSED       =      0x800\n      , const SHF_MASKOS           = 0x0ff00000\n      , const SHF_MASKPROC         = 0xf0000000\n    }\n}\n\nimpl fmt::LowerHex for Flags {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        self.bits.fmt(f)\n    }\n}\n\nbitflags! {\n    pub flags GroupFlags: u32 {\n        const GRP_COMDAT\t=        0x1\n      , const GRP_MASKOS\t= 0x0ff00000\n      , const GRP_MASKPROC\t= 0xf0000000\n    }\n}\n\npub enum Contents<'a> {\n    Empty\n  , Undefined(&'a [u8])\n  , Group { flags: &'a u32\n          , indicies: &'a[u32] }\n}\n\n/// Underlying representation of a section header type field\n///\n/// Unfortunately, we cannot have enums with open ranges yet, so we have\n/// to convert between the ELF file underlying representation and our\n/// type-safe representation.\n///\n/// Refer to [Figure 4-9]: \"Section Types, `sh_type`\" in Section 4 of the\n/// ELF standard for more information.\n///\n/// [Figure 4-9]:  http://www.sco.com/developers/gabi/latest/ch4.sheader.html#sh_type\n#[derive(Debug, Copy, Clone)]\nstruct TypeRepr(u32);\n\nimpl TypeRepr {\n    /// TODO: rewrite this as a `TryFrom` implementation (see issue #85)\n    //          - eliza, 03/09/2017\n    #[inline] fn as_type(&self) -> ElfResult<Type> {\n        match self.0 {\n            0 => Ok(Type::Null)\n          , 1 => Ok(Type::ProgramBits)\n          , 2 => Ok(Type::SymbolTable)\n          , 3 => Ok(Type::StringTable)\n          , 4 => Ok(Type::Rela)\n          , 5 => Ok(Type::HashTable)\n          , 6 => Ok(Type::Dynamic)\n          , 7 => Ok(Type::Notes)\n          , 8 => Ok(Type::NoBits)\n          , 9 => Ok(Type::Rel)\n          , 10 => Ok(Type::Shlib)\n          , 11 => Ok(Type::DynSymTable)\n          , 14 => Ok(Type::InitArray)\n          , 15 => Ok(Type::FiniArray)\n          , 16 => Ok(Type::PreInitArray)\n          , x @ SHT_LOOS ... SHT_HIOS => Ok(Type::OsSpecific(x))\n          , x @ SHT_LOPROC ... SHT_HIPROC => Ok(Type::ProcessorSpecific(x))\n          , x @ SHT_LOUSER ... SHT_HIUSER => Ok(Type::User(x))\n          , _ => Err(\"Invalid section type!\")\n        }\n    }\n}\n\n/// Enum representing an ELF file section type.\n///\n/// Refer to [Figure 4-9]: \"Section Types, `sh_type`\" in Section 4 of the\n/// ELF standard for more information.\n///\n/// [Figure 4-9]:  http://www.sco.com/developers/gabi/latest/ch4.sheader.html#sh_type\n#[derive(Debug, Eq, PartialEq, Ord, PartialOrd)]\npub enum Type {\n    /// Section type 0: `SHT_NULL`\n    ///\n    /// This value marks the section header as inactive; it does not have an\n    /// associated section. Other members of the section header have\n    /// undefined values.\n    Null\n  , /// Section type 1: `SHT_PROGBITS`\n    ///\n    /// The section holds information defined by the program, whose format and\n    /// meaning are determined solely by the program.\n    ProgramBits\n  , /// Section type 2: `SHT_SYMTAB`\n    ///\n    /// Typically, `SHT_SYMTAB` provides symbols for link editing, though it\n    /// may also be used for dynamic linking. As a complete symbol table, it\n    /// may contain many symbols unneces- sary for dynamic linking.\n    ///\n    /// Consequently, an object file may also contain a `SHT_DYNSYM` section,\n    /// which holds a minimal set of dynamic linking symbols, to save space.\n    SymbolTable\n  , /// Section type 3: `SHT_STRTAB`\n    ///\n    /// The section holds a string table. An object file may have multiple\n    /// string table sections.\n    StringTable\n  , /// Section type 4: `SHT_RELA`\n    ///\n    /// The section holds relocation entries with explicit addends, such as\n    /// type `Elf32_Rela` for the 32-bit class of object files. An object file\n    /// may have multiple relocation sections.\n    Rela\n  , /// Section type 5: `SHT_HASH`\n    ///\n    /// The section holds a symbol hash table. All objects participating in\n    /// dynamic linking must contain a symbol hash table. Currently, an object\n    /// file may have only one hash table, but this restriction may be relaxed\n    /// in the future.\n    HashTable\n  , /// Section type 6: `SHT_DYNAMIC`\n    ///\n    /// The section holds information for dynamic linking. Currently, an object\n    /// file may have only one dynamic section, but this restriction may be\n    ///  relaxed in the future.\n    Dynamic\n  , /// Section type 7: `SHT_NOTE`\n    ///\n    /// The section holds information that marks the file in some way.\n    Notes\n  , /// Section type 8: `SHT_NOBITS`\n    ///\n    /// A section of this type occupies no space in the file but otherwise\n    /// resembles `SHT_PROGBITS`. Although this section contains no bytes, the\n    /// `sh_offset` member contains the conceptual file offset.\n    NoBits\n  , /// Section type 9: `SHT_REL`\n    ///\n    /// The section holds relocation entries without explicit addends, such as\n    /// type `Elf32_Rel` for the 32-bit class of object files. An object file\n    /// may have multiple reloca- tion sections.\n    Rel\n  , /// Section type 10: `SHT_SHLIB`\n    ///\n    /// This section type is reserved but has unspecified semantics. Programs\n    /// that contain a section of this type do not conform to the ABI.\n    Shlib\n  , /// Section type 11: `SHT_DYNSYM`\n    ///\n    /// Typically, `SHT_SYMTAB` provides symbols for link editing, though it\n    /// may also be used for dynamic linking. As a complete symbol table, it\n    /// may contain many symbols unneces- sary for dynamic linking.\n    ///\n    /// Consequently, an object file may also contain a `SHT_DYNSYM` section,\n    /// which holds a minimal set of dynamic linking symbols, to save space.\n    DynSymTable\n  , InitArray\n  , FiniArray\n  , PreInitArray\n  , Group\n  , SymbolTableShIndex\n  , OsSpecific(u32)\n  , ProcessorSpecific(u32)\n  , User(u32)\n}\n\n/// Iterator over ELF64 sections\n#[derive(Clone,Debug)]\npub struct Sections<'a, W: 'a>\nwhere W: ElfWord { curr: &'a HeaderRepr<W>\n                 , remaining: u32\n                 , size: u32\n                 }\n\nimpl<'a, W: 'a> Sections<'a, W>\nwhere W: ElfWord {\n\n    pub fn new(curr: &'a HeaderRepr<W>, remaining: u32, size: u32)\n               -> Sections<'a, W>\n    {\n        Sections { curr: curr, remaining: remaining, size: size }\n\n    }\n\n}\n\n\nimpl<'a, W> Iterator for Sections<'a, W>\nwhere W: ElfWord\n    , HeaderRepr<W>: Header<Word = W> {\n    type Item = &'a Header<Word = W>;\n\n    fn next(&mut self) -> Option<Self::Item> {\n        if self.remaining == 0 {\n            None\n        } else {\n            let current = self.curr;\n            self.curr =  unsafe {\n                (self.curr as *const HeaderRepr<W>).offset(1)\n                    .as_ref()\n                    .expect(\"Expected an ELF section header, but got a null \\\n                             pointer!\\nThis shouldn't happen!\")\n            };\n            self.remaining -= 1;\n            if current.get_type().unwrap() == Type::Null {\n                self.next()\n            } else {\n                Some(current)\n            }\n        }\n    }\n}\n\n/// Characters in the ELF string table are 8-bit ASCII characters.\ntype ElfChar = u8;\n\n/// An ELF string table.\n///\n/// Refer to the String Table [entry] in Section 4 of the ELF standard\n/// for more information.\n///\n/// [entry]: http://www.sco.com/developers/gabi/latest/ch4.strtab.html\n//  TODO: this should be indexable by string number, possibly?\n//          - eliza, 03/07/2017\n//  TODO: add a function to get the name of the section (which always lives)\n//        at index 0.\n//          - eliza, 03/07/2017\n#[derive(Clone, Debug)]\npub struct StrTable<'a>(&'a [ElfChar]);\n\nimpl<'a> convert::From<&'a [ElfChar]> for StrTable<'a> {\n    #[inline(always)]\n    fn from(binary: &'a [ElfChar]) -> Self { StrTable(binary) }\n}\n\nimpl<'a> StrTable<'a> {\n\n    /// Returns the string at a given index in the string table,\n    /// if there is one.\n    // TODO: these docs are Bad\n    //          - eliza, 03/07/2017\n    // TODO: this def. shouldn't be u64, but i didn't want to annotate the\n    //       string table type with ElfWord...figure this out\n    //          - eliza, 03/07/2017\n    // TODO: can this be replaced with an ops::Index implementation?\n    //       but then we can't implement Deref to a slice any more?\n    //          - eliza, 03/07/2017\n    pub fn at_index(&'a self, i: usize) -> Option<&'a str> {\n        use core::str::from_utf8_unchecked;\n        if i <= self.len() {\n            read_to_null(&self[i..])\n                .map(|bytes| unsafe {\n                    // TODO: should this be checked, or do we assume the ELF\n                    //       binary has only well-formed strings? this could be\n                    //       a Security Thing...\n                    //          - eliza, 03/07/2017\n                    from_utf8_unchecked(bytes)\n                    // TODO: can the conversion to a Rust string be moved to\n                    //       `read_to_null()`? we also do this in the iterator\n                    //          - eliza, 03/07/2017\n                })\n\n        } else {\n            None\n        }\n    }\n}\n\n// impl<'a> StrTable<'a> {\n//     #[inline] fn len(&self) -> usize { self.0.len}\n//\n// }\nimpl<'a> ops::Deref for StrTable<'a> {\n    type Target = [ElfChar];\n\n    #[inline] fn deref(&self) -> &Self::Target { self.0 }\n}\n\nimpl<'a> IntoIterator for StrTable<'a> {\n    type IntoIter = Strings<'a>;\n    type Item = &'a str;\n\n    //  TODO: this doesn't strictly need to consume the StringTable...\n    //          - eliza, 03/07/2017\n    #[inline] fn into_iter(self) -> Self::IntoIter { Strings(&self.0) }\n}\n\n/// Returns true if `ch` is the null-terminator character\n#[inline] fn is_null(ch: &ElfChar) -> bool { *ch == b'\\0' }\n\n/// Read a series of bytes from a slice to the first null-terminator\n//  TODO: can this be moved to the StrTable type? no big deal but it would be\n//        somewhat prettier...\n//          - eliza, 03/07/2017\n#[inline] fn read_to_null<'a>(bytes: &'a [ElfChar]) -> Option<&'a [ElfChar]> {\n    bytes.iter().position(is_null)\n         .map(|i| &bytes[..i] )\n}\n\n/// Iterator over the strings in an ELF string table\n#[derive(Clone, Debug)]\npub struct Strings<'a>(&'a [ElfChar]);\n\nimpl<'a> Iterator for Strings<'a> {\n    type Item = &'a str;\n\n    fn next(&mut self) -> Option<Self::Item> {\n        use core::str::from_utf8_unchecked;\n        if self.0.len() == 0 {\n            // if there are no bytes remaining in the iterator, then we've\n            // iterated over all the strings in the string table (or it was\n            // empty to begin with).\n            //\n            // N.B. that `read_to_null()` _will_ return None in this case, so\n            // this check isn't strictly necessary; it just saves us from\n            // having to create an iterator if the slice is empty, so I'm\n            // calling it an \"optimisation\".\n            None\n        } else {\n            // otherwise, try to read the iterator's slice to the first null\n            // character...\n            read_to_null(self.0).map(|bytes| {\n                // ...if we found a null character, remove the string's bytes\n                // from the slice in the iterator (since we're returning that\n                // string), and return a string slice containing those bytes\n                // interpreted as UTF-8 (which should be equivalent to ASCII)\n                self.0 = &self.0[bytes.len() + 1..];\n                unsafe {\n                    // TODO: should this be checked, or do we assume the ELF\n                    //       binary has only well-formed strings? this could be\n                    //       a Security Thing...\n                    //          - eliza, 03/07/2017\n                    from_utf8_unchecked(bytes)\n                }\n            })\n        }\n    }\n\n    #[inline] fn size_hint(&self) -> (usize, Option<usize>) {\n        (0, Some(self.0.len() / 2))\n    }\n}\n"
  },
  {
    "path": "memory/Cargo.toml",
    "content": "[package]\nname = \"memory\"\nversion = \"0.0.1\"\nauthors = [ \"Eliza Weisman <eliza@elizas.website>\" ]\n\n[profile.dev]\nopt-level = 3\ndebug = true\nrpath = false\nlto = false\ndebug-assertions = true\ncodegen-units = 1\npanic = \"abort\"\n\n[profile.release]\nopt-level = 3\ndebug = true\nrpath = false\nlto = false\npanic = \"abort\"\n\n[dependencies]\nutil = { path = \"../util\" }\nbitflags = \"0.7\"\nspin = \"0.4.6\"\n\n[dependencies.vga]\npath = \"../vga\"\nfeatures = [\"kinfo\"]\n\n[dependencies.lazy_static]\nversion = \"^0.2.11\"\nfeatures = [\"spin_no_std\"]\n\n[dependencies.macro-attr]\ngit = \"https://github.com/DanielKeep/rust-custom-derive.git\"\nversion = \"0.2.1\"\ndefault-features = false\n\n# [dependencies.newtype_derive]\n# version = \"0.1.6\"\n# default-features = false\n\n[dependencies.log]\nversion = \"^0.3.6\"\ndefault-features = false\nfeatures = [\"release_max_level_info\"]\n"
  },
  {
    "path": "memory/src/arch/mod.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza Weisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\n// 64-bit x86_64 (long mode)\n#[cfg(target_arch=\"x86_64\")] mod x86_64;\n#[cfg(target_arch=\"x86_64\")] pub use self::x86_64::*;\n\n// 32-bit x86 (protected mode)\n// TODO: NYI\n#[cfg(target_arch = \"x86\")] mod x86;\n#[cfg(target_arch = \"x86\")] pub use self::x86::*;\n"
  },
  {
    "path": "memory/src/arch/x86/mod.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza Weisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\nuse ::memory::VAddr;\n\n/// A physical (linear) memory address is a 32-bit unsigned integer\n#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]\npub struct PAddr(u32);\n\nimpl Addr<u32> for PAddr { }\nimpl_addr! { PAddr, u32 }\n\nimpl convert::Into<u32> for PAddr {\n    #[inline] fn into(self) -> u32 { self.as_u32() }\n}\n\nimpl convert::From<u32> for PAddr {\n    #[inline] fn from(u: u32) -> Self { PAddr::from_u32(u) }\n}\n\nimpl convert::From<*mut u8> for PAddr {\n    #[inline] fn from(ptr: *mut u8) -> Self { PAddr::from_ptr(ptr) }\n}\n\nimpl PAddr {\n    #[inline] pub fn from_ptr(ptr: *mut u8) -> Self { PAddr(ptr as u32) }\n    #[inline] pub const fn from_u32(u: u32) -> Self { PAddr(u) }\n    #[inline] pub const fn as_u32(&self) -> u32 { self.0 }\n}\n"
  },
  {
    "path": "memory/src/arch/x86_64/mod.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza Weisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\n//! Architecture-specific memory management.\nuse ::{Addr, Page};\n\nuse core::{fmt, ops, mem};\n\npub const PAGE_SHIFT: u8 = 12;\n/// The size of a page (4KiB), in bytes\npub const PAGE_SIZE: u64 = 1 << PAGE_SHIFT; // 4k\n/// The size of a large page (2MiB) in bytes\npub const LARGE_PAGE_SIZE: u64 = 1024 * 1024 * 2;\n/// The size of a huge page (2GiB) in bytes\npub const HUGE_PAGE_SIZE: u64 = 1024 * 1024 * 1024;\n\n\nmacro_attr! {\n    /// A physical (linear) memory address is a 64-bit unsigned integer\n    #[derive(Copy, Clone, Eq, Ord, PartialEq, PartialOrd, Addr!(u64, 'P'))]\n    #[repr(C)]\n    pub struct PAddr(u64);\n}\n\nmacro_attr! {\n    /// A frame (physical page)\n    //  TODO: consider renaming this to `Frame` (less typing)?\n    //      - eliza, 2/28/2017\n    #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Page!(PAddr) )]\n    pub struct PhysicalPage { pub number: u64 }\n}\nimpl fmt::Debug for PhysicalPage {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        write!(f, \"frame #{} at {:#p}\", self.number, self.base_addr())\n    }\n}\n\nimpl ops::Add<usize> for PhysicalPage {\n    type Output = Self;\n\n    #[inline] fn add(self, rhs: usize) -> Self {\n        PhysicalPage { number: self.number +  rhs as u64 }\n    }\n}\n\nimpl ops::Sub<usize> for PhysicalPage {\n    type Output = Self;\n\n    #[inline] fn sub(self, rhs: usize) -> Self {\n        PhysicalPage { number: self.number -  rhs as u64 }\n    }\n}\n\nimpl ops::AddAssign<usize> for PhysicalPage {\n    #[inline] fn add_assign(&mut self, rhs: usize) {\n        self.number += rhs as u64;\n    }\n}\n\nimpl ops::SubAssign<usize> for PhysicalPage {\n    #[inline] fn sub_assign(&mut self, rhs: usize) {\n        self.number -= rhs as u64;\n    }\n}\n\nimpl PhysicalPage {\n\n    /// Returns the physical address where this frame starts.\n    #[inline]\n    pub const fn base_addr(&self) -> PAddr {\n        PAddr(self.number << PAGE_SHIFT)\n    }\n\n    /// Returns a new frame containing `addr`\n    #[inline]\n    pub const fn containing_addr(addr: PAddr) -> PhysicalPage {\n        PhysicalPage { number: addr.0 >> PAGE_SHIFT }\n    }\n\n    /// Convert the frame into a raw pointer to the frame's base address\n    #[inline]\n    pub unsafe fn as_ptr<T>(&self) -> *const T {\n        mem::transmute(self.base_addr())\n    }\n\n    /// Convert the frame into a raw mutable pointer to the frame's base address\n    #[inline]\n    pub unsafe fn as_mut_ptr<T>(&self) -> *mut T {\n        *self.base_addr() as *mut u8 as *mut T\n    }\n\n}\n"
  },
  {
    "path": "memory/src/lib.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2016 Eliza Weisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\n\n//! Kernel memory management.\n//!\n//! This module contains all of the non-arch-specific paging code, and\n//! re-exports memory-related definitions.\n#![crate_name = \"memory\"]\n#![feature(const_fn)]\n#![feature(asm)]\n#![feature(step_trait)]\n#![feature(linkage)]\n#![no_std]\n\n#[macro_use] extern crate macro_attr;\n#[macro_use] extern crate util;\n// #[cfg(not(test))] #[macro_use] extern crate vga;\n// extern crate alloc as liballoc; // TODO: workaround\n\n#[macro_use] pub mod macros;\npub mod arch;\n\n// use alloc::buddy;\n// use ::params::InitParams;\nuse core::{ops, cmp, convert, fmt};\nuse util::Align;\n\npub use arch::{PAddr, PAGE_SHIFT, PAGE_SIZE};\n\n/// Trait representing an address, whether physical or virtual.\npub trait Addr: ops::Add<Self> + ops::Sub<Self>\n              + ops::Mul<Self> + ops::Div<Self>\n              + ops::Shl<Self> + ops::Shr<Self>\n              + ops::BitOr<Self> + ops::BitAnd<Self>\n              + convert::From<*mut u8> + convert::From<*const u8>\n              + Sized {\n    type Repr: Align;\n\n    fn align_down(&self, align: Self::Repr) -> Self;\n    fn align_up(&self, align: Self::Repr) -> Self;\n\n    /// Returns true if this address is aligned on a page boundary.\n    fn is_page_aligned(&self) -> bool;\n}\n\n//impl Addr<usize> for VAddr { }\n\n//impl_addr! { VAddr, usize }\n\nmacro_attr! {\n    /// A virtual address is a machine-sized unsigned integer\n    #[derive(Copy, Clone, Eq, Ord, PartialEq, PartialOrd, Addr!(usize, 'V'))]\n    pub struct VAddr(usize);\n}\n\nimpl VAddr {\n    /// Convert this virtual address to a pointer\n    #[inline] pub fn from_ptr<T>(ptr: *mut T) -> Self { VAddr(ptr as usize) }\n\n    /// Convert a `usize` to a virtual address\n    #[inline] pub const fn from_usize(u: usize) -> Self { VAddr(u) }\n\n    /// Convert this virtual address to a `usize`.\n    #[inline] pub const fn as_usize(&self) -> usize { self.0 }\n\n    /// Calculate the index in the PML4 table corresponding to this address.\n    #[inline] pub fn pml4_index(&self) -> usize {\n        *((self >> 39) & 0b111111111 as usize)\n    }\n\n    /// Calculate the index in the PDPT table corresponding to this address.\n    #[inline] pub fn pdpt_index(&self) -> usize {\n        *((self >> 30) & 0b111111111)\n    }\n\n    /// Calculate the index in the PD table corresponding to this address.\n    #[inline] pub fn pd_index(&self) -> usize {\n        *((self >> 21) & 0b111111111)\n    }\n\n    /// Calculate the index in the PT table corresponding to this address.\n    #[inline] pub fn pt_index(&self) -> usize {\n        *((self >> 12) & 0b111111111)\n    }\n}\n\nuse core::ops::Range;\n\npub use arch::PhysicalPage;\n\npub type PageRange = Range<VirtualPage>;\npub type FrameRange = Range<PhysicalPage>;\n\n\n/// Trait for a page. These can be virtual pages or physical frames.\npub trait Page\nwhere Self: Sized\n    , Self: ops::AddAssign<usize> + ops::SubAssign<usize>\n    , Self: ops::Add<usize, Output=Self> + ops::Sub<usize, Output=Self>\n    , Self: cmp::PartialEq<Self> + cmp::PartialOrd<Self>\n    , Self: Copy + Clone {\n\n    /// The type of address used to address this `Page`.\n    ///\n    /// Typically, this is a `PAddr` or `VAddr` (but it could be a \"MAddr\")\n    /// in schemes where we differentiate between physical and machine\n    /// addresses. If we ever have those.\n    type Address: Addr;\n\n    /// Returns a new `Page` containing the given `Address`.\n    ///\n    /// N.B. that since trait functions cannot be `const`, implementors of\n    /// this trait may wish to provide implementations of this function\n    /// outside of the `impl` block and then wrap them here.\n    fn containing(addr: Self::Address) -> Self;\n\n    /// Returns the base `Address` where this page starts.\n    fn base(&self) -> Self::Address;\n\n    /// Returns the end `Address` of this `Page`.\n    fn end_address(&self) -> Self::Address;\n\n    ///// Convert the frame into a raw pointer to the frame's base address\n    //#[inline]\n    //unsafe fn as_ptr<T>(&self) -> *const T {\n    //    mem::transmute(self.base())\n    //}\n    //\n    ///// Convert the frame into a raw mutable pointer to the frame's base address\n    //#[inline]\n    //unsafe fn as_mut_ptr<T>(&self) -> *mut T {\n    //    mem::transmute(self.base())\n    //}\n\n    /// Returns a `PageRange` of this `Page` and the next `n` pages.\n    #[inline]\n    fn range_of(&self, n: usize) -> Range<Self> {\n        self.range_until(*self + n)\n    }\n\n    /// Returns a `PageRange` on the frames from this frame until the end frame\n    #[inline]\n    fn range_until(&self, end: Self) -> Range<Self> {\n        Range { start: *self, end: end }\n    }\n\n    fn number(&self) -> usize;\n\n}\n\n\nmacro_attr!{\n    /// A virtual page\n    #[derive( Copy, Clone, Eq, Ord, PartialEq, PartialOrd, Page!(VAddr) )]\n    pub struct VirtualPage { pub number: usize }\n}\n\nimpl VirtualPage {\n    fn containing_addr( addr: VAddr) -> Self {\n        use ::PAGE_SHIFT;\n        assert!( (addr < 0x0000_8000_0000_0000) || (addr >= 0xffff_8000_0000_0000)\n               , \"invalid address : 0x{:x}\", addr );\n        Self { number: addr.0 >> PAGE_SHIFT }\n    }\n}\n\nimpl fmt::Debug for VirtualPage {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        write!(f, \"page #{}\", self.number)\n    }\n}\n\n//\n///// A range of `Page`s.\n//#[derive(Copy, Clone, Debug, Eq, PartialEq)]\n//pub struct Range<P>\n//where P: Page { start: P, end: P }\n//\npub trait MemRange {\n    /// Returns the number of `Page`s in this ranage\n    #[inline]\n    fn length(&self) -> usize;\n\n    /// Remove `n` pages from the beginning of this `PageRange`\n    fn drop_front(&mut self, n: usize) -> &mut Self;\n\n    /// Remove `n` pages from the end of this `PageRange`\n    fn drop_back(&mut self, n: usize) -> &mut Self;\n\n    /// Add `n` pages at the front of this `PageRange`\n    fn add_front(&mut self, n: usize) -> &mut Self;\n\n    /// Add `n` pages at the back of this `PageRange`\n    fn add_back(&mut self, n: usize) -> &mut Self;\n}\n    //pub const fn start(&self) -> P { self.start }\n   //\n   ///// Returns a `PageRange` between two pages\n   //pub const fn between(start: P, end: P) -> Range<P> {\n   //    Range { start: start, end: end }\n   //}\n   //\n   // /// Returns an iterator over this `PageRange`\n   // pub fn iter<'a>(&'a self) -> RangeIter<'a, P> {\n   //     RangeIter { range: self, current: self.start.clone() }\n   // }\n\nimpl<P> MemRange for Range<P>\nwhere P: Page {\n\n    /// Returns the number of `Page`s in this ranage\n    #[inline]\n    fn length(&self) -> usize {\n        self.end.number() - self.start.number()\n    }\n\n    /// Remove `n` pages from the beginning of this `PageRange`\n    fn drop_front(&mut self, n: usize) -> &mut Self {\n        assert!(n < self.length());\n        self.start += n;\n        self\n    }\n\n    /// Remove `n` pages from the end of this `PageRange`\n    fn drop_back(&mut self, n: usize) -> &mut Self {\n        assert!(n < self.length());\n        self.end -= n;\n        self\n    }\n\n    /// Add `n` pages at the front of this `PageRange`\n    fn add_front(&mut self, n: usize) -> &mut Self {\n        self.start -= n;\n        self\n    }\n\n    /// Add `n` pages at the back of this `PageRange`\n    fn add_back(&mut self, n: usize) -> &mut Self {\n        self.end += n;\n        self\n    }\n}\n\n/// An iterator over a range of pages\npub struct RangeIter<'a, P>\nwhere P: Page\n    , P: 'a { range: &'a Range<P>, current: P }\n\nimpl<'a, P> Iterator for RangeIter<'a, P>\nwhere P: Page\n    , P: Clone {\n    type Item = P;\n\n    fn next(&mut self) -> Option<P> {\n        let end = self.range.end;\n      assert!(self.range.start <= end);\n      if self.current < end {\n          let page = self.current.clone();\n          self.current += 1;\n          Some(page)\n      } else {\n          None\n      }\n  }\n\n}\n"
  },
  {
    "path": "memory/src/macros.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza Weisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\n//! Macros to make our custom address types require a lot less repetitive code.\n#[macro_export]\nmacro_rules! Addr {\n    (($size:ty, $letter:expr) $(pub)* enum $name:ident $($tail:tt)*) => {\n        Addr! { @impl $name, $size, $letter }\n    };\n    (($size:ty, $letter:expr) $(pub)* struct $name:ident $($tail:tt)*) => {\n        Addr! { @impl $name, $size, $letter }\n    };\n    (@impl $ty:ident, $size:ty, $letter:expr) => {\n\n        impl ::core::fmt::Debug for $ty {\n            fn fmt(&self, f: &mut ::core::fmt::Formatter)\n                  -> ::core::fmt::Result {\n                write!(f, \"{}x{:x}\", $letter, self.0)\n            }\n        }\n\n        impl ::core::fmt::Pointer for $ty {\n            #[inline] fn fmt(&self, f: &mut ::core::fmt::Formatter)\n                  -> ::core::fmt::Result {\n                write!(f, \"{:?}\", self)\n            }\n        }\n\n        impl ::core::convert::Into<$size> for $ty {\n            #[inline] fn into(self) -> $size { self.0 }\n        }\n\n        impl ::core::convert::From<$size> for $ty {\n            #[inline] fn from(n: $size) -> Self { $ty(n) }\n        }\n\n        impl<T> ::core::convert::From<*mut T> for $ty {\n            #[inline] fn from(ptr: *mut T) -> Self { $ty(ptr as $size) }\n        }\n\n        impl<T> ::core::convert::From<*const T> for $ty {\n            #[inline] fn from(ptr: *const T) -> Self { $ty(ptr as $size) }\n        }\n\n        impl ::core::ops::Deref for $ty {\n            type Target = $size;\n            #[inline] fn deref(&self) -> &Self::Target { &self.0 }\n        }\n\n        impl $ty {\n            #[inline(always)]\n            pub const fn as_mut_ptr<T>(&self) -> *mut T { self.0 as *mut _ }\n\n            #[inline(always)]\n            pub const fn as_ptr<T>(&self) -> *const T { self.0 as *const _ }\n\n            #[inline(always)]\n            pub const fn new(value: $size) -> Self { $ty(value) }\n\n\n        }\n\n        impl_ops! {\n            Add, add, + for $ty, $size\n            Sub, sub, - for $ty, $size\n            Div, div, / for $ty, $size\n            Mul, mul, * for $ty, $size\n            Shl, shl, >> for $ty, $size\n            Shr, shr, << for $ty, $size\n            Rem, rem, % for $ty, $size\n            BitAnd, bitand, & for $ty, $size\n            BitOr, bitor, | for $ty, $size\n            BitXor, bitxor, ^ for $ty, $size\n\n        }\n\n        impl_assign_ops! {\n            AddAssign, add_assign, += for $ty, $size\n            SubAssign, sub_assign, -= for $ty, $size\n            DivAssign, div_assign, /= for $ty, $size\n            MulAssign, mul_assign, *= for $ty, $size\n            ShlAssign, shl_assign, >>= for $ty, $size\n            ShrAssign, shr_assign, <<= for $ty, $size\n            RemAssign, rem_assign, %= for $ty, $size\n            BitAndAssign, bitand_assign, &= for $ty, $size\n            BitOrAssign, bitor_assign, |= for $ty, $size\n            BitXorAssign, bitxor_assign, ^= for $ty, $size\n        }\n\n        impl_fmt! {\n            Binary for $ty\n            Display for $ty\n            Octal for $ty\n            LowerHex for $ty\n            UpperHex for $ty\n        }\n\n        impl ::core::cmp::PartialEq<$size> for $ty {\n            #[inline] fn eq(&self, rhs: &$size) -> bool {\n                self.0 == *rhs\n            }\n        }\n\n        impl ::core::cmp::PartialOrd<$size> for $ty {\n            #[inline]\n            fn partial_cmp(&self, rhs: &$size) -> Option<::core::cmp::Ordering> {\n                self.0.partial_cmp(rhs)\n            }\n        }\n\n        impl Addr for $ty {\n            type Repr = $size;\n\n            #[inline] fn align_down(&self, align: Self::Repr) -> Self {\n                use util::Align;\n                $ty ( self.0.align_down(align) )\n            }\n\n            #[inline] fn align_up(&self, align: Self::Repr) -> Self {\n                use util::Align;\n                // assert!(align.is_page_aligned());\n                $ty ( self.0.align_up(align) )\n            }\n\n            #[inline] fn is_page_aligned(&self) -> bool {\n                **self % PAGE_SIZE as <Self as Addr>::Repr == 0 as <Self as Addr>::Repr\n            }\n        }\n\n    }\n}\n\n\n\nmacro_rules! impl_page_ops {\n    ($($name:ident, $fun:ident, $op:tt for $ty:ident, $size:ty)*) => {$(\n        impl ::core::ops::$name<$ty> for $ty {\n            type Output = Self;\n\n            #[inline] fn $fun(self, rhs: $ty) -> Self {\n                expr!( $ty { number: expr!(self.number $op rhs.number) })\n            }\n        }\n        impl ::core::ops::$name<$size> for $ty {\n            type Output = $ty;\n\n            #[inline] fn $fun(self, rhs: $size) -> Self {\n                expr!($ty{ number: expr!(self.number $op rhs) })\n            }\n        }\n\n        forward_ref_binop! {\n            $name, $fun for $ty, $ty\n        }\n        forward_ref_binop! {\n            $name, $fun for $ty, $size\n        }\n    )*}\n}\n\nmacro_rules! impl_page_assign_ops {\n    ($($name:ident, $fun:ident, $op:tt for $ty:ident, $size:ty)*) => {$(\n        impl ::core::ops::$name<$ty> for $ty {\n\n            #[inline] fn $fun(&mut self, rhs: $ty) {\n                expr!(self.number $op rhs.number);\n            }\n        }\n        impl ::core::ops::$name<$size> for $ty {\n\n            #[inline] fn $fun(&mut self, rhs: $size) {\n                expr!(self.number $op rhs);\n            }\n        }\n    )*}\n}\n\n\n\nmacro_rules! Page {\n    (($addr:ty) $(pub)* struct $name:ident $($tail:tt)*) => {\n        Page! { @impl $name, $addr }\n    };\n    (@impl $ty:ident, $addr:ty) => {\n\n        impl Page for $ty {\n            type Address = $addr;\n\n\n            /// Create a new `Page` containing the given address.\n            //  TODO: rewrite this as `up`/`down` using the page shift, instead.\n            #[inline(always)]\n            fn containing(addr: $addr) -> Self {\n                $ty::containing_addr(addr)\n            }\n            /// Return the start address of this page\n            #[inline]\n            fn base(&self) -> $addr {\n                Self::Address::from(\n                    self.number << PAGE_SHIFT as <Self::Address as Addr>::Repr )\n            }\n\n            /// Return the end address of this page\n            #[inline]\n            fn end_address(&self) -> $addr {\n                self.base() + PAGE_SIZE as <Self::Address as Addr>::Repr\n            }\n\n            #[inline] fn number(&self) -> usize {\n                self.number as usize\n            }\n        }\n\n        // impl ::core::num::One for $ty {\n        //     #[inline] fn one() -> Self {\n        //         $ty { number:\n        //             <<$addr as Addr>::Repr as ::core::num::One>::one()\n        //         }\n        //     }\n        // }\n\n        impl ::core::iter::Step for $ty {\n            #[inline]\n            fn add_usize(&self, n: usize) -> Option<Self> {\n                self.number\n                    .add_usize(n)\n                    .map(|s| $ty { number: s})\n            }\n\n            #[inline]\n            #[allow(trivial_numeric_casts)]\n            fn steps_between(start: &$ty, end: &$ty) -> Option<usize> {\n                use ::core::iter::Step;\n                <<$addr as Addr>::Repr as Step>::steps_between( &start.number\n                                                              , &end.number\n                                                              )\n            }\n\n            #[inline] fn sub_one(&self) -> Self { self - 1 }\n\n            #[inline] fn add_one(&self) -> Self { self + 1 }\n\n            #[inline] fn replace_one(&mut self) -> Self { unimplemented!() }\n\n            #[inline] fn replace_zero(&mut self) -> Self { unimplemented!() }\n\n        }\n\n        impl<A> ::core::convert::From<A> for $ty\n        where <Self as Page>::Address: ::core::convert::From<A> {\n            #[inline] fn from(addr: A) -> Self {\n                $ty::containing(<Self as Page>::Address::from(addr))\n            }\n        }\n\n        impl_page_ops! {\n            Add, add, + for $ty, <<$ty as Page>::Address as Addr>::Repr\n            Sub, sub, - for $ty, <<$ty as Page>::Address as Addr>::Repr\n            Div, div, / for $ty, <<$ty as Page>::Address as Addr>::Repr\n            Mul, mul, * for $ty, <<$ty as Page>::Address as Addr>::Repr\n            Shl, shl, >> for $ty,<<$ty as Page>::Address as Addr>::Repr\n            Shr, shr, << for $ty, <<$ty as Page>::Address as Addr>::Repr\n            Rem, rem, % for $ty, <<$ty as Page>::Address as Addr>::Repr\n            BitAnd, bitand, & for $ty, <<$ty as Page>::Address as Addr>::Repr\n            BitOr, bitor, | for $ty, <<$ty as Page>::Address as Addr>::Repr\n            BitXor, bitxor, ^ for $ty, <<$ty as Page>::Address as Addr>::Repr\n\n        }\n\n        impl_page_assign_ops! {\n            AddAssign, add_assign, += for $ty, <<$ty as Page>::Address as Addr>::Repr\n            SubAssign, sub_assign, -= for $ty, <<$ty as Page>::Address as Addr>::Repr\n            DivAssign, div_assign, /= for $ty, <<$ty as Page>::Address as Addr>::Repr\n            MulAssign, mul_assign, *= for $ty, <<$ty as Page>::Address as Addr>::Repr\n            ShlAssign, shl_assign, >>= for $ty, <<$ty as Page>::Address as Addr>::Repr\n            ShrAssign, shr_assign, <<= for $ty, <<$ty as Page>::Address as Addr>::Repr\n            RemAssign, rem_assign, %= for $ty, <<$ty as Page>::Address as Addr>::Repr\n            BitAndAssign, bitand_assign, &= for $ty, <<$ty as Page>::Address as Addr>::Repr\n            BitOrAssign, bitor_assign, |= for $ty, <<$ty as Page>::Address as Addr>::Repr\n            BitXorAssign, bitxor_assign, ^= for $ty, <<$ty as Page>::Address as Addr>::Repr\n        }\n    }\n}\n"
  },
  {
    "path": "paging/Cargo.toml",
    "content": "[package]\nname = \"paging\"\nversion = \"0.0.1\"\nauthors = [ \"Eliza Weisman <hi@hawkweisman.me>\" ]\n\n[profile.dev]\nopt-level = 3\ndebug = true\nrpath = false\nlto = false\ndebug-assertions = true\ncodegen-units = 1\npanic = \"abort\"\n\n[profile.release]\nopt-level = 3\ndebug = true\nrpath = false\nlto = false\npanic = \"abort\"\n\n[dependencies]\nutil = { path = \"../util\" }\nmemory = { path = \"../memory\" }\nsos_alloc = { path = \"../sos_alloc\" }\nelf = { path = \"../elf\" }\ncpu = { path = \"../cpu\" }\nparams = { path = \"../params\" }\nbitflags = \"0.7\"\nspin = \"0.4.6\"\n\n[dependencies.vga]\npath = \"../vga\"\nfeatures = [\"kinfo\"]\n\n[dependencies.lazy_static]\nversion = \"0.2.11\"\nfeatures = [\"spin_no_std\"]\n\n[dependencies.macro-attr]\ngit = \"https://github.com/DanielKeep/rust-custom-derive.git\"\nversion = \"0.2.1\"\ndefault-features = false\n\n# [dependencies.newtype_derive]\n# version = \"0.1.6\"\n# default-features = false\n\n[dependencies.log]\nversion = \"0.3.6\"\ndefault-features = false\nfeatures = [\"release_max_level_info\"]\n"
  },
  {
    "path": "paging/src/arch/mod.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (hi@hawkweisman.me)\n//\n//  Copyright (c) 2015-2016 Eliza Weisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\n// 64-bit x86_64 (long mode)\n#[cfg(target_arch=\"x86_64\")] mod x86_64;\n#[cfg(target_arch=\"x86_64\")] pub use self::x86_64::*;\n\n// 32-bit x86 (protected mode)\n// TODO: NYI\n#[cfg(target_arch = \"x86\")] mod x86;\n#[cfg(target_arch = \"x86\")] pub use self::x86::*;\n"
  },
  {
    "path": "paging/src/arch/x86_64/cr3.rs",
    "content": "use super::table::{Table, PML4Level};\nuse cpu::control_regs::cr3::{read, write};\npub use cpu::control_regs::cr3::*;\n\n/// Returns the current Page Meta-Level 4 table\n///\n/// # Safety\n/// + Reading from control registers while not in kernel mode will cause\n///   a general protection fault.\n/// + Returns a `*mut` pointer with an arbitrary lifetime.\n#[cfg(target_arch = \"x86_64\")]\n#[inline]\npub unsafe fn current_pml4() -> *mut Table<PML4Level> {\n    read().as_mut_ptr::<Table<PML4Level>>()\n}\n\n/// Sets the current Page Meta-Level 4 Table\n///\n/// # Safety\n/// + Control registers should generally not be modified during normal\n///   operation.\n#[cfg(target_arch = \"x86_64\")]\npub unsafe fn set_pml4(pml4: Table<PML4Level>) {\n    write(pml4.frame().base_addr())\n}\n"
  },
  {
    "path": "paging/src/arch/x86_64/mod.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (hi@hawkweisman.me)\n//\n//  Copyright (c) 2015-2016 Eliza Weisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\n//! Paging\n//!\n//! The `x86_64` architecture uses a four-level page table structure. The top\n//! page table is called the Page Meta-Level 4 (PML4) table, followed by\n//! the Page Directory Pointer Table (PDPT), Page Directory (PD) table, and\n//! finally the bottom-level Page Table (PT).\nuse core::{fmt, ops};\nuse core::ptr::Unique;\n\nuse alloc::FrameAllocator;\nuse memory::{Addr, PAGE_SIZE, PAddr, Page, PhysicalPage, VAddr, VirtualPage};\nuse params::InitParams;\nuse ::{Mapper, MapResult, MapErr};\n\nuse self::table::*;\nuse self::temp::TempPage;\n\npub mod table;\npub mod tlb;\npub mod temp;\npub mod cr3;\n#[derive(Debug)]\npub struct ActivePageTable { pml4: ActivePML4 }\n\nimpl ops::Deref for ActivePageTable {\n    type Target = ActivePML4;\n\n    fn deref(&self) -> &ActivePML4 {\n        &self.pml4\n    }\n}\n\nimpl ops::DerefMut for ActivePageTable {\n    fn deref_mut(&mut self) -> &mut ActivePML4 {\n        &mut self.pml4\n    }\n}\n\nimpl ActivePageTable {\n    pub unsafe fn new() -> ActivePageTable {\n        ActivePageTable { pml4: ActivePML4::new() }\n    }\n\n    /// Execute a closure with the recursive mapping temporarily changed to a\n    /// new page table\n    pub fn using<F>( &mut self\n                   , table: &mut InactivePageTable\n                   , temp_page: &mut temp::TempPage\n                   , f: F)\n                   -> MapResult\n    where F: FnOnce(&mut ActivePML4) -> MapResult {\n        let result: MapResult;\n        use self::tlb::flush_all;\n        {\n            // back up the current PML4 frame\n            let prev_pml4_frame = unsafe {\n                // this is safe to execute; we are in kernel mode\n                cr3::current_pagetable_frame()\n            };\n\n            // map temporary_page to current p4 table\n            let pml4 = temp_page.map_to_table(prev_pml4_frame.clone(), self)?;\n\n            // remap the 511th PML4 entry (the recursive entry) to map to the // frame containing the new PML4.\n            self.pml4_mut()[511].set(table.pml4_frame, PRESENT | WRITABLE);\n            unsafe {\n                // this is safe to execute; we are in kernel mode\n                flush_all();\n            }\n\n            // execute the closure\n            result = f(self);\n\n            // remap the 511th entry to point back to the original frame\n            pml4[511].set(prev_pml4_frame, PRESENT | WRITABLE);\n\n            unsafe {\n                // this is safe to execute; we are in kernel mode\n                flush_all();\n            }\n        }\n        let _ = temp_page.unmap(self)?;\n        return result\n\n    }\n\n    /// Replace the current `ActivePageTable` with the given `InactivePageTable`\n    ///\n    /// # Arguments\n    /// + `new_table`: the `InactivePageTable` that will replace the current\n    ///                `ActivePageTable`.\n    ///\n    /// # Returns\n    /// + the old active page table as an `InactivePageTable`.\n    pub fn replace_with(&mut self, new_table: InactivePageTable)\n                       -> InactivePageTable {\n        unsafe {\n            trace!(\"replacing {:?} with {:?}\", self, new_table);\n            // this is safe to execute; we are in kernel mode\n            let old_pml4_frame = cr3::current_pagetable_frame();\n            trace!(\"current pml4 frame is {:?}\", old_pml4_frame);\n\n            cr3::set_pagetable_frame(new_table.pml4_frame);\n            trace!(\"set new pml4 frame to {:?}\", new_table.pml4_frame);\n\n            InactivePageTable {\n                pml4_frame: old_pml4_frame\n            }\n        }\n    }\n\n}\n\n/// Struct representing the currently active PML4 instance.\n///\n/// The `ActivePML4` is a `Unique` reference to a PML4-level page table. It's\n/// unique because, well, there can only be one active PML4 at a given time.\n///\npub struct ActivePML4(Unique<Table<PML4Level>>);\nimpl fmt::Debug for ActivePML4 {\n    #[inline]\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        write!(f, \"Active {:?}\", unsafe { self.0.as_ref() })\n    }\n}\n/// The active PML4 table is the single point of entry for page mapping.\nimpl Mapper for ActivePML4 {\n    type Flags = EntryFlags;\n\n    fn translate(&self, vaddr: VAddr) -> Option<PAddr> {\n        let offset = *vaddr % PAGE_SIZE as usize;\n        self.translate_page(Page::containing(vaddr))\n            .map(|frame| PAddr::from(frame.number + offset as u64) )\n    }\n\n    fn translate_page(&self, page: VirtualPage) -> Option<PhysicalPage> {\n        let pdpt = self.pml4().next_table(page);\n\n        let huge_page = || {\n            pdpt.and_then(|pdpt|\n                pdpt[page]\n                    .do_huge(PDLevel::index_of(page) + PTLevel::index_of(page))\n                    .or_else(|| {\n                        pdpt.next_table(page).and_then(|pd|\n                            pd[page].do_huge(PTLevel::index_of(page))\n                        )\n                    })\n                )\n        };\n\n        pdpt.and_then(|pdpt| pdpt.next_table(page))\n            .and_then(|pd| pd.next_table(page))\n            .and_then(|pt| pt[page].get_frame())\n            .or_else(huge_page)\n    }\n\n\n    /// Modifies the page tables so that `page` maps to `frame`.\n    ///\n    /// # Arguments\n    /// + `page`: the virtual `Page` to map\n    /// + `frame`: the physical `Frame` that `Page` should map to.\n    /// + `flags`: the page table entry flags.\n    /// + `alloc`: a memory allocator\n    fn map<A>( &mut self, page: VirtualPage, frame: PhysicalPage\n             , flags: EntryFlags, alloc: &mut A)\n             -> MapResult<()>\n    where A: FrameAllocator {\n        // base virtual address of page being mapped\n        // let addr = page.base();\n\n        // access or create all the lower-level page tables.\n        let mut page_table // get the PML4\n            = self.pml4_mut()\n                  // get or create the PDPT table at the page's PML4 index\n                  .create_next(page, alloc)\n                  // get or create the PD table at the page's PDPT index\n                  .and_then(|pdpt| pdpt.create_next(page, alloc))\n                  // get or create the page table at the  page's PD table index\n                  .and_then(|pd| pd.create_next(page, alloc))?;\n        trace!(\" . . Map: Got page table\");\n        // check if the page at that index is not currently in use, as we\n        // cannot map a page which is currently in use.\n        if page_table[page].is_unused() {\n            // set the page table entry at that index\n            page_table[page].set(frame, flags | table::PRESENT);\n            Ok(())\n        } else {\n            Err(MapErr::AlreadyInUse {\n                message: \"map frame\"\n              , page: page\n              , frame: frame\n            })\n        }\n    }\n\n    fn identity_map<A>(&mut self, frame: PhysicalPage, flags: EntryFlags\n                      , alloc: &mut A)\n                      -> MapResult<()>\n    where A: FrameAllocator {\n        self.map( Page::containing(VAddr::from(*frame.base_addr() as usize))\n                , frame\n                , flags\n                , alloc )\n    }\n\n    fn map_to_any<A>( &mut self\n                    , page: VirtualPage\n                    , flags: EntryFlags\n                    , alloc: &mut A)\n                    -> MapResult<()>\n    where A: FrameAllocator {\n        let frame = unsafe { alloc.allocate() }\n            .map_err(|err| MapErr::Alloc {\n                message: \"map to any\"\n              , page: page\n              , cause: err\n          })?;\n        self.map(page, frame, flags, alloc)\n    }\n\n    /// Unmap the given `VirtualPage`.\n    ///\n    /// All freed frames are returned to the given `FrameAllocator`.\n    fn unmap<A>(&mut self, page: VirtualPage, alloc: &mut A) -> MapResult<()>\n    where A: FrameAllocator {\n        use self::tlb::Flush;\n\n        // get the page table entry corresponding to the page.\n        let page_table = self.pml4_mut()\n                             .next_table_mut(page)\n                             .and_then(|pdpt| pdpt.next_table_mut(page))\n                             .and_then(|pd| pd.next_table_mut(page))\n                             .ok_or(MapErr::Other {\n                                message: \"unmap\"\n                              , page: page\n                              , cause: \"huge pages not supported\"\n                            })?;\n        // index the entry from the table\n        let entry = &mut page_table[page];\n        trace!(\"got page table entry for {:?}\", page);\n        // get the pointed frame for the page table entry.\n        let frame = entry.get_frame()\n                         .ok_or(MapErr::Other {\n                           message: \"unmap\"\n                         , page: page\n                         , cause: \"it was not mapped\"\n                       })?;\n        trace!(\"page table entry for {:?} points to {:?}\", page, frame);\n        // mark the page table entry as unused\n        entry.set_unused();\n        trace!(\"set page table entry for {:?} as unused\", page);\n        // deallocate the frame and flush the translation lookaside buffer\n        // this is safe because we're in kernel mode\n        unsafe { page.invlpg() };\n        trace!(\"flushed TLB\");\n        unsafe {\n            // this is hopefully safe because nobody else should be using an\n            // allocated page frame\n            alloc.deallocate(frame);\n            trace!(\"deallocated page {:?}\", frame);\n        }\n        // TODO: check if page tables containing the unmapped page are empty\n        //       and deallocate them too?\n        Ok(())\n    }\n\n}\n\nimpl ActivePML4 {\n\n    pub unsafe fn new() -> Self {\n        ActivePML4(Unique::new(PML4_PTR))\n    }\n\n    fn pml4(&self) -> &Table<PML4Level> {\n        unsafe { self.0.as_ref() }\n    }\n\n    fn pml4_mut(&mut self) -> &mut Table<PML4Level> {\n        unsafe { self.0.as_mut() }\n    }\n\n    /// Returns true if the given page is mapped.\n    #[inline]\n    pub fn is_mapped(&self, page: &VirtualPage) -> bool {\n         self.translate_page(*page).is_some()\n    }\n\n\n}\n\n/// An inactive page table that the CPU is not currently using\n#[derive(Debug)]\npub struct InactivePageTable {\n    pml4_frame: PhysicalPage\n}\n\nimpl InactivePageTable {\n    pub fn new( frame: PhysicalPage\n              , active_table: &mut ActivePageTable\n              , temp: &mut TempPage)\n              -> MapResult<Self> {\n        {\n            trace!(\"Mapping page {} to frame {}\", temp.number, frame.number);\n            let table = temp.map_to_table(frame.clone(), active_table)?;\n            trace!( \" . . . Mapped temp page to table frame .\");\n            table.zero();\n            trace!( \" . . . Zeroed inactive table frame.\");\n            table[511].set( frame.clone(), PRESENT | WRITABLE);\n            trace!(\" . . . Set active table to point to new inactive table.\")\n        }\n        let _ = temp.unmap(active_table)?;\n        trace!(\" . . Unmapped temp page.\");\n\n        Ok(InactivePageTable { pml4_frame: frame })\n    }\n}\n\npub fn test_paging<A>(alloc: &mut A) -> MapResult<()>\nwhere A: FrameAllocator {\n    info!(\"testing paging\");\n    // This testing code shamelessly stolen from Phil Oppermann.\n    let mut pml4 = unsafe { ActivePML4::new() };\n\n    // address 0 is mapped\n    trace!(\"Some = {:?}\", pml4.translate(VAddr::from(0)));\n     // second PT entry\n    trace!(\"Some = {:?}\", pml4.translate(VAddr::from(4096)));\n    // second PD entry\n    trace!(\"Some = {:?}\", pml4.translate(VAddr::from(512 * 4096)));\n    // 300th PD entry\n    trace!(\"Some = {:?}\", pml4.translate(VAddr::from(300 * 512 * 4096)));\n    // second PDPT entry\n    trace!(\"None = {:?}\", pml4.translate(VAddr::from(512 * 512 * 4096)));\n    // last mapped byte\n    trace!(\"Some = {:?}\", pml4.translate(VAddr::from(512 * 512 * 4096 - 1)));\n\n\n    let addr = VAddr::from(42 * 512 * 512 * 4096); // 42th PDPT entry\n    let page = VirtualPage::containing(addr);\n    let frame = unsafe { alloc.allocate().expect(\"no more frames\") };\n    trace!(\"None = {:?}, map to {:?}\",\n             pml4.translate(addr),\n             frame);\n    let _ = pml4.map(page, frame, EntryFlags::empty(), alloc)?;\n    trace!(\"Some = {:?}\", pml4.translate(addr));\n    trace!( \"next free frame: {:?}\"\n            , unsafe { alloc.allocate() });\n\n    //trace!(\"{:#x}\", *(Page::containing(addr).as_ptr()));\n\n    let _ = pml4.unmap(Page::containing(addr), alloc)?;\n    trace!(\"None = {:?}\", pml4.translate(addr));\n    Ok(())\n\n}\n\n/// Remaps the kernel using 4KiB pages.\npub fn kernel_remap<A>(params: &InitParams, alloc: &mut A)\n                       -> MapResult<ActivePageTable>\nwhere A: FrameAllocator {\n    use elf::Section;\n    // create a  temporary page for switching page tables\n    // page number chosen fairly arbitrarily.\n    const TEMP_PAGE_NUMBER: usize = 0xfacade;\n    let mut temp_page = TempPage::new(TEMP_PAGE_NUMBER, alloc);\n    trace!(\"Created temporary page.\");\n\n    // old and new page tables\n    let mut current_table = unsafe { ActivePageTable::new() };\n    trace!(\"Got current page table.\");\n\n    let mut new_table = unsafe {\n        InactivePageTable::new(\n             alloc.allocate()\n                  .map_err(|err| MapErr::Alloc {\n                      message: \"create the new page table\"\n                     , page: *temp_page\n                     , cause: err\n                 })?\n          , &mut current_table\n          , &mut temp_page\n      )?\n    };\n    kinfoln!(dots: \" . . \", \"Created new {:?}\", new_table);\n\n    // actually remap the kernel --------------------------------------------\n    current_table.using(&mut new_table, &mut temp_page, |pml4| {\n        // extract allocated ELF sections\n        let sections\n            = params.elf_sections()\n                    .filter(|s| s.is_allocated());\n\n        kinfoln!(dots: \" . . \", \"Remapping kernel ELF sections.\");\n\n        for section in sections { // remap ELF sections\n            attempt!(\n                if section.address().is_page_aligned() {\n                    let flags = EntryFlags::from(section);\n\n                    let start_frame = PhysicalPage::from(section.address());\n                    let end_frame = PhysicalPage::from(section.end_address());\n\n                    for frame in start_frame .. end_frame {\n                        let _ = pml4.identity_map(frame, flags, alloc)?;\n                    }\n                    Ok(())\n                } else {\n                    Err(MapErr::NoPage::<VirtualPage> {\n                        message: \"identity map section\"\n                      , cause: \"the start address was not page aligned\"\n                    })\n                } =>\n                      dots: \" . . . \",\n                      \"Identity mapping {}\", section );\n        }\n\n        // remap VGA buffer\n        let vga_buffer_frame = PhysicalPage::containing(PAddr::from(0xb8000));\n        attempt!( pml4.identity_map(vga_buffer_frame, WRITABLE, alloc) =>\n                  dots: \" . . \", \"Identity mapping VGA buffer\" );\n\n\n        // remap Multiboot info\n        kinfoln!( dots: \" . . \", \"Identity mapping multiboot info\" );\n        let multiboot_start = PhysicalPage::from(params.multiboot_start());\n        let multiboot_end = PhysicalPage::from(params.multiboot_end());\n\n        for frame in multiboot_start .. multiboot_end {\n            let _ = pml4.identity_map(frame, PRESENT, alloc)?;\n                // .expect(\"couldn't identity map Multiboot {:?}\", frame);\n        }\n        Ok(())\n    })?;\n\n    trace!(\"replacing old page table with new page table\");\n    // switch page tables ---------------------------------------------------\n    let old_table = current_table.replace_with(new_table);\n    kinfoln!(dots: \" . . \", \"Successfully switched to remapped page table!\");\n\n    // create guard page at the location of the old PML4 table\n    let old_pml4_vaddr = VAddr::from(*(old_table.pml4_frame.base()) as usize);\n    let old_pml4_page  = VirtualPage::containing(old_pml4_vaddr);\n    let _ = current_table.unmap(old_pml4_page, alloc)?;\n    trace!(\"Unmapped guard page at {:?}\", old_pml4_page.base());\n    Ok(current_table)\n}\n"
  },
  {
    "path": "paging/src/arch/x86_64/table.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (hi@hawkweisman.me)\n//\n//  Copyright (c) 2015-2017 Eliza Weisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\nuse alloc::FrameAllocator;\nuse ::elf;\nuse memory::{Addr, PAGE_SIZE, PAddr, Page, PhysicalPage, VAddr, VirtualPage};\n\nuse core::marker::PhantomData;\nuse core::ops::{Index, IndexMut};\nuse core::{convert, fmt, intrinsics};\n\nuse ::{ MapResult, MapErr};\n\n/// The number of entries in a page table.\npub const N_ENTRIES: usize = 512;\n/// Size of a page table (in bytes)\npub const PAGE_TABLE_SIZE: usize = N_ENTRIES * PAGE_SIZE as usize;\n\n/// Base virtual address of the PML4 table\npub const PML4_VADDR: u64 =  0xffffffff_fffff000;\n\n/// A pointer to the PML4 table\npub const PML4_PTR: *mut Table<PML4Level> = PML4_VADDR as *mut _;\n\n/// Mask to apply to a page table entry to isolate the flags\npub const ENTRY_FLAGS_MASK: u64 = (PAGE_SIZE as u64 - 1) as u64;\n\n/// A page table\n#[repr(C)]\npub struct Table<L>\nwhere L: TableLevel { /// The entries in the page table.\n                      entries: [Entry; N_ENTRIES]\n                    , _level_marker: PhantomData<L>\n                    }\n\nimpl<L:TableLevel> fmt::Debug for Table<L> {\n    #[inline]\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        write!(f, \"{} at {:#p}\"\n              , unsafe { intrinsics::type_name::<L>() }\n              , self)\n    }\n}\n// TODO: this can be moved to x86_all; it's the number of level traits that is\n//       x86-64 specific.\n//          - eliza, 5/29/2017\npub trait TableLevel {\n    /// How much to shift an address by to find its index in this table.\n    const ADDR_SHIFT_AMOUNT: usize;\n    /// How much to shift a page number by to find its index in this level table\n    const PAGE_SHIFT_AMOUNT: usize;\n    /// Mask for indices\n    const INDEX_MASK: usize = 0o777;\n\n}\n\npub trait IndexOf<I> {\n    fn index_of(i: I) -> usize;\n}\n\nimpl<T> IndexOf<VAddr> for T\nwhere T: TableLevel {\n\n    /// Returns the index in this table for the given virtual address\n    #[inline]\n    fn index_of(addr: VAddr) -> usize {\n        (addr.as_usize() >> Self::ADDR_SHIFT_AMOUNT) & Self::INDEX_MASK\n    }\n\n}\n\nimpl<T> IndexOf<VirtualPage> for T\nwhere T: TableLevel {\n    /// Returns the index in this table for the given virtual page\n    #[inline]\n    fn index_of(page: VirtualPage) -> usize {\n        (page.number >> Self::PAGE_SHIFT_AMOUNT) & Self::INDEX_MASK\n    }\n}\n\nimpl<T> IndexOf<usize> for T\nwhere T: TableLevel {\n    // lol\n    // i really hope that the compiler understands that this function does\n    // absolutely nothing...\n    #[inline(always)]\n    fn index_of(i: usize) -> usize { i }\n\n}\n\npub enum PML4Level {}\npub enum PDPTLevel {}\npub enum PDLevel   {}\npub enum PTLevel   {}\n\nimpl TableLevel for PML4Level {\n    // TODO: make sure these values are correct!\n    //          - eliza, 5/29/2017\n    const ADDR_SHIFT_AMOUNT: usize = 39;\n    const PAGE_SHIFT_AMOUNT: usize = 27;\n}\nimpl TableLevel for PDPTLevel {\n    const ADDR_SHIFT_AMOUNT: usize = 30;\n    const PAGE_SHIFT_AMOUNT: usize = 18;\n}\nimpl TableLevel for PDLevel   {\n    const ADDR_SHIFT_AMOUNT: usize = 21;\n    const PAGE_SHIFT_AMOUNT: usize = 9;\n}\nimpl TableLevel for PTLevel   {\n    const ADDR_SHIFT_AMOUNT: usize = 12;\n    const PAGE_SHIFT_AMOUNT: usize = 0;\n}\n\npub trait Sublevel: TableLevel {\n    type Next: TableLevel;\n}\nimpl Sublevel for PML4Level {\n    type Next = PDPTLevel;\n}\nimpl Sublevel for PDPTLevel {\n    type Next = PDLevel;\n}\nimpl Sublevel for PDLevel {\n    type Next = PTLevel;\n}\n\nimpl Table<PML4Level> {\n    #[inline]\n    pub fn page_table_for(&self, page: VirtualPage) -> Option<&Table<PTLevel>> {\n        self.next_table(page)\n            .and_then(|pdpt| pdpt.next_table(page))\n            .and_then(|pd| pd.next_table(page))\n    }\n\n    #[inline]\n    pub fn page_table_mut_for(&mut self, page: VirtualPage)\n                             -> Option<&mut Table<PTLevel>> {\n        self.next_table_mut(page)\n            .and_then(|pdpt| pdpt.next_table_mut(page))\n            .and_then(|pd| pd.next_table_mut(page))\n    }\n}\n\n\nimpl<L, I> Index<I> for Table<L>\nwhere L: TableLevel\n    , L: IndexOf<I> {\n    type Output = Entry;\n\n    #[inline] fn index(&self, i: I) -> &Entry {\n        &self.entries[L::index_of(i)]\n    }\n}\n\nimpl<L, I> IndexMut<I> for Table<L>\nwhere L: TableLevel\n    , L: IndexOf<I> {\n    #[inline] fn index_mut(&mut self, i: I) -> &mut Entry {\n        &mut self.entries[L::index_of(i)]\n    }\n}\n\n\nimpl<L: TableLevel> Table<L>  {\n\n    /// Zeroes out the page table by setting all entries \"unused\"\n    pub fn zero(&mut self) -> &mut Self {\n        trace!(\"zeroing {:?}\", self);\n        for entry in self.entries.iter_mut() {\n            entry.set_unused();\n        }\n        trace!(\"zeroed {:?} successfully\", self);\n        self\n    }\n\n    /// Return the start physical address of this `Table`\n    #[inline]\n    pub fn start_paddr(&self) -> PAddr {\n        PAddr::from(self as *const Self)\n    }\n\n    /// Return the `PhysicalPage` containing this table.\n    #[inline]\n    pub fn frame(&self) -> PhysicalPage {\n        PhysicalPage::containing(self.start_paddr())\n    }\n\n}\n\nimpl<L: Sublevel> Table<L> {\n\n\n    /// Returns the address of the next table, or None if none exists.\n    #[inline]\n    fn next_table_addr(&self, i: usize) -> Option<VAddr> {\n        let flags = self[i].flags();\n        if flags.contains(PRESENT) && !flags.contains(HUGE_PAGE) {\n            let table_addr = self as *const _ as usize;\n            Some(VAddr::from(table_addr << 9) | (i << 12))\n        } else {\n            None\n        }\n    }\n\n    /// Returns the next table, or `None` if none exists\n    #[inline]\n    pub fn next_table<I>(&self, i: I) -> Option<&Table<L::Next>>\n    where L: IndexOf<I> {\n        self.next_table_addr(L::index_of(i))\n            .map(|table_addr| unsafe { &*(table_addr.as_ptr()) })\n    }\n\n    /// Mutably borrows the next table.\n    #[inline]\n    pub fn next_table_mut<I>(&self, i: I) -> Option<& mut Table<L::Next>>\n    where L: IndexOf<I>\n        , I: fmt::Debug {\n        trace!(\"{:?}, {:?}\", self, i);\n        self.next_table_addr(L::index_of(i))\n            .map(|table_addr| unsafe { &mut *(table_addr.as_mut_ptr()) })\n    }\n\n\n    /// Returns the next table, creating it if it does not exist.\n    pub fn create_next<A>(&mut self, i: VirtualPage, alloc: &mut A)\n                         -> MapResult<&mut Table<L::Next>>\n    where A: FrameAllocator {\n        //println!(\"in create_next\");\n        if self.next_table(i).is_none() {\n            if self[i].is_huge() {\n                return Err(MapErr::Other {\n                    message: \"create next table\"\n                  , page: i\n                  , cause: \"huge pages not supported\"\n                })\n            }\n            //print!(\"allocating...\");\n            let frame = unsafe { alloc.allocate() }\n                .map_err(|err| MapErr::Alloc {\n                    message: \"create next table\"\n                  , page: i\n                  , cause: err\n              })?;\n            //println!(\"done.\");\n\n            self[i].set(frame, PRESENT | WRITABLE);\n            //println!(\"setted.\");\n            self.next_table_mut(i).map(Table::zero)\n        } else {\n            self.next_table_mut(i)\n        }.ok_or(MapErr::TableNotFound {\n            message: \"create next table\"\n          , page: i\n          , what: unsafe { intrinsics::type_name::<L::Next>() }\n        })\n\n    }\n}\n\n\n\nbitflags! {\n    pub flags EntryFlags: u64 {\n        /// Present flag.\n        /// Must be 1 to map a 2-MByte page or reference a page table.\n        const PRESENT =         1 << 0,\n        /// Writable flag.\n        /// If 0, writes may not be allowed to the 2-MB region controlled\n        /// by this entry\n        const WRITABLE =        1 << 1\n      , const USER_ACCESSIBLE = 1 << 2\n      , const WRITE_THROUGH =   1 << 3\n      , const NO_CACHE =        1 << 4\n      , const ACCESSED =        1 << 5\n      , const DIRTY =           1 << 6\n      , const HUGE_PAGE =       1 << 7\n      , const GLOBAL =          1 << 8\n      , const NO_EXECUTE =      1 << 63\n    }\n}\n\nimpl EntryFlags {\n    /// Returns true if this page is huge\n    #[inline]\n    pub fn is_huge(&self) -> bool {\n        self.contains(HUGE_PAGE)\n    }\n\n    /// Returns true if this page is present\n    #[inline]\n    pub fn is_present(&self) -> bool {\n        self.contains(PRESENT)\n    }\n\n    #[inline]\n    pub fn set_present(&mut self, present: bool) -> &mut Self {\n        if present { self.insert(PRESENT) }\n        else { self.remove(PRESENT) }\n        self\n    }\n\n    #[inline]\n    pub fn set_writable(&mut self, writable: bool) -> &mut Self {\n        if writable { self.insert(WRITABLE) }\n        else { self.remove(WRITABLE) }\n        self\n    }\n\n    #[inline]\n    pub fn set_executable(&mut self, executable: bool) -> &mut Self {\n        if executable { self.remove(NO_EXECUTE) }\n        else { self.insert(NO_EXECUTE) }\n        self\n    }\n}\n\n#[derive(Debug)]\npub struct Entry(u64);\n\nimpl Entry {\n\n    pub fn new(addr: PAddr) -> Self {\n        assert!(addr.is_page_aligned());\n        Entry(*addr)\n    }\n\n    // TODO: this is one of the worst names I have ever given a thing\n    #[inline]\n    pub fn do_huge(&self, offset: usize) -> Option<PhysicalPage> {\n        if self.is_huge() {\n            self.get_frame()\n                .map(|start_frame| {\n                    assert!( start_frame.number as usize % N_ENTRIES == 0\n                           , \"Start frame must be aligned on a 1GB boundary!\");\n                    start_frame + offset\n                })\n        } else {\n            None\n        }\n    }\n\n    /// Returns true if this is an unused entry\n    #[inline]\n    pub fn is_unused(&self) -> bool {\n        self.0 == 0\n    }\n\n    /// Sets this entry to be unused\n    #[inline(never)]\n    pub fn set_unused(&mut self) {\n        self.0 = 0;\n    }\n\n    /// Returns true if this page is huge\n    #[inline]\n    pub fn is_huge(&self) -> bool {\n        self.flags().is_huge()\n    }\n\n    /// Access the entry's bitflags.\n    #[inline]\n    pub fn flags(&self) -> EntryFlags {\n        EntryFlags::from_bits_truncate(self.0)\n    }\n\n    /// Returns the physical address pointed to by this page table entry\n    #[inline]\n    pub fn get_addr(&self) -> PAddr {\n        PAddr::from(self.0 & PML4_VADDR)\n    }\n\n    /// Returns the frame in memory pointed to by this page table entry.\n    pub fn get_frame(&self) -> Option<PhysicalPage> {\n        if self.flags().is_present() {\n            // If the entry is present, mask out bits 12-51 and\n            Some(PhysicalPage::containing(self.get_addr()))\n        } else {\n            None\n        }\n    }\n\n    pub fn set(&mut self, frame: PhysicalPage, flags: EntryFlags) {\n        let addr: u64 = frame.base_addr().into();\n        assert!(addr & !0x000fffff_fffff000 == 0);\n        self.0 = addr | flags.bits();\n    }\n\n}\n\nimpl<'a> convert::From<&'a elf::Section<u64>> for EntryFlags {\n    fn from(section: &'a elf::Section<u64>) -> Self {\n        *EntryFlags::empty()\n            .set_present(section.is_allocated())\n            .set_writable(section.is_writable())\n            .set_executable(section.is_executable())\n    }\n}\n"
  },
  {
    "path": "paging/src/arch/x86_64/temp.rs",
    "content": "use memory::{PAGE_SIZE, Page, PhysicalPage, VAddr, VirtualPage, FrameRange};\nuse alloc::{AllocResult, AllocErr, Layout, FrameAllocator};\n\nuse core::ops;\n\nuse super::ActivePageTable;\nuse super::table::{Table, PTLevel};\nuse ::{Mapper, MapResult};\n\n#[derive(Debug)]\npub struct TempPage { page: VirtualPage\n                    , frames: FrameCache\n                    }\n\n// Deref conversions for `TempPage` allow us to pass it to functions expecting\n// a `VirtualPage`.\nimpl ops::Deref for TempPage {\n    type Target = VirtualPage;\n    #[inline] fn deref(&self) -> &VirtualPage { &self.page }\n}\n\nimpl ops::DerefMut for TempPage {\n    #[inline] fn deref_mut(&mut self) -> &mut VirtualPage { &mut self.page }\n}\n\nimpl TempPage {\n\n    /// Create a new `TempPage`.\n    ///\n    /// # Arguments\n    /// + `number`: the page number for the temporary page\n    /// + `alloc`: a `FrameAllocator` for allocating the frames to use\n    ///            for the temporary page.\n    pub fn new<A>(number: usize, alloc: &mut A) -> Self\n    where A: FrameAllocator {\n        TempPage { page: VirtualPage { number: number }\n                 , frames: FrameCache::new(alloc)\n                 }\n    }\n\n    /// Map the `TempPage` to the given frame in the `ActivePageTable`.\n    ///\n    /// # Arguments\n    /// + `frame`: the `PhysicalPage` to map to\n    /// + `table`: the `ActivePageTable`\n    ///\n    /// # Returns\n    /// + The `VAddr` of the mapped page.\n    pub fn map_to( &mut self\n                 , frame: PhysicalPage\n                 , table: &mut ActivePageTable)\n                 -> MapResult<VAddr> {\n        //assert!( !table.is_mapped(self)\n                //, \"Cannot map {:?}, as it is already mapped\", self);\n        use super::table::WRITABLE;\n        trace!(\" . . TempPage::map_to({:?})\", frame);\n        table.map(self.page, frame, WRITABLE, &mut self.frames)\n             .map(|_| { self.page.base() })\n    }\n\n    pub fn map_to_table( &mut self\n                       , frame: PhysicalPage\n                       , table: &mut ActivePageTable)\n                       -> MapResult<&mut Table<PTLevel>> {\n        self.map_to(frame, table)\n            .map(|addr| unsafe {\n                &mut *(addr.as_mut_ptr::<Table<PTLevel>>())\n            })\n   }\n\n    pub fn unmap(&mut self, table: &mut ActivePageTable) -> MapResult<()> {\n        trace!(\"unmapping temp page {:?}\", self);\n        // assert!( table.is_mapped(self)\n        //         , \"Cannot unmap {:?}, as it is not mapped\", self);\n        table.unmap(self.page, &mut self.frames)\n             .map(|_| { trace!(\"temp page unmapped\") })\n\n    }\n}\n\n#[derive(Debug)]\npub struct FrameCache([Option<PhysicalPage>; 3]);\n\nimpl FrameCache {\n\n    pub fn new<A>(alloc: &mut A) -> Self\n    where A: FrameAllocator {\n        unsafe {\n            let frames = [ alloc.allocate().ok()\n                         , alloc.allocate().ok()\n                         , alloc.allocate().ok() ];\n            FrameCache(frames)\n        }\n    }\n}\n\nimpl FrameAllocator for FrameCache {\n\n    unsafe fn allocate(&mut self) -> AllocResult<PhysicalPage> {\n        self.0.iter_mut()\n            .find(    |frame| frame.is_some())\n            .and_then(|mut frame| frame.take())\n            .map(|frame| { trace!(\"frameCache: alloced {:?}\", &frame); frame})\n            .ok_or(AllocErr::Exhausted {\n                    request: Layout::from_size_align( PAGE_SIZE as usize\n                                                    , PAGE_SIZE as usize)\n                })\n    }\n\n    unsafe fn deallocate(&mut self, frame: PhysicalPage) {\n        self.0.iter_mut()\n            .find(    |slot| slot.is_none())\n            .and_then(|mut slot| { *slot = Some(frame); Some(()) })\n            .expect(\"FrameCache can only hold three frames!\");\n    }\n\n    unsafe fn allocate_range(&mut self, _num: usize)\n                            -> AllocResult<FrameRange> {\n        unimplemented!()\n    }\n\n    unsafe fn deallocate_range(&mut self, _range: FrameRange) {\n        unimplemented!()\n    }\n\n}\n"
  },
  {
    "path": "paging/src/arch/x86_64/tlb.rs",
    "content": "use memory::VAddr;\nuse super::{Page, VirtualPage};\n\n/// Invalidate the TLB completely by reloading the CR3 register.\n///\n/// # Safety\n/// + Causes a general protection fault if not executed in kernel mode.\npub unsafe fn flush_all() {\n    use cpu::control_regs::cr3;\n    cr3::write(cr3::read());\n}\n\n/// Something which may be flushed from the TLB\npub trait Flush {\n    /// Invalidate this object in the TLB using the `invlpg` instruction.\n    ///\n    /// # Safety\n    /// + Causes a general protection fault if not executed in kernel mode.\n    unsafe fn invlpg(self);\n    //\n    // /// Invalidate this object in the TLB instruction if we are in kernel mode.\n    // ///\n    // /// # Returns\n    // /// + True if the object was flushed\n    // /// + False if it was not flushed.\n    // #[inline]\n    // fn flush(&self) -> bool {\n    //     use cpu::PrivilegeLevel;\n    //\n    //     if PrivilegeLevel::current_iopl() != PrivilegeLevel::KernelMode {\n    //         false // can't flush, we are not in kernel mode\n    //     } else {\n    //         // this is safe since we know we are in kernel mode\n    //         unsafe { self.invlpg() };\n    //         true\n    //     }\n    // }\n}\n\nimpl Flush for VAddr {\n    #[inline]\n    unsafe fn invlpg(self) {\n         asm!( \"invlpg [$0]\"\n             :\n             : \"r\" (*self)\n             : \"memory\"\n             : \"intel\", \"volatile\" );\n    }\n}\n\nimpl Flush for VirtualPage {\n    #[inline]\n    unsafe fn invlpg(self) {\n        self.base().invlpg()\n    }\n}\n"
  },
  {
    "path": "paging/src/lib.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (hi@hawkweisman.me)\n//\n//  Copyright (c) 2015-2016 Eliza Weisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\n//! SOS Paging\n//!\n//! This is in its own crate so that it can depend on both the `memory` and\n//! `alloc` crates.\n#![feature(asm)]\n#![feature(unique)]\n#![feature(associated_consts, const_fn)]\n#![feature(core_intrinsics)]\n#![no_std]\n\n#[macro_use] extern crate bitflags;\n#[macro_use] extern crate log;\n#[macro_use] extern crate vga;\nextern crate spin;\n\nextern crate util;\nextern crate memory;\nextern crate sos_alloc as alloc;\nextern crate cpu;\nextern crate elf;\nextern crate params;\n\npub mod arch;\npub mod stack;\npub use self::arch::{kernel_remap, test_paging};\n\nuse memory::{Page, PAddr, PhysicalPage, VAddr, VirtualPage};\nuse alloc::{FrameAllocator, AllocErr};\nuse core::fmt;\n\npub type MapResult<T = ()> = Result<T, MapErr>;\n\n#[derive(Clone)]\npub enum MapErr<P: Page + fmt::Debug = VirtualPage> {\n    Alloc { message: &'static str, page: P, cause: AllocErr }\n  , Other { message: &'static str, page: P, cause: &'static str }\n  , TableNotFound { message: &'static str, page: VirtualPage, what: &'static str }\n  , AlreadyInUse { message: &'static str, page: VirtualPage, frame: PhysicalPage }\n  , NoPage { message: &'static str, cause: &'static str}\n}\n\nimpl<P> fmt::Debug for MapErr<P> where P: Page + fmt::Debug {\n    #[inline]\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        unimplemented!()\n    }\n}\n\npub trait Mapper {\n    type Flags;\n\n    /// Translates a virtual address to the corresponding physical address.\n    ///\n    /// # Return\n    /// + `Some(PAddr)` containing the physical address corresponding to\n    ///                 `vaddr`, if it is mapped.\n    /// + `None`: if the address is not mapped.\n    fn translate(&self, vaddr: VAddr) -> Option<PAddr>;\n\n    /// Translates a virtual page to a physical frame.\n    fn translate_page(&self, page: VirtualPage) -> Option<PhysicalPage>;\n\n    /// Modifies the page tables so that `page` maps to `frame`.\n    ///\n    /// # Arguments\n    /// + `page`: the virtual `Page` to map\n    /// + `frame`: the physical `Frame` that `Page` should map to.\n    /// + `flags`: the page table entry flags.\n    /// + `alloc`: a memory allocator\n    fn map<A>( &mut self, page: VirtualPage, frame: PhysicalPage\n             , flags: Self::Flags, alloc: &mut A )\n             -> MapResult<()>\n    where A: FrameAllocator;\n\n    /// Identity map a given `frame`.\n    ///\n    /// # Arguments\n    /// + `frame`: the physical `Frame` to identity map\n    /// + `flags`: the page table entry flags.\n    /// + `alloc`: a memory allocator\n    fn identity_map<A>( &mut self, frame: PhysicalPage\n                      , flags: Self::Flags, alloc: &mut A )\n                      -> MapResult<()>\n    where A: FrameAllocator;\n\n    /// Map the given `VirtualPage` to any free frame.\n    ///\n    /// This is like the fire and forget version of `map_to`: we just pick the\n    /// first available free frame and map the page to it.\n    ///\n    /// # Arguments\n    /// + `page`: the`VirtualPage` to map\n    /// + `flags`: the page table entry flags.\n    /// + `alloc`: a memory allocator\n    fn map_to_any<A>( &mut self, page: VirtualPage\n                    , flags: Self::Flags\n                    , alloc: &mut A)\n                    -> MapResult<()>\n    where A: FrameAllocator;\n\n    /// Unmap the given `VirtualPage`.\n    ///\n    /// All freed frames are returned to the given `FrameAllocator`.\n    fn unmap<A>(&mut self, page: VirtualPage, alloc: &mut A) -> MapResult<()>\n    where A: FrameAllocator;\n\n}\n"
  },
  {
    "path": "paging/src/stack.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza Weisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\n//! Stack allocator\nuse alloc::{AllocResult, AllocErr, FrameAllocator, Layout};\nuse memory::{PageRange, VAddr};\nuse ::Mapper;\nuse arch::ActivePageTable;\n\n\nuse core::ops::Range;\n\npub type Stack = Range<VAddr>;\n\npub trait StackAllocator {\n    fn allocate<A>( &mut self\n                      , page_table: &mut ActivePageTable\n                      , frames: &mut A\n                      , num_pages: usize) -> AllocResult<Stack>\n    where A: FrameAllocator;\n}\n\nimpl StackAllocator for PageRange {\n\n    fn allocate<A>( &mut self\n                      , page_table: &mut ActivePageTable\n                      , frames: &mut A\n                      , num_pages: usize) -> AllocResult<Stack>\n    where A: FrameAllocator {\n        use memory::{PAGE_SIZE, Page};\n        use arch::table::WRITABLE;\n        let exhausted = || {\n            AllocErr::Exhausted {\n                request: Layout::from_size_align( PAGE_SIZE as usize * num_pages\n                                                , PAGE_SIZE as usize)\n            }\n        };\n        if num_pages == 0 {\n            Err(AllocErr::Unsupported {\n                details: \"Why would you try to allocate a zero-page stack?\"\n            })\n        } else {\n            // clone a working copy of the stack allocator's page range\n            // we will only write it back if we successfully allocate a new\n            // stack\n            let mut working_pages = self.clone();\n\n            // try to get a guard page\n            working_pages.next().ok_or_else(&exhausted)?;\n\n            let start_page = working_pages.next().ok_or_else(&exhausted)?;\n            let end_page   = if num_pages == 1 { start_page }\n                             else { working_pages.nth(num_pages - 2)\n                                                 .ok_or_else(&exhausted)?\n                             };\n\n            // successfully allocated! write back the working page range\n            *self = working_pages;\n\n            for page in start_page .. end_page {\n                page_table.map_to_any(page, WRITABLE, frames);\n            }\n\n            let stack_top = end_page.end_address();\n            Ok(stack_top .. start_page.base())\n        }\n    }\n}\n"
  },
  {
    "path": "params/Cargo.toml",
    "content": "[package]\nname = \"params\"\nversion = \"0.0.1\"\nauthors = [ \"Eliza Weisman <hi@hawkweisman.me>\" ]\n\n[profile.dev]\nopt-level = 3\ndebug = true\nrpath = false\nlto = false\ndebug-assertions = true\ncodegen-units = 1\npanic = \"abort\"\n\n[profile.release]\nopt-level = 3\ndebug = true\nrpath = false\nlto = false\npanic = \"abort\"\n\n[dependencies]\nutil = { path = \"../util\" }\nmemory = { path = \"../memory\" }\nelf = { path = \"../elf\" }\n\n[dependencies.arrayvec]\nversion = \"0.3.16\"\ndefault-features = false\n"
  },
  {
    "path": "params/src/lib.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (hi@hawkweisman.me)\n//\n//  Copyright (c) 2015-2017 Eliza Weisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\n//! SOS init parameters\n//!\n//! This crate is intended to facilitate the sharing of initialization\n//! parameters between \"higher-level\" SOS subcrates (such as [`alloc`] and\n//! [`paging`]) in a platform-independent way.\n//!\n//! [`alloc`](../alloc)\n//! [`paging`](../paging)\n#![no_std]\n#![deny(missing_docs)]\n#![feature(step_trait)]\n\nextern crate memory;\nextern crate elf;\nextern crate arrayvec;\n\nuse memory::{ PAddr, Page, PhysicalPage, FrameRange };\nuse core::default::Default;\nuse core::iter::Step;\nuse core::slice::Iter as SliceIter;\nuse arrayvec::{ArrayVec};\n\npub mod mem;\n\nconst MAX_MEM_AREAS: usize = 32;\n\n/// If we are on x86_64 or armv7 this uses the 64-bit ELF word\n#[cfg(target_pointer_width = \"64\")]\npub type ElfSections = elf::section::Sections<'static, u64>;\n\n/// If we are on x86, this uses the 32-bit ELF word\n#[cfg(target_pointer_width = \"32\")]\npub type ElfSections = elf::section::Sections<'static, u32>;\n\n/// Parameters used during the init process\n#[derive(Clone, Debug)]\npub struct InitParams {\n    /// The base of the kernel memory range\n    pub kernel_base: PAddr\n  , /// The top of the kernel memory range\n    pub kernel_top: PAddr\n  , /// The base of the memory range for the kernel heap\n    pub heap_base: PAddr\n  , /// The top of the memory range to use for the kernel heap\n    pub heap_top: PAddr\n  , /// The base of the memory range for the kernel stack\n    pub stack_base: PAddr\n  , /// The top of the memory range to use for the kernel stack\n    pub stack_top: PAddr\n  , /// The start address of the Multiboot info structure, if it exists.\n    ///\n    /// N.B. that this is currently never `None`, as we only support multiboot.\n    /// However, this may change at a later date.\n    pub multiboot_start: Option<PAddr>\n  , /// The end address of the Multiboot info structure, if it exists.\n    ///\n    /// N.B. that this is currently never `None`, as we only support multiboot.\n    /// However, this may change at a later date.\n    pub multiboot_end: Option<PAddr>\n  , /// Map of memory areas\n    pub mem_map: ArrayVec<[mem::Area; MAX_MEM_AREAS]>\n    , /// Map of elf sections\n    // todo: construct using convert::From<multiboot>\n     pub elf_sections: Option<ElfSections>\n}\n\nimpl Default for InitParams {\n    fn default() -> Self {\n        // use memory::arch::{HEAP_BASE, HEAP_TOP, STACK_BASE, STACK_TOP};\n        InitParams { kernel_base: PAddr::from(0x0)\n                     // NOTE: this is, of course, Extremely Wrong, but the\n                     //       `Default` impl is not going to make _correct_\n                     //       params, just fill in default values for other\n                     //       fns that make params.\n                     // TODO: should this be an Option instead?\n                   , kernel_top: PAddr::from(0x0)\n                   , heap_base:  PAddr::from(0x0)\n                   , heap_top: PAddr::from(0x0)\n                   , stack_base: PAddr::from(0x0)\n                   , stack_top: PAddr::from(0x0)\n                   , multiboot_start: None\n                   , multiboot_end: None\n                   , mem_map: ArrayVec::<[mem::Area; MAX_MEM_AREAS]>::new()\n                   , elf_sections: None\n                   }\n    }\n}\n\nimpl InitParams {\n    /// Returns an iterator over the kernel's ELF sections\n    // TODO: is this cross-platform? are we using ELF on all our supported\n    //       architectures? i think we are, but we should ensure this is the\n    //       case...\n    //          – eliza, 1/22/2017\n    pub fn elf_sections(&self) ->  ElfSections {\n        self.elf_sections.clone()\n        .expect(\"Attempted to access ELF sections on a \\\n                 non-ELF kernel!\")\n    }\n\n    /// Returns the start address of the multiboot info struct\n    ///\n    /// # Panics\n    /// If this is a non-Multiboot kernel\n    // TODO: instead of panicking, return Option!\n    //          - eliza, 5/26/2017\n    #[inline]\n    pub fn multiboot_start(&self) -> PAddr {\n        self.multiboot_start\n            .expect(\"Attempted to access Multiboot info structure on a \\\n                     non-Multiboot kernel!\")\n    }\n\n    /// Returns the end address of the multiboot info struct\n    ///\n    /// # Panics\n    /// If this is a non-Multiboot kernel\n    // TODO: instead of panicking, return Option!\n    //          - eliza, 5/26/2017\n    pub fn multiboot_end(&self) -> PAddr {\n        self.multiboot_end\n            .expect(\"Attempted to access Multiboot info structure on a \\\n                     non-Multiboot kernel!\")\n    }\n\n    /// Returns the range of frames containing the kernel binary.\n    ///\n    /// The kernel _should_ start on the first address in the frame range,\n    /// since the kernel should be page aligned.\n    //  TODO: this should be an array vector or linked list of frame ranges\n    //        possibly?\n    //          - eliza, 2/28/2017\n    #[inline]\n    pub fn kernel_frames(&self) -> FrameRange {\n        // TODO: assert that the kernel base addr is page aligned here?\n        //       this should maybe be a debug assertion?\n        //          - eliza, 1/22/2017\n        PhysicalPage::containing(self.kernel_base) ..\n        PhysicalPage::containing(self.kernel_top).add_one()\n    }\n\n    /// Returns the range of frames containing the kernel heap\n    ///\n    /// The heap _should_ start on the first address in the frame range,\n    /// since the heap should be page aligned.\n    #[inline]\n    pub fn heap_frames(&self) -> FrameRange {\n        // TODO: assert that the heap base addr is page aligned here?\n        //       this should maybe be a debug assertion?\n        //          - eliza, 1/22/2017\n        PhysicalPage::containing(self.heap_base) ..\n        PhysicalPage::containing(self.heap_top).add_one()\n    }\n\n    /// Returns the range of frames containing the kernel stack.\n    #[inline]\n    pub fn stack_frames(&self) -> FrameRange {\n        unimplemented!()\n    }\n\n    /// returns an iterator over the memory map\n    #[inline]\n    pub fn mem_map(&self) -> mem::Map {\n        self.mem_map.iter()\n    }\n\n\n}\n"
  },
  {
    "path": "params/src/mem.rs",
    "content": "//! Memory parameters\n\nuse memory::PAddr;\nuse core::ops::Range;\nuse core::slice::Iter;\n/// A memory map is an iterator over memory areas\npub type Map<'a> = Iter<'a, Area>;\n\n/// A memory area\n#[derive(Debug, Copy, Clone)]\npub struct Area {\n    /// The start address of this memory area\n    pub start_addr: PAddr\n  , /// The end address of this memory area\n    pub end_addr: PAddr\n  , /// Whether or not the memory area is usable\n    pub is_usable: bool\n}\n"
  },
  {
    "path": "rustfmt.toml",
    "content": "where_indent = \"Inherit\"\nstruct_lit_style = \"Visual\"\nchain_base_indent = \"Tabbed\"\nchain_indent = \"Visual\"\nreorder_imports = true\nwrap_comments = true\nfn_brace_style = \"PreferSameLine\"\nitem_brace_style = \"PreferSameLine\"\nuse_try_shorthand = true\n"
  },
  {
    "path": "scripts/README.md",
    "content": "this directory contains a handful of scripts to help install the needed tools to build SOS. these scripts are run by the `make env` task in the `Makefile`.\n\nif you'd rather install manually, [BUILDING.md](https://github.com/hawkw/sos-kernel/blob/master/BUILDING.md) describes what you'll need to build SOS and how to install it.\n\ni've tried my best to make sure these scripts work correctly on most common platforms, but due to the wide amount of variation in possible build environments, i haven't tested them everywhere. therefore, i can't guarantee they'll work on _your_ system. if something goes wrong, please don't hesitate to [let me know](https://github.com/hawkw/sos-kernel/issues/new).\n\n-- eliza\n"
  },
  {
    "path": "scripts/install-env-linux.sh",
    "content": "#!/bin/bash\n#\n#  SOS: the Stupid Operating System\n#  by Eliza Weisman (eliza@elizas.website)\n#\n#  Copyright (c) 2015-2017 Eliza Weisman\n#  Released under the terms of the MIT license. See `LICENSE` in the root\n#  directory of this repository for more information.\n#\n#  Portions of this script are adapted from a script by Steve Klabnik for\n#  the IntermezzOS project, available at\n#  http://intermezzos.github.io/book/appendix/osx-install.html\n#\nset -e\n# this script will install the required dependencies and tools\n# to build the SOS kernel.\n\nCONTINUE=false\n\ndistro=$(lsb_release -is)\nplatform=$(uname)\nbold=$(tput bold)\nnormal=$(tput sgr0)\n\necho \"${bold}install-env-linux:${normal} Distro is ${distro}\"\ncase $distro in\n    Ubuntu | Debian)\n        echo \"${bold}install-env-linux:${normal} Installing with apt-get.\"\n        echo \"${bold}install-env-linux:${normal} This will require sudo.\"\n        echo \"${bold}install-env-linux:${normal} Do you want to continue? (y/n)\"\n\n        read -r response\n        if [[ $response =~ ^([yY][eE][sS]|[yY])$ ]]; then\n            CONTINUE=true\n        fi\n\n        if ! $CONTINUE; then\n            echo \"${bold}install-env-linux:${normal} Okay, cancelling installation.\"\n            exit\n        fi\n\n        sudo apt-get install xorriso qemu build-essential mtools | sed \"s/^/${bold}apt-get:${normal} /\"\n        ;;\n    Arch | ManjaroLinux)\n        echo \"${bold}install-env-linux:${normal} Installing with pacman.\"\n        echo \"${bold}install-env-linux:${normal} This will require sudo.\"\n        echo \"${bold}install-env-linux:${normal} Do you want to continue? (y/n)\"\n\n        read -r response\n        if [[ $response =~ ^([yY][eE][sS]|[yY])$ ]]; then\n            CONTINUE=true\n        fi\n\n        if ! $CONTINUE; then\n            echo \"${bold}install-env-linux:${normal} Okay, cancelling installation.\"\n            exit\n        fi\n\n        sudo pacman -S --needed binutils grub libisoburn qemu mtools | sed \"s/^/${bold}pacman:${normal} /\"\n        ;;\nesac\n    # todo: support non-x86_64 architectures here (later)\n\n    gcc=$(which gcc)\n    echo \"${bold}install-env-linux:${normal} Linking ${gcc} to /usr/bin/x86_64-pc-elf-gcc.\"\n    sudo ln -s $gcc /usr/bin/x86_64-pc-elf-gcc\n\n    objcopy=$(which objcopy)\n    echo \"${bold}install-env-linux:${normal} Linking ${objcopy} to /usr/bin/x86_64-elf-objcopy.\"\n    sudo ln -s $objcopy x86_64-elf-objcopy\n\n    strip=$(which strip)\n    echo \"${bold}install-env-linux:${normal} Linking ${strip} to /usr/bin/x86_64-elf-strip.\"\n    sudo ln -s $strip x86_64-elf-strip\n"
  },
  {
    "path": "scripts/install-env-mac.sh",
    "content": "#!/bin/bash\n#\n#  SOS: the Stupid Operating System\n#  by Eliza Weisman (eliza@elizas.website)\n#\n#  Copyright (c) 2015-2017 Eliza Weisman\n#  Released under the terms of the MIT license. See `LICENSE` in the root\n#  directory of this repository for more information.\n#\n#  Portions of this script are adapted from a script by Steve Klabnik for\n#  the IntermezzOS project, available at\n#  http://intermezzos.github.io/book/appendix/osx-install.html\n#\nset -e\n# this script will install the required dependencies and tools\n# to build the SOS kernel.\nbold=$(tput bold)\nnormal=$(tput sgr0)\n# check if `brew` is installed\ncommand -v brew >/dev/null 2>&1\nif [ $? -eq 1 ]\nthen\n    echo \"${bold}install-mac:${normal} Homebrew is not installed.\"\n    echo \"${bold}install-mac:${normal} Please go to http://brew.sh/ to install it before continuing.\"\n    exit\nfi\n\nexport TARGET=x86_64-pc-elf\n\nmkdir -p $HOME/src\n\n# dependencies installable with brew\necho \"${bold}install-mac:${normal} Installing dependencies using Homebrew...\"\nbrew update | sed \"s/^/${bold}brew:${normal} /\"\nbrew tap Homebrew/bundle | sed \"s/^/${bold}brew:${normal} /\"\nbrew bundle | sed \"s/^/${bold}brew:${normal} /\"\n\n\nCARGO_CONFIG=\"$HOME/.cargo/config\"\nGREP_TARGET_LINKER=\"\\[target\\.x86_64\\-sos\\-kernel\\-gnu\\]\"\nTARGET_LINKER=\"\\n\\n[target.x86_64-sos-kernel-gnu]\\nlinker = \\\"/usr/local/bin/x86_64-pc-elf-gcc\\\"\"\n\nif grep -q $GREP_TARGET_LINKER \"$CARGO_CONFIG\"; then\n    echo \"${bold}install-mac:${normal} Target linker already present in $CARGO_CONFIG. Done.\"\nelse\n    echo \"${bold}install-mac:${normal} Adding target linker to $CARGO_CONFIG...\"\n    printf \"$TARGET_LINKER\" >> \"$CARGO_CONFIG\"\nfi\n"
  },
  {
    "path": "scripts/install-env.sh",
    "content": "#!/bin/bash\n#\n#  SOS: the Stupid Operating System\n#  by Eliza Weisman (eliza@elizas.website)\n#\n#  Copyright (c) 2015-2017 Eliza Weisman\n#  Released under the terms of the MIT license. See `LICENSE` in the root\n#  directory of this repository for more information.\n#\nset -e\n# this script will install the required dependencies and tools\n# to build the SOS kernel.\n\nCONTINUE=false\nplatform=$(uname)\nbold=$(tput bold)\nnormal=$(tput sgr0)\n\necho \"\"\necho \"${bold}install-env:${normal} Stupid Operating System Dev Environment Setup *** \"\necho \"\"\necho \"${bold}install-env:${normal} This script is about to download and install software on your computer.\"\nif [[ $PLATFORM == 'Darwin' ]]; then\n    echo \"${bold}install-env:${normal} Since you are on macOS, this install process will not require sudo\"\nelse\n    echo \"${bold}install-env:${normal} Depending on your OS and package manager, this process may require sudo.\"\nfi\necho \"${bold}install-env:${normal} Please take the time to read the script source code and ensure you are\"\necho \"${bold}install-env:${normal} aware of what software will be installed before continuing.\"\necho \"\"\necho \"${bold}install-env:${normal} Do you want to continue? (y/n)\"\n\nread -r response\nif [[ $response =~ ^([yY][eE][sS]|[yY])$ ]]; then\n    CONTINUE=true\nfi\n\nif ! $CONTINUE; then\n    echo \"${bold}install-env:${normal} Okay, cancelling installation.\"\n    exit\nfi\n\nset +e\n\necho \"${bold}install-env:${normal} Checking if Rust is installed...\"\ncommand -v rustc >/dev/null 2>&1\nif [[ $? -eq 0 ]]; then\n    command -v rustup >/dev/null 2>&1\n    if [[ $? -eq 1 ]]; then\n        echo \"${bold}install-env:${normal} Rust is installed, but it is not managed by \\`rustup\\`.\"\n        echo \"${bold}install-env:${normal} Your current Rust installation is not supported.\"\n        echo \"${bold}install-env:${normal} Please visit https://www.rustup.rs to re-install using \\`rustup\\`.\"\n        echo \"${bold}install-env:${normal} Exiting.\"\n        exit 1\n    else\n        echo \"${bold}install-env:${normal} Rust is already installed.\"\n    fi\nelse\n    set -e\n    echo \"\"\n    echo \"${bold}install-env:${normal} installing Rust\"\n    echo \"\"\n    curl https://sh.rustup.rs -sSf | sh\nfi\n\nif [ -f ~/.bash_profile ]\nthen\n    echo \"export PATH=$PATH:$HOME/.cargo/bin\" >> ~/.bash_profile\nfi\n\n\necho \"${bold}install-env:${normal} Updating Rust version\"\nrustup update nightly\necho \"${bold}install-env:${normal} Overriding default Rust to nightly for SOS\"\nrustup override add nightly\necho \"${bold}install-env:${normal} Installing rust-src component\"\nrustup component add rust-src\necho \"${bold}install-env:${normal} Installing platform-specific dependencies.\"\ncase $platform in\n    Darwin)\n        echo \"${bold}install-env:${normal} Detected OS as macOS.\"\n        ./scripts/install-env-mac.sh\n        ;;\n    Linux)\n        echo \"${bold}install-env:${normal} Detected OS as Linux.\"\n        ./scripts/install-env-linux.sh\n        ;;\n    *)\n        echo \"${bold}install-env:${normal} Unknown OS, exiting.\"\n        exit 1\n        ;;\nesac\n\nset +e\n\necho \"${bold}install-env:${normal} Checking if xargo is installed...\"\ncommand -v xargo >/dev/null 2>&1\nif [[ $? -eq 1 ]]; then\n    echo \"${bold}install-env:${normal} xargo is already installed.\"\n    exit 0\nelse\n    set -e\n    echo \"\" \n    echo \"${bold}install-env:${normal} Installing \\`xargo\\`.\"\n    echo \"\"\n    cargo install xargo\nfi\n"
  },
  {
    "path": "sos_alloc/Cargo.toml",
    "content": "[package]\nname = \"sos_alloc\"\nversion = \"0.1.0\"\nauthors = [\"Eliza Weisman <eliza@elizas.website>\"]\n\n[features]\ndefault = [\"buddy\", \"bump_ptr\", \"borrow\"]\nbuddy = [\"sos_intrusive\"]\nbuddy_as_system = [\"buddy\", \"once\"]\nsystem = []\nbump_ptr = []\nplacement_in = [\"system\"]\nborrow = []\nfirst_fit = [\"arrayvec\"]\nbench = []\n\n[dependencies.log]\nversion = \"0.3.6\"\ndefault-features = false\nfeatures = [\"release_max_level_info\"]\n\n[dependencies.memory]\npath = \"../memory\"\n\n[dependencies.spin]\nversion = \"^0.4.6\"\n\n[dependencies.sos_intrusive]\npath = \"../sos_intrusive\"\noptional = true\n\n[dependencies.arrayvec]\nversion = \"0.3.16\"\ndefault-features = false\noptional = true\n\n[dependencies.once]\nversion = \"^0.3.3\"\noptional = true\n\n[dependencies.params]\npath = \"../params\"\n"
  },
  {
    "path": "sos_alloc/src/borrow.rs",
    "content": "use super::{Address, Allocator, Layout};\nuse ptr::Unique;\nuse ops::{Deref, DerefMut};\nuse spin::Mutex;\n\npub trait Lender {\n    type Borrowed;\n    fn borrow(&self) -> Self::Borrowed;\n}\n\n/// A borrowed handle on a heap allocation with a specified lifetime.\n///\n/// This automatically deallocates the allocated object when the borrow's\n/// lifetime ends. It also ensures that the borrow only lives as long as the\n/// allocator that provided it, and that the borrow is dropped if the allocator\n/// is dropped.\n// TODO: can we replace this with one generic implementation that works for\n//       borrowed pointers, objects, and arrays? can that code be reused for\n//       BorrowedFrame/BorrowedFrameRange as well?\n//          - eliza, 02/21/2017\npub struct BorrowedPtr<'alloc, A>\nwhere A: Allocator\n    , A: 'alloc {\n    ptr: Unique<u8>\n  , layout: Layout\n  , allocator: &'alloc Mutex<A>\n}\n\nimpl<'alloc, A> BorrowedPtr<'alloc, A>\nwhere A: Allocator\n    , A: 'alloc {\n\n    #[inline]\n    pub fn new( ptr: Address\n                    , layout: Layout\n                    , allocator: &'alloc Mutex<A>)\n                    -> Self {\n        BorrowedPtr { ptr: unsafe { Unique::new(ptr) }\n                    , layout: layout\n                    , allocator: allocator\n                    }\n\n    }\n}\n\nimpl<'alloc, A> Deref for BorrowedPtr<'alloc, A>\nwhere A: Allocator\n    , A: 'alloc {\n    type Target = Unique<u8>;\n    fn deref(&self) ->  &Self::Target { &self.ptr }\n}\n\nimpl<'alloc, A> Drop for BorrowedPtr<'alloc, A>\nwhere A: Allocator\n    , A: 'alloc {\n    fn drop(&mut self) {\n        unsafe {\n            self.allocator.lock().dealloc(self.ptr.as_ptr(), self.layout.clone())\n        }\n    }\n}\n\n/// A borrowed handle on a heap allocation with a specified lifetime.\n///\n/// This automatically deallocates the allocated object when the borrow's\n/// lifetime ends. It also ensures that the borrow only lives as long as the\n/// allocator that provided it, and that the borrow is dropped if the allocator\n/// is dropped.\npub struct Borrowed<'alloc, A, T>\nwhere A: Allocator\n    , A: 'alloc {\n    value: Unique<T>\n  , allocator: &'alloc Mutex<A>\n}\n\nimpl<'alloc, A, T> Borrowed<'alloc, A, T>\nwhere A: Allocator\n    , A: 'alloc {\n\n    #[inline]\n    pub fn new( value: Unique<T>, allocator: &'alloc Mutex<A>)\n                    -> Self {\n        Borrowed { value: value\n                 , allocator: allocator\n                 }\n\n    }\n}\n\nimpl<'alloc, A, T> Deref for Borrowed<'alloc, A, T>\nwhere A: Allocator\n    , A: 'alloc {\n    type Target = T;\n    fn deref(&self) ->  &Self::Target { unsafe { self.value.as_ref() } }\n}\n\nimpl<'alloc, A, T> DerefMut for Borrowed<'alloc, A, T>\nwhere A: Allocator\n    , A: 'alloc {\n    fn deref_mut(&mut self) ->  &mut Self::Target {\n        unsafe { self.value.as_mut() }\n    }\n}\n\nimpl<'alloc, A, T> Drop for Borrowed<'alloc, A, T>\nwhere A: Allocator\n    , A: 'alloc {\n    fn drop(&mut self) {\n        use mem::drop;\n        let address = self.value.as_ptr() as Address;\n        // ensure we drop the object _before_ deallocating it, so that\n        // the object's destructor gets run first\n        // i hope this is correct...\n        drop(self.value.as_ptr());\n        unsafe {\n            self.allocator.lock()\n                .dealloc( address\n                        , Layout::for_value(self.value.as_ref()))\n        }\n    }\n}\n"
  },
  {
    "path": "sos_alloc/src/buddy/math.rs",
    "content": "#[cfg(target_arch=\"x86\")]\nconst B: [usize; 5]\n    = [ 0x2, 0xC, 0xF0\n      , 0xFF00\n      , 0xFFFF0000];\n#[cfg(target_arch=\"x86\")]\nconst S: [usize; 5] = [ 1, 2, 4, 8, 16 ];\n\n#[cfg(target_arch=\"x86_64\")]\nconst B: [usize; 6]\n    = [ 0x2, 0xC, 0xF0\n      , 0xFF00, 0xFFFF0000\n      , 0xFFFFFFFF00000000];\n\n#[cfg(target_arch=\"x86_64\")]\nconst S: [usize; 6] = [ 1, 2, 4, 8, 16, 32 ];\n\npub trait PowersOf2 {\n    fn is_pow2(&self) -> bool;\n    fn next_pow2(&self) -> Self;\n    fn log2(&self) -> Self;\n}\n\nimpl PowersOf2 for usize {\n    fn is_pow2(&self) -> bool {\n        *self != 0 && (self & (self - 1)) == 0\n    }\n\n    /// Returns the next power of 2\n    fn next_pow2(&self) -> usize {\n        let mut v = *self;\n        if v == 0 {\n            1\n        } else {\n            v -= 1;\n            v = v | (v >> 1);\n            v = v | (v >> 2);\n            v = v | (v >> 4);\n            v = v | (v >> 8);\n            v = v | (v >> 16);\n            v + 1\n        }\n    }\n\n    #[cfg(not(any(target_arch=\"x86_64\", target_arch=\"x86\")))]\n    fn log2(&self) -> usize {\n        // This is the \"obvious\" log base 2 implementation. The lookup table\n        // -based approach would be much faster, but we can't use it for\n        // `usize` since we aren't sure what size a usize is without conditional\n        // compilation.\n        let mut res = 0;\n        let mut num = *self >> 1;\n        while num != 0 {\n            res += 1;\n            num >>= 1;\n        }\n        res\n    }\n\n    #[cfg(any(target_arch=\"x86_64\", target_arch=\"x86\"))]\n    fn log2(&self) -> usize {\n        let mut r: usize = 0;\n        let mut v = *self;\n\n        for i in (0..S.len()).rev() {\n            if v & B[i] != 0 {\n                v >>= S[i];\n                r |=  S[i];\n            }\n        }\n        r\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n    #[cfg(feature = \"bench\")]\n    use test::{self, Bencher};\n\n    #[test]\n    fn test_next_pow2() {\n        assert_eq!(2usize.next_pow2(), 2);\n        assert_eq!(0usize.next_pow2(), 1);\n        assert_eq!(3usize.next_pow2(), 4);\n        assert_eq!(5678usize.next_pow2(), 8192);\n        assert_eq!(1,  0.next_pow2());\n        assert_eq!(1,  1.next_pow2());\n        assert_eq!(2,  2.next_pow2());\n        assert_eq!(4,  3.next_pow2());\n        assert_eq!(4,  4.next_pow2());\n        assert_eq!(8,  5.next_pow2());\n        assert_eq!(8,  8.next_pow2());\n        assert_eq!(16, 9.next_pow2());\n        assert_eq!(16, 16.next_pow2());\n        assert_eq!(32, 17.next_pow2());\n        assert_eq!(32, 32.next_pow2());\n        assert_eq!(8388608, 8376263.next_pow2());\n    }\n\n    #[test]\n    fn test_is_pow2() {\n    assert_eq!(false, 0.is_pow2());\n    assert_eq!(true,  1.is_pow2());\n    assert_eq!(true,  2.is_pow2());\n    assert_eq!(false, 3.is_pow2());\n    assert_eq!(true,  4.is_pow2());\n    assert_eq!(false, 255.is_pow2());\n    assert_eq!(true,  256.is_pow2());\n    assert_eq!(false, 257.is_pow2());\n    assert_eq!(false, 4294967295.is_pow2());\n    }\n\n\n    #[test]\n    fn test_log2() {\n    assert_eq!(0, 0.log2());\n    assert_eq!(0, 1.log2());\n    assert_eq!(1, 2.log2());\n    assert_eq!(5, 32.log2());\n    assert_eq!(10, 1024.log2());\n    }\n\n    #[cfg(feature = \"bench\")]\n    #[bench]\n    fn our_next_pow2(b: &mut Bencher) {\n        use collections::Vec;\n        b.iter(|| {\n            let n = test::black_box(100_000);\n\n            (0..n).map(|x: usize| x.next_pow2())\n                  .collect::<Vec<_>>() // force the map to return so it doesn't get optimised away\n        })\n    }\n\n    #[cfg(feature = \"bench\")]\n    #[bench]\n    fn std_next_power_of_two(b: &mut Bencher) {\n        use collections::Vec;\n        b.iter(|| {\n            let n = test::black_box(100_000);\n\n            (0..n).map(|x: usize| x.next_power_of_two())\n                  .collect::<Vec<_>>() // force the map to return so it doesn't get optimised away\n        })\n    }\n\n    #[cfg(feature = \"bench\")]\n    #[bench]\n    fn our_is_pow2(b: &mut Bencher) {\n        use collections::Vec;\n        b.iter(|| {\n            let n = test::black_box(100_000);\n\n            (0..n).map(|ref x: usize| x.is_pow2())\n                  .collect::<Vec<_>>() // force the map to return so it doesn't get optimised away\n        })\n    }\n\n    #[cfg(feature = \"bench\")]\n    #[bench]\n    fn std_is_power_of_two(b: &mut Bencher) {\n        use collections::Vec;\n        b.iter(|| {\n            let n = test::black_box(100_000);\n\n            (0..n).map(|x: usize| x.next_power_of_two())\n                  .collect::<Vec<_>>() // force the map to return so it doesn't get optimised away\n        })\n    }\n}\n"
  },
  {
    "path": "sos_alloc/src/buddy/mod.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza Weisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\n//! Simple buddy-block allocator\n\n#![warn(missing_docs)]\nmod math;\n#[cfg(feature = \"buddy_as_system\")]\npub mod system;\n#[cfg(feature = \"buddy_as_system\")]\npub use self::system::BuddyFrameAllocator;\n\nuse super::{Allocator, Layout, Address, AllocErr};\nuse self::math::PowersOf2;\n\nuse core::mem;\nuse core::cmp::{max, min};\nuse core::ptr::Unique;\n\nuse intrusive::list::{List, Node};\nuse intrusive::rawlink::RawLink;\nuse memory::PAGE_SIZE;\n\n#[cfg(test)]\nmod test;\n\n/// A `FreeList` is a list of unique free blocks\npub type FreeList = List<Unique<FreeBlock>, FreeBlock>;\n\n/// A free block header stores a pointer to the next and previous free blocks.\npub struct FreeBlock { next: RawLink<FreeBlock>\n                     , prev: RawLink<FreeBlock>\n                     }\nimpl FreeBlock {\n    #[inline] unsafe fn as_ptr(&self) -> *mut u8 { mem::transmute(self) }\n}\n\nimpl Node for FreeBlock {\n    #[inline] fn prev(&self) -> &RawLink<FreeBlock> {\n        &self.prev\n    }\n    #[inline] fn next(&self) -> &RawLink<FreeBlock> {\n        &self.next\n    }\n    #[inline] fn prev_mut(&mut self) -> &mut RawLink<FreeBlock> {\n        &mut self.prev\n    }\n    #[inline] fn next_mut(&mut self) -> &mut RawLink<FreeBlock> {\n        &mut self.next\n    }\n}\n\n// Variadic macro for taking the maximum of n > 2 numbers.\n// because I'm lazy.\nmacro_rules! max {\n    ($x:expr) => ($x);\n    ($x:expr, $($xs:expr),+) => (max($x, max!($($xs),+)));\n}\n\n/// Structure with data for implementing the buddy block allocation strategy.\npub struct Heap<'a> {\n    /// Address of the base of the heap. This must be aligned\n    /// on a `MIN_ALIGN` boundary.\n    pub start_addr: Unique<u8>\n  , /// The allocator's free list\n    free_lists: &'a mut [FreeList]\n  , /// Number of blocks in the heap (must be a power of 2)\n    pub heap_size: usize\n  , /// Minimum block size\n    pub min_block_size: usize\n}\n\nimpl<'a> Heap<'a> {\n    /// Construct a new `Heap`.\n    ///\n    /// # Arguments\n    /// + `start_addr`: a pointer to the start location of the heap\n    /// + `free_lists`: an array of [`FreeList`]s. The cardinality\n    ///    of the `free_lists` array should be equal to the maximum\n    ///    allocateable order.\n    /// + `heap_size`: the size of the heap (in bytes)\n    ///\n    /// # Returns\n    /// + A new `Heap`, obviously.\n    ///\n    /// # Panics\n    /// + If `start_addr` is a null pointer or is not page-aligned\n    /// + If the array of `free_lists` is empty\n    /// + If the `heap_size` is too small to contain at least one block, or is\n    ///   not a power of two.\n    /// + If the calculated minimum block size is to small to contain a\n    ///   [`FreeBlock`] header\n    ///\n    /// # Safety\n    /// + If `start_addr` is not valid, you will have a bad time\n    ///\n    /// [`FreeList`]: type.FreeList.html\n    /// [`FreeBlock`]: struct.FreeBlock.html\n    pub unsafe fn new( start_addr: Address\n                     , free_lists: &'a mut [FreeList]\n                     , heap_size: usize)\n                     -> Heap<'a> {\n        // Cache the number of free lists hopefully saving performance.\n        let n_free_lists = free_lists.len();\n\n        assert!( !start_addr.is_null()\n                , \"Heap start address cannot be null.\" );\n        assert!( n_free_lists > 0\n               , \"Allocator must have at least one free list.\");\n        // assert!( start_addr as usize & (PAGE_SIZE-1) as usize == 0\n        //        , \"Heap start address must be aligned on a 4k boundary.\");\n\n        let min_block_size = heap_size >> (n_free_lists - 1);\n\n        assert!( heap_size >= min_block_size\n               , \"Heap must be large enough to contain at least one block.\");\n        assert!( min_block_size >= mem::size_of::<FreeBlock>()\n               , \"Minimum block size must be large enough to contain \\\n                  the free block header.\");\n        assert!( heap_size.is_pow2()\n               , \"Heap size must be a power of 2.\");\n\n    //    // We must have one free list per possible heap block size.\n    //    assert_eq!(min_block_size *\n    //               (2u32.pow(free_lists.len() as u32 - 1)) as usize,\n    //               heap_size);\n\n        // Zero out the free lists in case we were passed existing data.\n        for list in free_lists.iter_mut() {\n            *list = FreeList::new();\n        }\n\n        let mut heap\n            = Heap { start_addr: Unique::new(start_addr)\n                   , free_lists: free_lists\n                   , heap_size: heap_size\n                   , min_block_size: min_block_size\n                   };\n\n        // the order needed to allocate the entire heap as a single block\n        let root_order\n            = heap.alloc_order(&Layout::from_size_align(heap_size, 1))\n                  .expect(\"Couldn't determine heap root allocation order!\\\n                           This should be (as far as I know) impossible.\\\n                           Something is seriously amiss.\");\n\n        // Push the entire heap onto the free lists as the first block.\n        heap.push_block(start_addr, root_order);\n        heap\n    }\n\n    /// Add a block of max order\n    ///\n    /// # Safety\n    /// + This function has no way to guarantee that the given `block` of\n    ///   uninitialized memory is not already in use.\n    pub unsafe fn add_block(&mut self, block: Address) {\n        // TODO: assert the passed block is not a null pointer?\n        //       - eliza, 1/23/2017\n        let order = self.free_lists.len() -1;\n        self.push_block(block, order);\n    }\n\n    /// Computes the size of an allocation request.\n    ///\n    /// # Arguments\n    /// + `size`: A `usize` containing the size of the request\n    /// + `align`: A `usize` containing the alignment of the request\n    ///\n    /// # Returns\n    /// + `None` if the request is invalid\n    /// + `Some(usize)` containing the size needed if the request is valid\n    #[inline]\n    pub fn alloc_size(&self, layout: &Layout) -> Result<usize, AllocErr> {\n        // Pre-check if this is a valid allocation request:\n        //  - allocations must be aligned on power of 2 boundaries\n        //  - we cannot allocate requests with alignments greater than the\n        //    base alignment of the heap without jumping through a bunch of\n        //    hoops.\n        let align = layout.align();\n        debug_assert!(align.is_power_of_two());\n        if align > PAGE_SIZE as usize {\n            Err(AllocErr::Unsupported {\n                details: \"Cannot allocate requests with alignments greater \\\n                          than the base alignment of the heap!\"\n                })\n        // If the request is valid, compute the size we need to allocate\n        } else {\n            // the allocation size for the request is the next power of 2\n            // after the size of the request, the alignment of the request,\n            // or the minimum block size (whichever is greatest).\n            let alloc_size\n                = max!( layout.size(), self.min_block_size, align)\n                    .next_power_of_two();\n\n            if alloc_size > self.heap_size {\n                // if the calculated size is greater than the size of the heap,\n                // we (obviously) cannot allocate this request.\n                Err(AllocErr::Unsupported {\n                    details: \"Cannot allocate requests larger than the heap!\"\n                })\n            } else {\n                // otherwise, return the calculated size.\n                Ok(alloc_size)\n            }\n        }\n    }\n\n    /// Computes the order of an allocation request.\n    ///\n    /// The \"order\" of an allocation refers to the number of times we need to\n    /// double the minimum block size to get a large enough block for that\n    /// allocation.\n    #[inline]\n    pub fn alloc_order(&self, layout: &Layout) -> Result<usize, AllocErr> {\n        trace!(target: \"alloc\", \"TRACE: alloc_order() called\");\n        self.alloc_size(layout)\n            .map(|s| {\n                trace!( target: \"alloc\"\n                      , \"in alloc_order(): alloc_size() returned {}\", s);\n                s.log2() - self.min_block_size.log2()\n            })\n    }\n\n    /// Computes the size  allocated for a request of the given order.\n    #[inline]\n    fn order_alloc_size(&self, order: usize) -> usize {\n        1 << (self.min_block_size.log2() + order)\n    }\n\n    #[inline]\n    unsafe fn push_block(&mut self, ptr: *mut u8, order: usize) {\n        self.free_lists[order]\n            .push_front(Unique::new(ptr as *mut FreeBlock))\n    }\n\n    #[inline]\n    unsafe fn pop_block(&mut self, order: usize) -> Option<*mut u8>{\n        self.free_lists[order]\n            .pop_front()\n            .map(|block| block.as_ref().as_ptr())\n    }\n\n\n    /// Splits a block\n    ///\n    /// # Arguments\n    /// + `block`: a pointer to the block to split\n    /// + `old_order`: the current order of `block`\n    /// + `new_order`: the requested order for the split block\n    ///\n    /// # Safety\n    /// + This function has no guarantee that `block` is not a null pointer.\n    /// + This function has no guarantee that `block` is not already in use --\n    ///   if it is invoked on an already allocated block, that block may be\n    ///   clobbered without warning.\n    /// + This function has no guarantee that `old_order` is the correct order\n    ///   for `block`.\n    ///\n    /// # Panics\n    /// + If `new_order` is less than `old_order`: we make a block _larger_ by\n    ///   splitting it.\n    /// + If `old_order` is larger than the maximum order of this allocator\n    unsafe fn split_block( &mut self\n                         , block: Address\n                         , old_order: usize\n                         , new_order: usize ) {\n        // TODO: assert the passed block is not a null pointer?\n        //       - eliza, 1/23/2017\n        trace!( target: \"alloc\"\n              , \"split_block() was called, target order: {}.\", new_order);\n\n        assert!( new_order < old_order\n               , \"Cannot split a block larger than its current order!\");\n        assert!( old_order <= self.free_lists.len()\n               , \"Order is too large for this allocator!\");\n\n        let mut split_size = self.order_alloc_size(old_order);\n        // let mut curr_order = order;\n        for order in (new_order..old_order).rev() {\n            split_size >>= 1;\n\n            // let split_size = self.order_alloc_size(order);\n            self.push_block(block.offset(split_size as isize), order);\n\n            trace!( target: \"alloc\"\n                  , \"split block successfully, order: {}, split size: {}\"\n                  , order, split_size );\n\n        }\n    }\n\n    /// Finds the buddy block for a given block.\n    ///\n    /// # Arguments\n    /// + `order`: the order of the block to find a buddy for\n    /// + `block`: a pointer to the block to find a buddy for\n    ///\n    /// # Returns\n    /// + `Some(*mut u8)` pointing to the buddy block if a buddy was found\n    /// + `None` if the block was the size of the entire heap\n    pub unsafe fn get_buddy( &self\n                           , order: usize\n                           , block: Address)\n                            -> Option<Address> {\n        // Determine the size of the block allocated for the given order\n        let block_size = self.order_alloc_size(order);\n        if block_size < self.heap_size {\n\n            let start_addr = self.start_addr.as_ptr();\n            debug_assert!( !start_addr.is_null(),\n                \"Start address of a (supposedly) valid heap was null. Something\\\n                 has gone horribly, horribly wrong!\");\n\n            // Determine the block's position in the heap.\n            let block_pos = (block as usize) - (start_addr as usize);\n\n            // Calculate the block's buddy by XORing the block's position\n            // in the heap with its size.\n            let block_offset = (block_pos ^ block_size) as isize;\n            Some(start_addr.offset(block_offset))\n        } else {\n            // If the block is the size of the entire heap, it (obviously)\n            // cannot have a buddy block.\n            None\n        }\n    }\n\n    /// Finds and removes the target block from the free list.\n    ///\n    /// # Arguments\n    /// + `order`: the order of the free list to remove the block from_raw\n    /// + `block`: a pointer to the block to remove\n    ///\n    /// # Returns\n    /// + `true` if the block was found and removed from the free List\n    /// + `false` if the block was not found\n    pub fn remove_block(&mut self, order: usize, block: Address) -> bool {\n        self.free_lists[order]\n            .cursor_mut()\n            .find_and_remove(|b| b as *const FreeBlock as *const u8 == block)\n            .is_some()\n    }\n}\n\n\nunsafe impl<'a> Allocator for Heap<'a> {\n\n    /// Returns a pointer suitable for holding data described by\n    /// `layout`, meeting its size and alignment guarantees.\n    ///\n    /// The returned block of storage may or may not have its contents\n    /// initialized. (Extension subtraits might restrict this\n    /// behavior, e.g. to ensure initialization.)\n    ///\n    /// Returning `Err` indicates that either memory is exhausted or `layout`\n    /// does not meet allocator's size or alignment constraints.\n    ///\n    unsafe fn alloc(&mut self, layout: Layout) -> Result<Address, AllocErr> {\n        trace!(target: \"alloc\", \"allocate() was called!\");\n        // First, compute the allocation order for this request\n        self.alloc_order(&layout)\n            .and_then(|order|\n                if order > self.free_lists.len() - 1 {\n                    Err(AllocErr::Exhausted { request: layout.clone() })\n                } else { Ok(order) } )\n            // If the allocation order is defined, then we try to allocate\n            // a block of that order. Otherwise, the request is invalid.\n            .and_then(|min_order| {\n                trace!( target: \"alloc\"\n                      , \"in allocate(): min alloc order is {}\", min_order);\n                // Starting at the minimum possible order...\n                // TODO: this is ugly and not FP, rewrite.\n                for order in min_order..self.free_lists.len() {\n                    if let Some(block) = self.pop_block(order) {\n                        trace!(target: \"alloc\", \"in allocate(): found block\");\n                        if order > min_order {\n                            trace!( target: \"alloc\"\n                                  , \"in allocate(): order {} is less than \\\n                                     minimum ({}), splitting.\"\n                                  , order, min_order);\n                            self.split_block(block, order, min_order);\n                            trace!( target: \"alloc\"\n                                  , \"in allocate(): split_block() done\");\n\n                        }\n                        return Ok(block)\n                    }\n                }\n                Err(AllocErr::Exhausted { request: layout })\n            })\n    }\n\n    /// Release an allocated block of memory.\n    ///\n    /// The `size` and `align` parameters _must_ be the same as the original\n    /// size and alignment of the frame being deallocated, otherwise our\n    /// heap will become corrupted.\n    ///\n    /// # Arguments\n    /// + `frame`: a pointer to the block of memory to deallocate\n    /// + `size`: the size of the block being deallocated\n    /// + `align`: the alignment of the block being deallocated\n    unsafe fn dealloc(&mut self, ptr: Address, layout: Layout) {\n        let min_order = self.alloc_order(&layout).unwrap();\n\n        // Check if the deallocated block's buddy block is also free.\n        // If it is, merge the two blocks.\n        let mut new_block = ptr;\n        for order in min_order..self.free_lists.len() {\n            // If there is a buddy for this block of the given order...\n            if let Some(buddy) = self.get_buddy(order, ptr) {\n                // ...and if the buddy was free...\n                if self.remove_block(order, buddy) {\n                    // ...merge the buddy with the new block (just use\n                    // the lower address), and keep going.\n                    new_block = min(new_block, buddy);\n                    continue;\n                }\n            }\n            // Otherwise, if we've run out of free buddies, push the new\n            // merged block onto the free lsit and return.\n            self.push_block(new_block, order);\n            return;\n        }\n    }\n}\n"
  },
  {
    "path": "sos_alloc/src/buddy/system.rs",
    "content": "//! This module integrates the buddy heap allocator into the Rust runtime.\nuse spin::Mutex;\nuse core::ptr;\n\nuse ::{Allocator, Layout};\nuse super::{Heap, FreeList};\n\n/// The number of free lists for the kernel heap\npub const NUM_FREE_LISTS: usize = 19;\n\nstatic ALLOC: Mutex<Option<Heap<'static>>>\n    = Mutex::new(None);\n\nstatic mut KERNEL_FREE_LISTS: [FreeList; NUM_FREE_LISTS]\n    // TODO: I really wish there was a less awful way to do this...\n    = [ FreeList::new(),  FreeList::new(), FreeList::new()\n      , FreeList::new(),  FreeList::new(), FreeList::new()\n      , FreeList::new(),  FreeList::new(), FreeList::new()\n      , FreeList::new(),  FreeList::new(), FreeList::new()\n      , FreeList::new(),  FreeList::new(), FreeList::new()\n      , FreeList::new(),  FreeList::new(), FreeList::new()\n      , FreeList::new()\n      , ];\n\n/// Initialize the system heap at the given start address\n///\n/// # Arguments\n/// + `start_addr`: a pointer to the start address of the kernel heap\n/// + `heap_size`: the maximum size (in bytes) of the kernel heap\n///\n/// # Panics\n/// + If called once the kernel heap is already initialized\npub unsafe fn init_heap(start_addr: *mut u8, heap_size: usize ) {\n    assert_has_not_been_called!(\"the kernel heap may not be initialized \\\n                                 more than once!\");\n    trace!(target: \"alloc\", \"init_heap() was called.\");\n    *(ALLOC.lock())\n        = Some(Heap::new( start_addr\n                                      , &mut KERNEL_FREE_LISTS\n                                      , heap_size));\n}\n\n// -- integrate the heap allocator into the Rust runtime ------------------\n#[allow(missing_docs)]\n#[no_mangle]\npub extern \"C\" fn __rust_allocate(size: usize, align: usize) -> *mut u8 {\n    trace!(\"__rust_allocate() was called.\");\n    unsafe {\n        ALLOC.lock().as_mut()\n             .expect(\"Cannot allocate memory, no system allocator exists!\")\n             .alloc(Layout::from_size_align(size, align))\n             .map(|blck| {\n                 // TODO: can we use `inspect()` here instead?\n                 //       - eliza, 1/23/2017\n                 trace!( target: \"alloc\"\n                       , \"__rust_allocate: allocated {:?}\", blck);\n                 blck })\n            // TODO: how to handle various error conditions here in\n            //       ways the stdlib expects?\n            //          - eliza, 02/02/2017\n             .unwrap()\n    }\n}\n#[allow(missing_docs)]\n#[no_mangle]\npub extern \"C\" fn __rust_deallocate( ptr: *mut u8, old_size: usize\n                                   , align: usize ) {\n    unsafe {\n        ALLOC.lock().as_mut()\n             .expect(\"Cannot deallocate memory, no system allocator exists!\")\n             .dealloc(ptr, Layout::from_size_align(old_size, align))\n    }\n}\n\n#[allow(missing_docs)]\n#[no_mangle]\npub extern \"C\" fn __rust_reallocate( ptr: *mut u8, old_size: usize\n                                   , size: usize, align: usize )\n                                   -> *mut u8 {\n    unsafe {\n        ALLOC.lock().as_mut()\n             .expect(\"Cannot reallocate memory, no system allocator exists!\")\n             .realloc( ptr\n                     , Layout::from_size_align(old_size, align)\n                     , Layout::from_size_align(size, align))\n             // TODO: how to handle various error conditions here in\n             //       ways the stdlib expects?\n             //          - eliza, 02/02/2017\n             .unwrap()\n     }\n}\n\n/// This is currently unsupported, so we just silently ignore it\n/// and return the old size.\n#[no_mangle]\npub extern \"C\" fn __rust_reallocate_inplace( _ptr: *mut u8\n                                           , old_size: usize\n                                           , _: usize, _: usize )\n                                           -> usize {\n    old_size\n}\n\n#[allow(missing_docs)]\n#[no_mangle]\npub extern \"C\" fn __rust_usable_size(size: usize, _: usize) -> usize {\n    size\n}\n\n/// A frame allocator using the system's buddy-block heap allocator\n// quick first pass on using the heap allocator as a frame allocator\n// TODO: this is Extremely Bad And Ugly And Awful. pleae make better.\n//       – eliza, 1/21/2017\npub struct BuddyFrameAllocator;\n\nimpl BuddyFrameAllocator {\n    /// Construct a new `BuddyFrameAllocator`\n    pub const fn new() -> Self { BuddyFrameAllocator }\n}\n//\n// impl FrameAllocator for BuddyFrameAllocator {\n//\n//     unsafe fn allocate(&self) -> Option<PhysicalPage> {\n//         ALLOC.lock().as_mut()\n//              .expect(\"Cannot allocate frame, no system allocator exists!\")\n//              .allocate(PAGE_SIZE as usize, PAGE_SIZE as usize)\n//              .map(|block| {\n//                 let addr = VAddr::from_ptr(block);\n//                 // TODO: make this not be bad and ugly.\n//                 PhysicalPage::containing_addr(\n//                     PAddr::from(addr.as_usize() as u64))\n//              })\n//\n//     }\n//\n//     unsafe fn deallocate(&self, frame: PhysicalPage) {\n//         ALLOC.lock().as_mut()\n//              .expect(\"Cannot deallocate frame, no system allocator exists!\")\n//              .deallocate( frame.as_mut_ptr()\n//                         , PAGE_SIZE as usize\n//                         , PAGE_SIZE as usize);\n//\n//     }\n//\n//     unsafe fn allocate_range(&self, _num: usize) -> Option<FrameRange> {\n//         unimplemented!()\n//     }\n//\n//     unsafe fn deallocate_range(&self, range: FrameRange) {\n//         for frame in range {\n//             ALLOC.lock().as_mut()\n//                  .expect(\"Cannot deallocate frames, no system allocator exists\")\n//                  .deallocate( frame.as_mut_ptr()\n//                             , PAGE_SIZE as usize\n//                             , PAGE_SIZE as usize);\n//         }\n//     }\n//\n//\n// }\n"
  },
  {
    "path": "sos_alloc/src/buddy/test.rs",
    "content": "use super::*;\n\nuse ::{Allocator, Layout};\n\nuse core::ptr;\n\nextern \"C\" {\n    /// We need this to allocate aligned memory for our heap.\n    #[cfg(target_os = \"macos\")]\n    #[link_name = \"je_posix_memalign\"]\n    fn memalign(alignment: usize, size: usize) -> *mut u8;\n\n    #[cfg(not(target_os = \"macos\"))]\n    fn memalign(alignment: usize, size: usize) -> *mut u8;\n\n    // Release our memory.\n    fn free(ptr: *mut u8);\n}\n\nconst HEAP_ALIGN: usize = 4096;\nconst HEAP_SIZE: usize = 256;\n\n#[test]\nfn test_allocation_size_and_order() {\n    unsafe {\n        let mem = memalign(HEAP_ALIGN, HEAP_SIZE);\n        let mut free_lists: [FreeList; 5]\n            = [ FreeList::new(), FreeList::new()\n              , FreeList::new(), FreeList::new()\n              , FreeList::new()\n              ];\n        let heap = Heap::new( mem, &mut free_lists, HEAP_SIZE );\n\n        // TEST NEEDED: Can't align beyond MIN_HEAP_ALIGN.\n\n        // Can't align beyond heap_size.\n        assert!(heap.alloc_size(&Layout::from_size_align(256, 256*2)).is_err());\n\n        macro_rules! assert_size {\n            ($(size: $size: expr, align: $align:expr, $result:expr),*) => {\n                $(assert_eq!( $result\n                            , heap.alloc_size(&Layout::from_size_align($size,\n                                $align)));\n                 )*\n            }\n        }\n\n        macro_rules! assert_order {\n            ($(size: $size: expr, align: $align:expr,  $result:expr),*) => {\n                $(assert_eq!( $result\n                            , heap.alloc_order(&Layout::from_size_align($size,\n                                $align)));\n                 )*\n            }\n        }\n\n        // Simple allocations just round up to next block size.\n        assert_size!{ size: 0, align: 1, Ok(16)\n                    , size: 1, align: 1, Ok(16)\n                    , size: 16, align: 1, Ok(16)\n                    , size: 17, align: 1, Ok(32)\n                    , size: 32, align: 32, Ok(32)\n                    , size: 256, align: 256, Ok(256)\n                    };\n        // Aligned allocations use alignment as block size.\n        assert_size!(size: 16, align: 64, Ok(64));\n\n        // Block orders.\n        assert_order!{ size: 0, align: 1, Ok(0)\n                     , size: 1, align: 1, Ok(0)\n                     , size: 16, align: 16, Ok(0)\n                     , size: 32, align: 32, Ok(1)\n                     , size: 64, align: 64, Ok(2)\n                     , size: 128, align: 128, Ok(3)\n                     , size: 256, align: 256, Ok(4)\n                    //  , size: 512, align: 512, Err\n                     };\n        assert!(heap.alloc_order(&Layout::from_size_align(512,512)).is_err());\n        free(mem);\n    }\n}\n\n#[test]\nfn test_get_buddy() {\n    unsafe {\n        let mem = memalign(HEAP_ALIGN, HEAP_SIZE);\n        let mut free_lists: [FreeList; 5]\n            = [ FreeList::new(), FreeList::new()\n              , FreeList::new(), FreeList::new()\n              , FreeList::new()\n              ];\n        let heap = Heap::new( mem\n                                          , &mut free_lists\n                                          , HEAP_SIZE );\n        let block_16_0 = mem;\n        let block_16_1 = mem.offset(16);\n        assert_eq!(Some(block_16_1), heap.get_buddy(0, block_16_0));\n        assert_eq!(Some(block_16_0), heap.get_buddy(0, block_16_1));\n\n        let block_32_0 = mem;\n        let block_32_1 = mem.offset(32);\n        assert_eq!(Some(block_32_1), heap.get_buddy(1, block_32_0));\n        assert_eq!(Some(block_32_0), heap.get_buddy(1, block_32_1));\n\n        let block_32_2 = mem.offset(64);\n        let block_32_3 = mem.offset(96);\n        assert_eq!(Some(block_32_3), heap.get_buddy(1, block_32_2));\n        assert_eq!(Some(block_32_2), heap.get_buddy(1, block_32_3));\n\n        let block_256_0 = mem;\n        assert_eq!(None, heap.get_buddy(4, block_256_0));\n\n        free(mem);\n    }\n}\n\n#[test]\nfn test_alloc_and_dealloc() {\n    unsafe {\n        let mem = memalign(HEAP_ALIGN, HEAP_SIZE);\n        let mut free_lists: [FreeList; 5]\n            = [ FreeList::new(), FreeList::new()\n              , FreeList::new(), FreeList::new()\n              , FreeList::new()\n              ];\n        let mut heap = Heap::new( mem\n                                              , &mut free_lists\n                                              , HEAP_SIZE );\n\n        let block_128_0 = heap.alloc(Layout::from_size_align(128, 128));\n        assert_eq!(Ok(mem.offset(0)), block_128_0);\n\n        heap.dealloc(block_128_0.unwrap(),Layout::from_size_align(128, 128));\n\n        let block_16_0 = heap.alloc(Layout::from_size_align(8, 8));\n        assert_eq!(Ok(mem), block_16_0);\n\n        let bigger_than_heap = heap.alloc(Layout::from_size_align(4096, HEAP_SIZE));\n        assert!(bigger_than_heap.is_err());\n\n        let bigger_than_free = heap.alloc(Layout::from_size_align(HEAP_SIZE, HEAP_SIZE));\n        assert!(bigger_than_free.is_err());\n\n        let block_16_1 = heap.alloc(Layout::from_size_align(8, 8));\n        assert_eq!(Ok(mem.offset(16)), block_16_1);\n\n        let block_16_2 = heap.alloc(Layout::from_size_align(8, 8));\n        assert_eq!(Ok(mem.offset(32)), block_16_2);\n\n        let block_32_2 = heap.alloc(Layout::from_size_align(32, 32));\n        assert_eq!(Ok(mem.offset(64)), block_32_2);\n\n        let block_16_3 = heap.alloc(Layout::from_size_align(8, 8))      ;\n        assert_eq!(Ok(mem.offset(48)), block_16_3);\n\n        // let too_fragmented = heap.alloc(Layout::from_size_align(64, 64);\n        // assert_eq!(None, too_fragmented);\n        heap.dealloc(block_16_0.unwrap(), Layout::from_size_align(8, 8));\n        heap.dealloc(block_16_3.unwrap(), Layout::from_size_align(8, 8));\n        heap.dealloc(block_16_1.unwrap(), Layout::from_size_align(8, 8));\n        heap.dealloc(block_16_2.unwrap(), Layout::from_size_align(8, 8));\n\n        heap.dealloc(block_32_2.unwrap(), Layout::from_size_align(32, 32));\n\n        let block_128_0 = heap.alloc(Layout::from_size_align(128, 128));\n        assert_eq!(Ok(mem.offset(0)), block_128_0);\n\n        let block_128_1 = heap.alloc(Layout::from_size_align(128, 128));\n        assert_eq!(Ok(mem.offset(128)), block_128_1);\n\n        heap.dealloc(block_128_1.unwrap(), Layout::from_size_align(128, 128));\n        heap.dealloc(block_128_0.unwrap(), Layout::from_size_align(128, 128));\n\n        // And allocate the whole heap, just to make sure everything\n        // got cleaned up correctly.\n        let block_256_0 = heap.alloc(Layout::from_size_align(256, 256)).unwrap();\n        assert_eq!(mem.offset(0), block_256_0);\n\n        free(mem);\n    }\n}\n"
  },
  {
    "path": "sos_alloc/src/bump_ptr.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (hi@hawkweisman.me)\n//\n//  Copyright (c) 2015-2017 Eliza Weisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\n\nuse memory::{Addr, PAddr};\nuse super::{Address, Allocator, AllocErr, Layout};\n\n/// A simple bump pointer allocator.\n///\n/// This allocator has few \"moving parts\" and is very fast. However, it doesn't\n/// allow objects to be deallocated. We use this allocator for early kernel\n/// objects before we can set up a more sophisticated heap allocator.\n#[derive(Debug)]\npub struct BumpPtr { start: PAddr\n                   , end: PAddr\n                   , ptr: PAddr\n                   }\n\nimpl BumpPtr {\n    pub const fn new(start: PAddr, end: PAddr) -> Self {\n        BumpPtr { start: start\n                , end: end\n                , ptr: start\n                }\n    }\n}\n\nunsafe impl Allocator for BumpPtr {\n    unsafe fn alloc(&mut self, layout: Layout) -> Result<Address, AllocErr> {\n        let start = self.ptr.align_up(layout.align() as <PAddr as Addr>::Repr);\n        // TODO: can this be a saturating add?\n        let end = start + layout.size() as <PAddr as Addr>::Repr;\n        if end > self.end {\n            Err(AllocErr::Exhausted{ request: layout.clone() })\n        } else {\n            // bump\n            self.ptr = end;\n            Ok(start.as_mut_ptr())\n        }\n    }\n    unsafe fn dealloc(&mut self, _ptr: Address, _layout: Layout) {\n        // just leak it\n    }\n}\n"
  },
  {
    "path": "sos_alloc/src/first_fit.rs",
    "content": "use arrayvec::ArrayVec;\nuse memory::{Page, MemRange, PhysicalPage, FrameRange};\nuse super::FrameAllocator;\nuse spin::Mutex;\n\nconst SIZE: usize = 256;\n\n/// A simple first-fit allocator for allocating page frames.\npub struct FirstFit<'a> {\n    frames: &'a Mutex<ArrayVec<[FrameRange; SIZE]>>\n}\n\nimpl<'a> FrameAllocator for FirstFit<'a> {\n\n    unsafe fn allocate(&self) -> Option<PhysicalPage> {\n        unimplemented!()\n    }\n\n    unsafe fn deallocate(&self, _frame: PhysicalPage) {\n        unimplemented!()\n    }\n\n    unsafe fn allocate_range(&self, num: usize) -> Option<FrameRange> {\n        let mut frames = self.frames.lock();\n        frames.iter()\n            .position(|range| range.length() >= num)\n            .map(|i| {\n                if num < frames[i].length() {\n                    frames[i].drop_front(num);\n                } else {\n                    frames.remove(i);\n                }\n                frames[i].start.range_of(num)\n            })\n    }\n\n    unsafe fn deallocate_range(&self, _range: FrameRange) {\n        unimplemented!()\n    }\n\n}\n"
  },
  {
    "path": "sos_alloc/src/frame/mem_map.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza Weisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\n//! A simple allocator using the [`InitParams`] memory map.\n//!\n//! This is basically just a bump pointer allocator for frames; since\n//! it doesn't support deallocating frames.\nuse super::{Frame, FrameRange, Allocator};\nuse ::{AllocResult, AllocErr, Layout};\nuse params::{InitParams, mem};\nuse memory::{Page, PAGE_SIZE, PAddr};\n\nuse core::iter::Step;\nuse core::convert::From;\n/// A simple area allocator.\n///\n/// This is based on the memory area allocation scheme described\n/// by Phil Oppermann at [http://os.phil-opp.com/allocating-frames.html].\n///\n/// This is Not A Good Allocation Scheme, as it does not currently support\n/// reallocation of freed frames. The plan is that it will only be used\n/// initially, and after we've allocated everything once, we'll switch over\n/// to a better allocator.\npub struct MemMapAllocator<'a> { next_free: Frame\n                               , current_area: Option<&'a mem::Area>\n                               , areas: mem::Map<'a>\n                               , kernel_frames: FrameRange\n                               , mb_frames: FrameRange\n                               }\nimpl<'a> MemMapAllocator<'a> {\n    fn next_area(&mut self) {\n        // println!(\"In next_area\");\n        self.current_area\n            = self.areas.clone()\n                  .filter(|a|\n                      Frame::containing(a.end_addr) >= self.next_free)\n                  .min_by_key(|a| a.start_addr)\n                  .map(|area| {\n                      let start = Frame::containing(area.start_addr);\n                      if self.next_free > start { self.next_free = start };\n                      area\n                  })\n    }\n\n}\n\nimpl<'a> From<&'a InitParams> for MemMapAllocator<'a> {\n    fn from(params: &'a InitParams) -> Self {\n        let mut new_allocator = MemMapAllocator {\n              next_free: Frame::containing(PAddr::new(0x12000))\n            , current_area: None\n            , areas: params.mem_map()\n            , kernel_frames: params.kernel_frames()\n            // TODO: handle non-multiboot case\n            , mb_frames: Frame::containing(params.multiboot_start()) ..\n                         Frame::containing(params.multiboot_end()).add_one()\n            };\n        trace!(\"creating mem map allocator\");\n        trace!(\"kernel frames: {:?}\", new_allocator.kernel_frames);\n        trace!(\"multiboot frames: {:?}\", new_allocator.mb_frames);\n        new_allocator.next_area();\n        new_allocator\n    }\n}\n\nimpl<'a> Allocator for MemMapAllocator<'a> {\n    // type Frame = Frame;\n\n    unsafe fn allocate(&mut self) -> AllocResult<Frame> {\n        // // println!(\"In alloc method\");\n        if let Some(area) = self.current_area {\n            let frame = Frame { number: self.next_free.number };\n            match frame {\n                // all frames in the current memory area are in use\n                f if f > Frame::containing(area.end_addr) => {\n                    // so we advance to the next free area\n\n                    // println!(\"All frames in current area in use.\");\n                    self.next_area();\n                    // println!(\"...and returning None\");\n                }\n              , // this frame is in use by the kernel.\n                f if f >= self.kernel_frames.start && f <= self.kernel_frames.end => {\n                    // skip ahead to the end of the kernel\n                    // println!(\"In kernel frame, skipping.\");\n                    self.next_free = self.kernel_frames.end.add_one();\n                    // println!(\"...and returning None\");\n                }\n              , // this frame is part of the multiboot info.\n                f if f >= self.mb_frames.start && f <= self.mb_frames.end=> {\n                    // skip ahead to the end of the multiboot info.\n                    // println!(\"In multiboot frame, skipping...\");\n                    self.next_free = self.mb_frames.end.add_one();\n                    // println!(\"...and returning None\");\n                }\n              , // this frame is free.\n                frame => {\n                    // advance the next free frame and return this frame.\n                    // println!(\"In free frame, advancing...\");\n                    self.next_free = self.next_free.add_one();\n                    // println!(\"...and returning {:?}\", frame);\n                    trace!(\"allocated {:?}\", frame);\n                    return Ok(frame)\n                }\n            };\n            self.allocate()\n        } else {\n            // println!(\"No free frames remain!\");\n            Err(AllocErr::Exhausted {\n                    request: Layout::from_size_align( PAGE_SIZE as usize, PAGE_SIZE as usize)\n            })\n        }\n    }\n\n    /// Deallocate a frame\n    unsafe fn deallocate(&mut self, _frame: Frame) {\n        // just leak it\n    }\n\n    /// Allocate a range of frames\n    unsafe fn allocate_range(&mut self, _num: usize) -> AllocResult<FrameRange> {\n        unimplemented!()\n    }\n    /// Deallocate a range of frames\n    unsafe fn deallocate_range(&mut self, _range: FrameRange) {\n        //just leak it\n    }\n}\n"
  },
  {
    "path": "sos_alloc/src/frame/mod.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza Weisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\n//! Frame allocation\n#![warn(missing_docs)]\nuse memory::{FrameRange, PhysicalPage as Frame};\nuse super::AllocResult;\nuse core::ops;\nuse spin::Mutex;\n\npub mod mem_map;\n\n/// An allocator for allocating physical frames.\npub trait Allocator: Sized  {\n\n    /// Allocate a new frame\n    unsafe fn allocate(&mut self) -> AllocResult<Frame>;\n    /// Deallocate a frame\n    unsafe fn deallocate(&mut self, frame: Frame);\n\n    /// Allocate a range of frames\n    unsafe fn allocate_range(&mut self, num: usize) -> AllocResult<FrameRange>;\n    /// Deallocate a range of frames\n    unsafe fn deallocate_range(&mut self, range: FrameRange);\n\n}\n\n/// An allocator capable of lending [borrowed frame]s\n///\n/// [borrowed frame]: struct.BorrowedFrame.html\npub trait Lender<A>\nwhere A: Allocator {\n    /// Borrow a `Frame` from this allocator.\n    ///e\n    /// The `BorrowedFrame` will live as long as this allocator, and will\n    /// contain a handle on a `Frame` that will be automatically deallocated\n    /// when the `BorrowedFrame` is dropped.\n    ///\n    /// # Returns\n    /// + `Some(BorrowedFrame)` if there are frames remaining in this\n    ///    allocator.\n    /// + `None` if the allocator is out of frames.\n    //  TODO: do we want to refactor this into returning Results?\n    //          - eliza, 02/21/2017\n    fn borrow(&self) -> AllocResult<BorrowedFrame<A>>;\n\n    /// Borrow a `FrameRange` from this allocator.\n    ///\n    /// The `BorrowedFrameRange` will live as long as this allocator, and will\n    /// contain a handle on a range of `Frame`s that will be automatically\n    /// deallocated when the `BorrowedFrameRange` is dropped.\n    ///\n    /// # Arguments\n    /// + `num`: The number of frames to allocate.\n    ///\n    /// # Returns\n    /// + `Some(BorrowedFrameRange)` if there are enough `Frame`s\n    ///    remaining in the allocator to fulfill the allocation\n    ///    request.\n    /// + `None` if there are not enough frames in the allocator to fulfill the\n    ///   allocation request.\n    //  TODO: do we want to refactor this into returning Results?\n    //          - eliza, 02/21/2017\n    fn borrow_range(&self, num: usize) -> AllocResult<BorrowedFrameRange<A>>;\n\n}\n\nimpl<A: Allocator> Lender<A> for Mutex<A> {\n\n    fn borrow(&self) -> AllocResult<BorrowedFrame<A>> {\n        // TODO: can this be rewritten to just use `self.borrow_range(1)`?\n        //          - eliza, 02/21/2017\n        unsafe { self.lock().allocate() }\n                     .map(|frame| BorrowedFrame { frame: frame\n                                                , allocator: self })\n    }\n\n    fn borrow_range(&self, num: usize) -> AllocResult<BorrowedFrameRange<A>> {\n        unsafe { self.lock().allocate_range(num) }\n                     .map(|range| BorrowedFrameRange { range: range\n                                                     , allocator: self })\n    }\n\n\n\n}\n\n/// A borrowed handle on a frame with a specified lifetime.\n///\n/// This automatically deallocates the frame when the borrow's lifetime\n/// ends. It also ensures that the borrow only lives as long as the allocator\n/// that provided it, and that the borrow is dropped if the allocator is\n/// dropped.\npub struct BorrowedFrame<'alloc, A>\nwhere A: Allocator\n    , A: 'alloc {\n    frame: Frame\n  , allocator: &'alloc Mutex<A>\n}\n\nimpl<'alloc, A> ops::Deref for BorrowedFrame<'alloc, A>\nwhere A: Allocator\n    , A: 'alloc {\n    type Target = Frame;\n    fn deref(&self) ->  &Self::Target { &self.frame }\n}\n\nimpl<'alloc, A> ops::DerefMut for BorrowedFrame<'alloc, A>\nwhere A: Allocator\n    , A: 'alloc {\n    fn deref_mut(&mut self) ->  &mut Self::Target { &mut self.frame }\n}\n\nimpl<'alloc, A> Drop for BorrowedFrame<'alloc, A>\nwhere A: Allocator\n    , A: 'alloc {\n    fn drop(&mut self) {\n        unsafe { self.allocator.lock().deallocate(self.frame) }\n    }\n}\n\n/// Identical to a `BorrowedFrame` but borrowing a range of `Frame`s.\npub struct BorrowedFrameRange<'alloc, A>\nwhere A: Allocator\n    , A: 'alloc {\n    range: FrameRange\n  , allocator: &'alloc Mutex<A>\n}\n\nimpl<'alloc, A> ops::Deref for BorrowedFrameRange<'alloc, A>\nwhere A: Allocator\n    , A: 'alloc {\n    type Target = FrameRange;\n    fn deref(&self) -> &Self::Target { &self.range }\n}\n\nimpl<'alloc, A> ops::DerefMut for BorrowedFrameRange<'alloc, A>\nwhere A: Allocator\n    , A: 'alloc {\n    fn deref_mut(&mut self) -> &mut Self::Target { &mut self.range }\n}\n\nimpl<'alloc, A> Drop for BorrowedFrameRange<'alloc, A>\nwhere A: Allocator\n    , A: 'alloc {\n    fn drop(&mut self) {\n        unsafe { self.allocator.lock().deallocate_range(self.range.clone()) }\n    }\n}\n"
  },
  {
    "path": "sos_alloc/src/free.rs",
    "content": "use core::ptr::Unique;\nuse core::mem;\n\nuse intrusive::list::{List as IList, Node};\nuse intrusive::rawlink::RawLink;\n\n/// A `FreeList` is a list of unique free blocks\npub type List = IList<Unique<Block>, Block>;\n\n/// A free block header stores a pointer to the next and previous free blocks.\n///\n/// A `Block` can be any size, as long as\npub struct Block { next: RawLink<Block>\n                 , prev: RawLink<Block>\n                 }\nimpl Block {\n    #[inline] pub unsafe fn as_ptr(&self) -> *mut u8 { mem::transmute(self) }\n}\n\nimpl Node for Block {\n    #[inline] fn prev(&self) -> &RawLink<Block> {\n        &self.prev\n    }\n    #[inline] fn next(&self) -> &RawLink<Block> {\n        &self.next\n    }\n    #[inline] fn prev_mut(&mut self) -> &mut RawLink<Block> {\n        &mut self.prev\n    }\n    #[inline] fn next_mut(&mut self) -> &mut RawLink<Block> {\n        &mut self.next\n    }\n}\n"
  },
  {
    "path": "sos_alloc/src/lib.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza Weisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\n//  Allocator API copyright 2015 The Rust Project Developers.\n//  See the COPYRIGHT file at http://rust-lang.org/COPYRIGHT.\n//\n//  Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or\n//  http://www.apache.org/licenses/LICENSE-2.0> or the MIT license\n//  <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your\n//  option. This file may not be copied, modified, or distributed\n//  except according to those terms.\n//! SOS memory allocation library\n//!\n//! This is in its own crate so it can be used by kernel-space and user-space\n//! OS components.\n//!\n//! We reproduce the Rust [`Allocator`] trait described in Rust [RFC 1398], so\n//! that our allocators can implement it. Once RFC 1398 is implemented, we will\n//! be able to remove the [`Allocator`] and [`Layout`] types from this crate.\n//!\n//! For more information on the Allocator API, refer to:\n//! + the text of [RFC 1398]\n//! + rust-lang/rust [tracking issue]\n//!\n//! [`Allocator`]: trait.Allocator.html\n//! [`Layout`]: struct.Layout.html\n//! [RFC 1398]: https://github.com/rust-lang/rfcs/blob/master/text/1398-kinds-of-allocators.md\n//! [tracking issue]: https://github.com/rust-lang/rust/issues/32838\n#![crate_name = \"sos_alloc\"]\n#![crate_type = \"lib\"]\n\n// The compiler needs to be instructed that this crate is an allocator in order\n// to realize that when this is linked in another allocator like jemalloc\n// should not be linked in\n#![cfg_attr( feature = \"system\", feature(allocator) )]\n#![cfg_attr( feature = \"system\", allocator )]\n\n#![cfg_attr(feature = \"clippy\", feature(plugin))]\n#![cfg_attr(feature = \"clippy\", plugin(clippy))]\n\n#![cfg_attr( feature = \"placement_in\"\n           , feature(placement_new_protocol, placement_in_syntax))]\n\n// Allocators are not allowed to depend on the standard library which in turn\n// requires an allocator in order to avoid circular dependencies. This crate,\n// however, can use all of libcore.\n#![no_std]\n\n#![feature(const_fn)]\n#![feature(unique)]\n#![feature(core_intrinsics)]\n#![feature(step_trait)]\n\n#![cfg_attr(all(test, feature = \"bench\"), feature(test))]\n#![cfg_attr(test, feature(collections))]\n#[cfg(all(test, feature = \"bench\"))] extern crate test;\n#[cfg(test)] extern crate collections;\n\nextern crate memory;\n\n#[cfg(feature = \"first_fit\")]\nextern crate arrayvec;\n\n#[cfg(feature = \"buddy\")]\nextern crate sos_intrusive as intrusive;\n\nextern crate spin;\n\n#[cfg(feature = \"buddy_as_system\")]\n#[macro_use] extern crate once;\n\n#[macro_use] extern crate log;\n\nextern crate params;\n\nuse core::{cmp, ops, ptr, mem};\nuse ptr::Unique;\n\npub type AllocResult<T> = Result<T, AllocErr>;\n\npub type Size = usize;\npub type Capacity = usize;\npub type Alignment = usize;\n\npub type Address = *mut u8;\n\npub mod frame;\npub use frame::{Allocator as FrameAllocator, Lender as FrameLender};\n\n/// Represents the combination of a starting address and\n/// a total capacity of the returned block.\npub struct Excess(Address, Capacity);\n\nfn size_align<T>() -> (usize, usize) {\n    (mem::size_of::<T>(), mem::align_of::<T>())\n}\n\n/// Category for a memory record.\n///\n/// An instance of `Layout` describes a particular layout of memory.\n/// You build a `Layout` up as an input to give to an allocator.\n///\n/// All layouts have an associated non-negative size and positive alignment.\n#[derive(Clone, Debug, PartialEq, Eq)]\npub struct Layout {\n    // size of the requested block of memory, measured in bytes.\n    size: Size,\n    // alignment of the requested block of memory, measured in bytes.\n    // we ensure that this is always a power-of-two, because API's\n    // like `posix_memalign` require it and it is a reasonable\n    // constraint to impose on Layout constructors.\n    //\n    // (However, we do not analogously require `align >= sizeof(void*)`,\n    //  even though that is *also* a requirement of `posix_memalign`.)\n    align: Alignment,\n}\n\n\n// FIXME: audit default implementations for overflow errors,\n// (potentially switching to overflowing_add and\n//  overflowing_mul as necessary).\n\nimpl Layout {\n    // (private constructor)\n    pub fn from_size_align(size: usize, align: usize) -> Layout {\n        assert!(align.is_power_of_two());\n        assert!(align > 0);\n        Layout { size: size, align: align }\n    }\n\n    /// The minimum size in bytes for a memory block of this layout.\n    pub fn size(&self) -> usize { self.size }\n\n    /// The minimum byte alignment for a memory block of this layout.\n    pub fn align(&self) -> usize { self.align }\n\n    /// Constructs a `Layout` suitable for holding a value of type `T`.\n    pub fn new<T>() -> Self {\n        let (size, align) = size_align::<T>();\n        Layout::from_size_align(size, align)\n    }\n\n    /// Produces layout describing a record that could be used to\n    /// allocate backing structure for `T` (which could be a trait\n    /// or other unsized type like a slice).\n    pub fn for_value<T: ?Sized>(t: &T) -> Self {\n        let (size, align) = (mem::size_of_val(t), mem::align_of_val(t));\n        Layout::from_size_align(size, align)\n    }\n\n    /// Creates a layout describing the record that can hold a value\n    /// of the same layout as `self`, but that also is aligned to\n    /// alignment `align` (measured in bytes).\n    ///\n    /// If `self` already meets the prescribed alignment, then returns\n    /// `self`.\n    ///\n    /// Note that this method does not add any padding to the overall\n    /// size, regardless of whether the returned layout has a different\n    /// alignment. In other words, if `K` has size 16, `K.align_to(32)`\n    /// will *still* have size 16.\n    pub fn align_to(&self, align: Alignment) -> Self {\n        if align > self.align {\n            let pow2_align = align.checked_next_power_of_two().unwrap();\n            debug_assert!(pow2_align > 0); // (this follows from self.align > 0...)\n            Layout { align: pow2_align,\n                     ..*self }\n        } else {\n            self.clone()\n        }\n    }\n\n    /// Returns the amount of padding we must insert after `self`\n    /// to ensure that the following address will satisfy `align`\n    /// (measured in bytes).\n    ///\n    /// Behavior undefined if `align` is not a power-of-two.\n    ///\n    /// Note that in practice, this is only useable if `align <=\n    /// self.align` otherwise, the amount of inserted padding would\n    /// need to depend on the particular starting address for the\n    /// whole record, because `self.align` would not provide\n    /// sufficient constraint.\n    pub fn padding_needed_for(&self, align: Alignment) -> usize {\n        debug_assert!(align <= self.align());\n        let len = self.size();\n        let len_rounded_up = (len + align - 1) & !(align - 1);\n        return len_rounded_up - len;\n    }\n\n    /// Creates a layout describing the record for `n` instances of\n    /// `self`, with a suitable amount of padding between each to\n    /// ensure that each instance is given its requested size and\n    /// alignment. On success, returns `(k, offs)` where `k` is the\n    /// layout of the array and `offs` is the distance between the start\n    /// of each element in the array.\n    ///\n    /// On arithmetic overflow, returns `None`.\n    pub fn repeat(&self, n: usize) -> Option<(Self, usize)> {\n        let padded_size = match self.size.checked_add(self.padding_needed_for(self.align)) {\n            None => return None,\n            Some(padded_size) => padded_size,\n        };\n        let alloc_size = match padded_size.checked_mul(n) {\n            None => return None,\n            Some(alloc_size) => alloc_size,\n        };\n        Some((Layout::from_size_align(alloc_size, self.align), padded_size))\n    }\n\n    /// Creates a layout describing the record for `self` followed by\n    /// `next`, including any necessary padding to ensure that `next`\n    /// will be properly aligned. Note that the result layout will\n    /// satisfy the alignment properties of both `self` and `next`.\n    ///\n    /// Returns `Some((k, offset))`, where `k` is layout of the concatenated\n    /// record and `offset` is the relative location, in bytes, of the\n    /// start of the `next` embedded witnin the concatenated record\n    /// (assuming that the record itself starts at offset 0).\n    ///\n    /// On arithmetic overflow, returns `None`.\n    pub fn extend(&self, next: Self) -> Option<(Self, usize)> {\n        let new_align = cmp::max(self.align, next.align);\n        let realigned = Layout { align: new_align, ..*self };\n        let pad = realigned.padding_needed_for(new_align);\n        let offset = self.size() + pad;\n        let new_size = offset + next.size();\n        Some((Layout::from_size_align(new_size, new_align), offset))\n    }\n\n    /// Creates a layout describing the record for `n` instances of\n    /// `self`, with no padding between each instance.\n    ///\n    /// On arithmetic overflow, returns `None`.\n    pub fn repeat_packed(&self, n: usize) -> Option<Self> {\n        let scaled = match self.size().checked_mul(n) {\n            None => return None,\n            Some(scaled) => scaled,\n        };\n        let size = { assert!(scaled > 0); scaled };\n        Some(Layout { size: size, align: self.align })\n    }\n\n    /// Creates a layout describing the record for `self` followed by\n    /// `next` with no additional padding between the two. Since no\n    /// padding is inserted, the alignment of `next` is irrelevant,\n    /// and is not incoporated *at all* into the resulting layout.\n    ///\n    /// Returns `(k, offset)`, where `k` is layout of the concatenated\n    /// record and `offset` is the relative location, in bytes, of the\n    /// start of the `next` embedded witnin the concatenated record\n    /// (assuming that the record itself starts at offset 0).\n    ///\n    /// (The `offset` is always the same as `self.size()`; we use this\n    ///  signature out of convenience in matching the signature of\n    ///  `fn extend`.)\n    ///\n    /// On arithmetic overflow, returns `None`.\n    pub fn extend_packed(&self, next: Self) -> Option<(Self, usize)> {\n        let new_size = match self.size().checked_add(next.size()) {\n            None => return None,\n            Some(new_size) => new_size,\n        };\n        Some((Layout { size: new_size, ..*self }, self.size()))\n    }\n\n    // Below family of methods *assume* inputs are pre- or\n    // post-validated in some manner. (The implementations here\n    ///do indirectly validate, but that is not part of their\n    /// specification.)\n    //\n    // Since invalid inputs could yield ill-formed layouts, these\n    // methods are `unsafe`.\n\n    /// Creates layout describing the record for a single instance of `T`.\n    pub unsafe fn new_unchecked<T>() -> Self {\n        let (size, align) = size_align::<T>();\n        Layout::from_size_align(size, align)\n    }\n\n\n    /// Creates a layout describing the record for `self` followed by\n    /// `next`, including any necessary padding to ensure that `next`\n    /// will be properly aligned. Note that the result layout will\n    /// satisfy the alignment properties of both `self` and `next`.\n    ///\n    /// Returns `(k, offset)`, where `k` is layout of the concatenated\n    /// record and `offset` is the relative location, in bytes, of the\n    /// start of the `next` embedded witnin the concatenated record\n    /// (assuming that the record itself starts at offset 0).\n    ///\n    /// Requires no arithmetic overflow from inputs.\n    pub unsafe fn extend_unchecked(&self, next: Self) -> (Self, usize) {\n        self.extend(next).unwrap()\n    }\n\n    /// Creates a layout describing the record for `n` instances of\n    /// `self`, with a suitable amount of padding between each.\n    ///\n    /// Requires non-zero `n` and no arithmetic overflow from inputs.\n    /// (See also the `fn array` checked variant.)\n    pub unsafe fn repeat_unchecked(&self, n: usize) -> (Self, usize) {\n        self.repeat(n).unwrap()\n    }\n\n    /// Creates a layout describing the record for `n` instances of\n    /// `self`, with no padding between each instance.\n    ///\n    /// Requires non-zero `n` and no arithmetic overflow from inputs.\n    /// (See also the `fn array_packed` checked variant.)\n    pub unsafe fn repeat_packed_unchecked(&self, n: usize) -> Self {\n        self.repeat_packed(n).unwrap()\n    }\n\n    /// Creates a layout describing the record for `self` followed by\n    /// `next` with no additional padding between the two. Since no\n    /// padding is inserted, the alignment of `next` is irrelevant,\n    /// and is not incoporated *at all* into the resulting layout.\n    ///\n    /// Returns `(k, offset)`, where `k` is layout of the concatenated\n    /// record and `offset` is the relative location, in bytes, of the\n    /// start of the `next` embedded witnin the concatenated record\n    /// (assuming that the record itself starts at offset 0).\n    ///\n    /// (The `offset` is always the same as `self.size()`; we use this\n    ///  signature out of convenience in matching the signature of\n    ///  `fn extend`.)\n    ///\n    /// Requires no arithmetic overflow from inputs.\n    /// (See also the `fn extend_packed` checked variant.)\n    pub unsafe fn extend_packed_unchecked(&self, next: Self) -> (Self, usize) {\n        self.extend_packed(next).unwrap()\n    }\n\n    /// Creates a layout describing the record for a `[T; n]`.\n    ///\n    /// On zero `n`, zero-sized `T`, or arithmetic overflow, returns `None`.\n    pub fn array<T>(n: usize) -> Option<Self> {\n        Layout::new::<T>()\n            .repeat(n)\n            .map(|(k, offs)| {\n                debug_assert!(offs == mem::size_of::<T>());\n                k\n            })\n    }\n\n    /// Creates a layout describing the record for a `[T; n]`.\n    ///\n    /// Requires nonzero `n`, nonzero-sized `T`, and no arithmetic\n    /// overflow; otherwise behavior undefined.\n    pub fn array_unchecked<T>(n: usize) -> Self {\n        Layout::array::<T>(n).unwrap()\n    }\n\n}\n\n/// The `AllocErr` error specifies whether an allocation failure is\n/// specifically due to resource exhaustion or if it is due to\n/// something wrong when combining the given input arguments with this\n/// allocator.\n#[derive(Clone, PartialEq, Eq, Debug)]\npub enum AllocErr {\n    /// Error due to hitting some resource limit or otherwise running\n    /// out of memory. This condition strongly implies that *some*\n    /// series of deallocations would allow a subsequent reissuing of\n    /// the original allocation request to succeed.\n    Exhausted { request: Layout },\n\n    /// Error due to allocator being fundamentally incapable of\n    /// satisfying the original request. This condition implies that\n    /// such an allocation request will never succeed on the given\n    /// allocator, regardless of environment, memory pressure, or\n    /// other contextual condtions.\n    ///\n    /// For example, an allocator that does not support zero-sized\n    /// blocks can return this error variant.\n    Unsupported { details: &'static str },\n}\n\nimpl AllocErr {\n    pub fn invalid_input(details: &'static str) -> Self {\n        AllocErr::Unsupported { details: details }\n    }\n    pub fn is_memory_exhausted(&self) -> bool {\n        if let AllocErr::Exhausted { .. } = *self { true } else { false }\n    }\n    pub fn is_request_unsupported(&self) -> bool {\n        if let AllocErr::Unsupported { .. } = *self { true } else { false }\n    }\n}\n\n/// The `CannotReallocInPlace` error is used when `fn realloc_in_place`\n/// was unable to reuse the given memory block for a requested layout.\n#[derive(Clone, PartialEq, Eq, Debug)]\npub struct CannotReallocInPlace;\n\n/// An implementation of `Allocator` can allocate, reallocate, and\n/// deallocate arbitrary blocks of data described via `Layout`.\n///\n/// Some of the methods require that a layout *fit* a memory block.\n/// What it means for a layout to \"fit\" a memory block means is that\n/// the following two conditions must hold:\n///\n/// 1. The block's starting address must be aligned to `layout.align()`.\n///\n/// 2. The block's size must fall in the range `[use_min, use_max]`, where:\n///\n///    * `use_min` is `self.usable_size(layout).0`, and\n///\n///    * `use_max` is the capacity that was (or would have been)\n///      returned when (if) the block was allocated via a call to\n///      `alloc_excess` or `realloc_excess`.\n///\n/// Note that:\n///\n///  * the size of the layout most recently used to allocate the block\n///    is guaranteed to be in the range `[use_min, use_max]`, and\n///\n///  * a lower-bound on `use_max` can be safely approximated by a call to\n///    `usable_size`.\n///\npub unsafe trait Allocator {\n    /// Returns a pointer suitable for holding data described by\n    /// `layout`, meeting its size and alignment guarantees.\n    ///\n    /// The returned block of storage may or may not have its contents\n    /// initialized. (Extension subtraits might restrict this\n    /// behavior, e.g. to ensure initialization.)\n    ///\n    /// Returning `Err` indicates that either memory is exhausted or `layout`\n    /// does not meet allocator's size or alignment constraints.\n    ///\n    /// Implementations are encouraged to return `Err` on memory\n    /// exhaustion rather than panicking or aborting, but this is\n    /// not a strict requirement. (Specifically: it is *legal* to use\n    /// this trait to wrap an underlying native allocation library\n    /// that aborts on memory exhaustion.)\n    unsafe fn alloc(&mut self, layout: Layout) -> Result<Address, AllocErr>;\n\n    /// Deallocate the memory referenced by `ptr`.\n    ///\n    /// `ptr` must have previously been provided via this allocator,\n    /// and `layout` must *fit* the provided block (see above);\n    /// otherwise yields undefined behavior.\n    unsafe fn dealloc(&mut self, ptr: Address, layout: Layout);\n\n    /// Allocator-specific method for signalling an out-of-memory\n    /// condition.\n    ///\n    /// Implementations of the `oom` method are discouraged from\n    /// infinitely regressing in nested calls to `oom`. In\n    /// practice this means implementors should eschew allocating,\n    /// especially from `self` (directly or indirectly).\n    ///\n    /// Implementions of this trait's allocation methods are discouraged\n    /// from panicking (or aborting) in the event of memory exhaustion;\n    /// instead they should return an appropriate error from the\n    /// invoked method, and let the client decide whether to invoke\n    /// this `oom` method.\n    fn oom(&mut self, _: AllocErr) -> ! {\n        unsafe { ::core::intrinsics::abort() }\n    }\n\n    // == ALLOCATOR-SPECIFIC QUANTITIES AND LIMITS ==\n    // usable_size\n\n    /// Returns bounds on the guaranteed usable size of a successful\n    /// allocation created with the specified `layout`.\n    ///\n    /// In particular, for a given layout `k`, if `usable_size(k)` returns\n    /// `(l, m)`, then one can use a block of layout `k` as if it has any\n    /// size in the range `[l, m]` (inclusive).\n    ///\n    /// (All implementors of `fn usable_size` must ensure that\n    /// `l <= k.size() <= m`)\n    ///\n    /// Both the lower- and upper-bounds (`l` and `m` respectively) are\n    /// provided: An allocator based on size classes could misbehave\n    /// if one attempts to deallocate a block without providing a\n    /// correct value for its size (i.e., one within the range `[l, m]`).\n    ///\n    /// Clients who wish to make use of excess capacity are encouraged\n    /// to use the `alloc_excess` and `realloc_excess` instead, as\n    /// this method is constrained to conservatively report a value\n    /// less than or equal to the minimum capacity for *all possible*\n    /// calls to those methods.\n    ///\n    /// However, for clients that do not wish to track the capacity\n    /// returned by `alloc_excess` locally, this method is likely to\n    /// produce useful results.\n    unsafe fn usable_size(&self, layout: &Layout) -> (Capacity, Capacity) {\n        (layout.size(), layout.size())\n    }\n\n    // == METHODS FOR MEMORY REUSE ==\n   // realloc. alloc_excess, realloc_excess\n\n   /// Returns a pointer suitable for holding data described by\n   /// `new_layout`, meeting its size and alignment guarantees. To\n   /// accomplish this, this may extend or shrink the allocation\n   /// referenced by `ptr` to fit `new_layout`.\n   ///\n   /// * `ptr` must have previously been provided via this allocator.\n   ///\n   /// * `layout` must *fit* the `ptr` (see above). (The `new_layout`\n   ///   argument need not fit it.)\n   ///\n   /// Behavior undefined if either of latter two constraints are unmet.\n   ///\n   /// In addition, `new_layout` should not impose a different alignment\n   /// constraint than `layout`. (In other words, `new_layout.align()`\n   /// should equal `layout.align()`.)\n   /// However, behavior is well-defined (though underspecified) when\n   /// this constraint is violated; further discussion below.\n   ///\n   /// If this returns `Ok`, then ownership of the memory block\n   /// referenced by `ptr` has been transferred to this\n   /// allocator. The memory may or may not have been freed, and\n   /// should be considered unusable (unless of course it was\n   /// transferred back to the caller again via the return value of\n   /// this method).\n   ///\n   /// Returns `Err` only if `new_layout` does not meet the allocator's\n   /// size and alignment constraints of the allocator or the\n   /// alignment of `layout`, or if reallocation otherwise fails. (Note\n   /// that did not say \"if and only if\" -- in particular, an\n   /// implementation of this method *can* return `Ok` if\n   /// `new_layout.align() != old_layout.align()`; or it can return `Err`\n   /// in that scenario, depending on whether this allocator\n   /// can dynamically adjust the alignment constraint for the block.)\n   ///\n   /// If this method returns `Err`, then ownership of the memory\n   /// block has not been transferred to this allocator, and the\n   /// contents of the memory block are unaltered.\n   unsafe fn realloc(&mut self,\n                     ptr: Address,\n                     layout: Layout,\n                     new_layout: Layout) -> Result<Address, AllocErr> {\n       let (min, max) = self.usable_size(&layout);\n       let s = new_layout.size();\n       // All Layout alignments are powers of two, so a comparison\n       // suffices here (rather than resorting to a `%` operation).\n       if min <= s && s <= max && new_layout.align() <= layout.align() {\n           return Ok(ptr);\n       } else {\n           let new_size = new_layout.size();\n           let old_size = layout.size();\n           let result = self.alloc(new_layout);\n           if let Ok(new_ptr) = result {\n               ptr::copy(ptr as *const u8, new_ptr, cmp::min(old_size, new_size));\n               self.dealloc(ptr, layout);\n           }\n           result\n       }\n   }\n\n   /// Behaves like `fn alloc`, but also returns the whole size of\n   /// the returned block. For some `layout` inputs, like arrays, this\n   /// may include extra storage usable for additional data.\n   unsafe fn alloc_excess(&mut self, layout: Layout) -> Result<Excess, AllocErr> {\n       let usable_size = self.usable_size(&layout);\n       self.alloc(layout).map(|p| Excess(p, usable_size.1))\n   }\n\n   /// Behaves like `fn realloc`, but also returns the whole size of\n   /// the returned block. For some `layout` inputs, like arrays, this\n   /// may include extra storage usable for additional data.\n   unsafe fn realloc_excess(&mut self,\n                            ptr: Address,\n                            layout: Layout,\n                            new_layout: Layout) -> Result<Excess, AllocErr> {\n       let usable_size = self.usable_size(&new_layout);\n       self.realloc(ptr, layout, new_layout)\n           .map(|p| Excess(p, usable_size.1))\n   }\n\n   /// Attempts to extend the allocation referenced by `ptr` to fit `new_layout`.\n   ///\n   /// * `ptr` must have previously been provided via this allocator.\n   ///\n   /// * `layout` must *fit* the `ptr` (see above). (The `new_layout`\n   ///   argument need not fit it.)\n   ///\n   /// Behavior undefined if either of latter two constraints are unmet.\n   ///\n   /// If this returns `Ok`, then the allocator has asserted that the\n   /// memory block referenced by `ptr` now fits `new_layout`, and thus can\n   /// be used to carry data of that layout. (The allocator is allowed to\n   /// expend effort to accomplish this, such as extending the memory block to\n   /// include successor blocks, or virtual memory tricks.)\n   ///\n   /// If this returns `Err`, then the allocator has made no assertion\n   /// about whether the memory block referenced by `ptr` can or cannot\n   /// fit `new_layout`.\n   ///\n   /// In either case, ownership of the memory block referenced by `ptr`\n   /// has not been transferred, and the contents of the memory block\n   /// are unaltered.\n   unsafe fn realloc_in_place(&mut self,\n                              ptr: Address,\n                              layout: Layout,\n                              new_layout: Layout) -> Result<(), CannotReallocInPlace> {\n       let (_, _, _) = (ptr, layout, new_layout);\n       Err(CannotReallocInPlace)\n   }\n\n    // == COMMON USAGE PATTERNS ==\n    // alloc_one, dealloc_one, alloc_array, realloc_array. dealloc_array\n\n    /// Allocates a block suitable for holding an instance of `T`.\n    ///\n    /// Captures a common usage pattern for allocators.\n    ///\n    /// The returned block is suitable for passing to the\n    /// `alloc`/`realloc` methods of this allocator.\n    ///\n    /// May return `Err` for zero-sized `T`.\n    unsafe fn alloc_one<T>(&mut self) -> Result<Unique<T>, AllocErr>\n        where Self: Sized {\n        let k = Layout::new::<T>();\n        if k.size() > 0 {\n            self.alloc(k).map(|p|Unique::new(*p as *mut T))\n        } else {\n            Err(AllocErr::invalid_input(\"zero-sized type invalid for alloc_one\"))\n        }\n    }\n\n    /// Deallocates a block suitable for holding an instance of `T`.\n    ///\n    /// The given block must have been produced by this allocator,\n    /// and must be suitable for storing a `T` (in terms of alignment\n    /// as well as minimum and maximum size); otherwise yields\n    /// undefined behavior.\n    ///\n    /// Captures a common usage pattern for allocators.\n    unsafe fn dealloc_one<T>(&mut self, mut ptr: Unique<T>)\n        where Self: Sized {\n        let raw_ptr = ptr.as_mut() as *mut T as *mut u8;\n        self.dealloc(raw_ptr, Layout::new::<T>());\n    }\n\n    /// Allocates a block suitable for holding `n` instances of `T`.\n    ///\n    /// Captures a common usage pattern for allocators.\n    ///\n    /// The returned block is suitable for passing to the\n    /// `alloc`/`realloc` methods of this allocator.\n    ///\n    /// May return `Err` for zero-sized `T` or `n == 0`.\n    ///\n    /// Always returns `Err` on arithmetic overflow.\n    unsafe fn alloc_array<T>(&mut self, n: usize) -> Result<Unique<T>, AllocErr>\n        where Self: Sized {\n        match Layout::array::<T>(n) {\n            Some(ref layout) if layout.size() > 0 => {\n                self.alloc(layout.clone())\n                    .map(|p| {\n                        // println!(\"alloc_array layout: {:?} yielded p: {:?}\", layout, p);\n                        Unique::new(p as *mut T)\n                    })\n            }\n            _ => Err(AllocErr::invalid_input(\"invalid layout for alloc_array\")),\n        }\n    }\n\n    /// Reallocates a block previously suitable for holding `n_old`\n    /// instances of `T`, returning a block suitable for holding\n    /// `n_new` instances of `T`.\n    ///\n    /// Captures a common usage pattern for allocators.\n    ///\n    /// The returned block is suitable for passing to the\n    /// `alloc`/`realloc` methods of this allocator.\n    ///\n    /// May return `Err` for zero-sized `T` or `n == 0`.\n    ///\n    /// Always returns `Err` on arithmetic overflow.\n    unsafe fn realloc_array<T>(&mut self,\n                               ptr: Unique<T>,\n                               n_old: usize,\n                               n_new: usize) -> Result<Unique<T>, AllocErr>\n        where Self: Sized {\n        match ( Layout::array::<T>(n_old)\n              , Layout::array::<T>(n_new)\n              , ptr.as_ptr()) {\n            (Some(ref k_old), Some(ref k_new), ptr) if k_old.size() > 0 && k_new.size() > 0 => {\n                self.realloc(ptr as *mut u8, k_old.clone(), k_new.clone())\n                    .map(|p|Unique::new(p as *mut T))\n            }\n            _ => {\n                Err(AllocErr::invalid_input(\"invalid layout for realloc_array\"))\n            }\n        }\n    }\n\n    /// Deallocates a block suitable for holding `n` instances of `T`.\n    ///\n    /// Captures a common usage pattern for allocators.\n    unsafe fn dealloc_array<T>(&mut self, ptr: Unique<T>, n: usize) -> Result<(), AllocErr>\n        where Self: Sized {\n        let raw_ptr = ptr.as_ptr() as *mut u8;\n        match Layout::array::<T>(n) {\n            Some(ref k) if k.size() > 0 => {\n                Ok(self.dealloc(raw_ptr, k.clone()))\n            }\n            _ => {\n                Err(AllocErr::invalid_input(\"invalid layout for dealloc_array\"))\n            }\n        }\n    }\n\n    // UNCHECKED METHOD VARIANTS\n\n    /// Returns a pointer suitable for holding data described by\n    /// `layout`, meeting its size and alignment guarantees.\n    ///\n    /// The returned block of storage may or may not have its contents\n    /// initialized. (Extension subtraits might restrict this\n    /// behavior, e.g. to ensure initialization.)\n    ///\n    /// Returns `None` if request unsatisfied.\n    ///\n    /// Behavior undefined if input does not meet size or alignment\n    /// constraints of this allocator.\n    unsafe fn alloc_unchecked(&mut self, layout: Layout) -> Option<Address> {\n        // (default implementation carries checks, but impl's are free to omit them.)\n        self.alloc(layout).ok()\n    }\n\n    /// Returns a pointer suitable for holding data described by\n    /// `new_layout`, meeting its size and alignment guarantees. To\n    /// accomplish this, may extend or shrink the allocation\n    /// referenced by `ptr` to fit `new_layout`.\n    ////\n    /// (In other words, ownership of the memory block associated with\n    /// `ptr` is first transferred back to this allocator, but the\n    /// same block may or may not be transferred back as the result of\n    /// this call.)\n    ///\n    /// * `ptr` must have previously been provided via this allocator.\n    ///\n    /// * `layout` must *fit* the `ptr` (see above). (The `new_layout`\n    ///   argument need not fit it.)\n    ///\n    /// * `new_layout` must meet the allocator's size and alignment\n    ///    constraints. In addition, `new_layout.align()` must equal\n    ///    `layout.align()`. (Note that this is a stronger constraint\n    ///    that that imposed by `fn realloc`.)\n    ///\n    /// Behavior undefined if any of latter three constraints are unmet.\n    ///\n    /// If this returns `Some`, then the memory block referenced by\n    /// `ptr` may have been freed and should be considered unusable.\n    ///\n    /// Returns `None` if reallocation fails; in this scenario, the\n    /// original memory block referenced by `ptr` is unaltered.\n    unsafe fn realloc_unchecked(&mut self,\n                                ptr: Address,\n                                layout: Layout,\n                                new_layout: Layout) -> Option<Address> {\n        // (default implementation carries checks, but impl's are free to omit them.)\n        self.realloc(ptr, layout, new_layout).ok()\n    }\n\n    /// Behaves like `fn alloc_unchecked`, but also returns the whole\n    /// size of the returned block.\n    unsafe fn alloc_excess_unchecked(&mut self, layout: Layout) -> Option<Excess> {\n        self.alloc_excess(layout).ok()\n    }\n\n    /// Behaves like `fn realloc_unchecked`, but also returns the\n    /// whole size of the returned block.\n    unsafe fn realloc_excess_unchecked(&mut self,\n                                       ptr: Address,\n                                       layout: Layout,\n                                       new_layout: Layout) -> Option<Excess> {\n        self.realloc_excess(ptr, layout, new_layout).ok()\n    }\n\n\n    /// Allocates a block suitable for holding `n` instances of `T`.\n    ///\n    /// Captures a common usage pattern for allocators.\n    ///\n    /// Requires inputs are non-zero and do not cause arithmetic\n    /// overflow, and `T` is not zero sized; otherwise yields\n    /// undefined behavior.\n    unsafe fn alloc_array_unchecked<T>(&mut self, n: usize) -> Option<Unique<T>>\n        where Self: Sized {\n        let layout = Layout::array_unchecked::<T>(n);\n        self.alloc_unchecked(layout).map(|p|Unique::new(*p as *mut T))\n    }\n\n    /// Reallocates a block suitable for holding `n_old` instances of `T`,\n    /// returning a block suitable for holding `n_new` instances of `T`.\n    ///\n    /// Captures a common usage pattern for allocators.\n    ///\n    /// Requires inputs are non-zero and do not cause arithmetic\n    /// overflow, and `T` is not zero sized; otherwise yields\n    /// undefined behavior.\n    unsafe fn realloc_array_unchecked<T>(&mut self,\n                                         ptr: Unique<T>,\n                                         n_old: usize,\n                                         n_new: usize) -> Option<Unique<T>>\n        where Self: Sized {\n        let (k_old, k_new, ptr) = ( Layout::array_unchecked::<T>(n_old)\n                                  , Layout::array_unchecked::<T>(n_new)\n                                  , ptr.as_ptr());\n        self.realloc_unchecked(ptr as *mut u8, k_old, k_new)\n            .map(|p|Unique::new(*p as *mut T))\n    }\n\n    /// Deallocates a block suitable for holding `n` instances of `T`.\n    ///\n    /// Captures a common usage pattern for allocators.\n    ///\n    /// Requires inputs are non-zero and do not cause arithmetic\n    /// overflow, and `T` is not zero sized; otherwise yields\n    /// undefined behavior.\n    unsafe fn dealloc_array_unchecked<T>(&mut self, ptr: Unique<T>, n: usize)\n        where Self: Sized {\n        let layout = Layout::array_unchecked::<T>(n);\n        self.dealloc(ptr.as_ptr() as *mut u8, layout);\n    }\n}\n\n\n#[cfg(feature = \"borrow\")] pub mod borrow;\n\n#[cfg(feature = \"buddy\")]\npub mod buddy;\n#[cfg(feature = \"first_fit\")]\npub mod first_fit;\n#[cfg(feature = \"bump_ptr\")]\npub mod bump_ptr;\n\n#[cfg(feature = \"system\")] pub mod system;\n#[cfg(feature = \"system\")] pub use system::*;\n\n#[cfg(feature = \"placement_in\")] pub mod place;\n#[cfg(feature = \"placement_in\")] pub use place::*;\n"
  },
  {
    "path": "sos_alloc/src/place.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (hi@hawkweisman.me)\n//\n//  Copyright (c) 2015-2017 Eliza Weisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\n//! Support for placement expressions & box placement.\n//!\n//! See Rust [issue #27779] for more information.\n//!\n//! [issue #27779]: https://github.com/rust-lang/rust/issues/27779\nuse core::ops::{BoxPlace, Place, Placer, InPlace};\nuse core::ptr::Unique;\nuse core::marker::PhantomData;\n\nuse super::{Layout, Allocator};\n\nuse spin::Mutex;\n\n/// A [`Place`] representing an intermediate allocoation attempt.\n///\n/// [`Place`]: https://doc.rust-lang.org/std/ops/trait.Place.html\npub struct IntermediateAlloc<'alloc, A, T>\nwhere T: ?Sized\n    , A: Allocator {\n    ptr: Unique<T>\n  , layout: Layout\n  , alloc: &'alloc Mutex<A>\n}\n\nimpl Placer<'alloc, Data, A> for &'alloc Mutex<A>\nwhere A: Allocator\n    , Data: ? Sized {\n\n        type Place = IntermediateAlloc<'alloc, A, Data>;\n\n        /// Creates a fresh place from `self`.\n        fn make_place(self) -> Self::Place {\n            IntermediateAlloc { ptr: self.lock()\n                                         .alloc_one::<T>()\n                                         .unwrap()\n                              , layout: Layout::new::<T>()\n                              , alloc: self }\n        }\n}\n\nimpl<'alloc, A, Data> Place<Data> for IntermediateAlloc<'alloc, A, Data>\nwhere Data: ?Sized\n    , A: Allocator {\n\n        #[inline] fn pointer(&mut self) -> *mut Data {\n            self.ptr\n        }\n}\n\nimpl<'alloc, A, Data> InPlace<Data> for IntermediateAlloc<'alloc, A, Data>\nwhere Data: ?Sized\n    , A: Allocator {\n\n        /// `Owner` is the type of the end value of `in (PLACE) EXPR`\n        ///\n        /// Note that when `in (PLACE) EXPR` is solely used for\n        /// side-effecting an existing data-structure,\n        /// e.g. `Vec::emplace_back`, then `Owner` need not carry any\n        /// information at all (e.g. it can be the unit type `()` in that\n        /// case).\n        type Owner = Data;\n\n        /// Converts self into the final value, shifting\n        /// deallocation/cleanup responsibilities (if any remain), over to\n        /// the returned instance of `Owner` and forgetting self.\n        unsafe fn finalize(self) -> Self::Owner {\n            unimplemented!()\n        }\n}\n"
  },
  {
    "path": "sos_alloc/src/system.rs",
    "content": "use spin::Mutex;\nuse super::{Address, Allocator, AllocErr, Layout, AllocResult};\nuse core::ops::Deref;\n\n#[cfg(feature = \"borrow\")]\nuse borrow::{Borrowed, BorrowedPtr};\n\n#[cfg(feature = \"bump_ptr\")]\nuse bump_ptr::BumpPtr;\n\n#[cfg(feature = \"buddy\")]\nuse buddy::Heap as BuddyHeap;\n\npub enum Tier<'a> {\n    Uninitialized\n    , #[cfg(feature = \"bump_ptr\")]\n      Bump(BumpPtr)\n    , #[cfg(feature = \"buddy\")]\n      Buddy(BuddyHeap<'a>)\n}\n#[cfg(all(feature = \"bump_ptr\", feature=\"buddy\"))]\nimpl Deref for Tier<'static> {\n    type Target = Allocator + 'static ;\n    fn deref(&self) -> &Self::Target{\n        match self {\n            &Tier::Bump(ref alloc) => alloc\n          , &Tier::Buddy(ref alloc) => alloc\n          , _ => panic!(\"no allocator!\")\n        }\n    }\n}\n\n#[cfg(all(feature = \"bump_ptr\", feature = \"buddy\"))]\nunsafe impl<'a> Allocator for Tier<'a> {\n    #[inline(always)]\n    unsafe fn alloc(&mut self, layout: Layout) -> AllocResult<Address> {\n        match *self {\n            Tier::Bump(ref mut alloc) => alloc.alloc(layout)\n          , Tier::Buddy(ref mut alloc) => alloc.alloc(layout)\n          , _ => Err(AllocErr::Unsupported {\n                    details: \"System allocator uninitialized!\"\n                })\n        }\n    }\n\n    #[inline(always)]\n    unsafe fn dealloc(&mut self, ptr: Address, layout: Layout) {\n        match *self {\n            Tier::Bump(ref mut alloc) => alloc.dealloc(ptr, layout)\n          , Tier::Buddy(ref mut alloc) => alloc.dealloc(ptr, layout)\n          , _ =>  {\n              // just leak it? not sure if we should panic here...\n          }\n        }\n    }\n\n}\n\npub struct SystemAllocator(Mutex<Tier<'static>>);\n\n#[cfg(feature = \"borrow\")]\nimpl SystemAllocator {\n\n    /// Borrow a raw allocation from the system allocator\n    ///\n    /// The borrowed allocation handle will automagically deallocate the\n    /// allocation at the end of its lifetime\n    pub fn borrow_ptr<'alloc>(&'alloc self, layout: Layout)\n                      -> AllocResult<BorrowedPtr<'alloc, Tier<'static>>> {\n        let ptr = unsafe { self.0.lock().alloc(layout.clone())? };\n        Ok(BorrowedPtr::new(ptr, layout, &self.0))\n    }\n\n    /// Borrow an object allocation from the system allocator.\n    ///\n    /// The borrowed allocation handle will automagically deallocate the\n    /// allocated object at the end of its lifetime\n    pub fn borrow<'alloc, T>(&'alloc self)\n                        -> AllocResult<Borrowed<'alloc, Tier<'static>, T>> {\n        let value = unsafe { self.0.lock().alloc_one::<T>()? };\n        Ok(Borrowed::new(value, &self.0 ))\n    }\n}\n"
  },
  {
    "path": "sos_intrusive/Cargo.toml",
    "content": "[package]\nname = \"sos_intrusive\"\nversion = \"0.1.0\"\nauthors = [\"Eliza Weisman <eliza@elizas.website>\"]\n\n[features]\ndefault = []\nno-std = []\n"
  },
  {
    "path": "sos_intrusive/src/lib.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza Weisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\n//! # SOS Intrusive Collections\n//!\n//! _Intrusive_ data structures are data structures whose elements are\n//! \"aware\" of the structures in which they are stored. That is to say\n//! that data related to the layout and structure of an intrusive collection\n//! is stored by the elements in the collection, rather than internally to\n//! them.\n//!\n//! Intrusive data structures are useful for low-level programming in Rust\n//! since they do not explicitly allocate memory. This means that we can use\n//! intrusive structures to implement the kernel memory allocator and other\n//! kernel subsystems which require structures such as lists prior to\n//! the initialization of the kernel heap.\n//!\n//! This crate currently provides an intrusive linked-list implementation.\n//!\n//! # Features\n//! + `use-std`: use the Rust standard library (`std`), rather than `core`.\n#![crate_name = \"sos_intrusive\"]\n#![crate_type = \"lib\"]\n#![feature( const_fn\n          , const_ptr_null_mut )]\n#![feature(ptr_internals)]\n#![feature(unique )]\n#![cfg_attr(not(feature = \"use-std\"), no_std )]\n#![cfg_attr(feature = \"clippy\", feature(plugin))]\n#![cfg_attr(feature = \"clippy\", plugin(clippy))]\n\n#![cfg_attr(test, feature(box_syntax))]\n\npub mod rawlink;\npub use rawlink::RawLink;\npub mod list;\npub use list::List;\n\n#[cfg(test)]\nextern crate std;\n"
  },
  {
    "path": "sos_intrusive/src/list/mod.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza Weisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\n//! An intrusive linked list implementation using `RawLink`s.\n//!\n//! An _intrusive_ list is a list structure wherein the type of element stored\n//! in the list holds references to other nodes. This means that we don't have\n//! to store a separate node data type that holds the stored elements and\n//! pointers to other nodes, reducing the amount of memory allocated. We can\n//! use intrusive lists in code that runs without the kernel memory allocator,\n//! like the allocator implementation itself, since each list element manages\n//! its own memory.\nuse super::rawlink::RawLink;\n\nuse core::marker::PhantomData;\nuse core::ptr::Unique;\nuse core::iter;\n#[cfg(test)] mod test;\n\npub unsafe trait OwnedRef<T> {\n    unsafe fn from_raw(ptr: *mut T) -> Self;\n    unsafe fn take(self);\n    fn get(&self) -> &T;\n    fn get_mut(&mut self) -> &mut T;\n}\n\n/// This trait defines a node in an intrusive list.\n///\n/// A Node must be capable of providing mutable and immutable references to\n/// the previous and next nodes in the list.\npub trait Node: Sized {\n    fn next(&self) -> &RawLink<Self>;\n    fn prev(&self) -> &RawLink<Self>;\n\n    fn next_mut(&mut self) -> &mut RawLink<Self>;\n    fn prev_mut(&mut self) -> &mut RawLink<Self>;\n}\n\n/// The `List` struct is our way of interacting with an intrusive list.\n///\n/// It stores a pointer to the head and tail of the list, the length of the\n/// list, and a `PhantomData` marker for the list's `OwnedRef` type. It\n/// provides the methods for pushing, popping, and indexing the list.\npub struct List<T, N>\nwhere T: OwnedRef<N>\n    , N: Node {\n    head: RawLink<N>\n  , tail: RawLink<N>\n  , _ty_marker: PhantomData<T>\n  , length: usize\n }\n\n // impl<T> Node for List<T>\n // where T: OwnedRef\n //     , T: Node {\n //\n //    fn next(&self) -> &RawLink<Self> { &self.head }\n //    fn prev(&self) -> &RawLink<Self> { &self.tail }\n //\n //    fn next_mut(&mut self) -> &mut RawLink<Self> { self.head }\n //    fn prev_mut(&mut self) -> &mut RawLink<Self> { self.tail }\n // }\nimpl<T, N> List<T, N>\nwhere T: OwnedRef<N>\n    , N: Node {\n\n    /// Construct a new `List<T, N>` with zero elements\n    pub const fn new() -> Self {\n        List { head: RawLink::none()\n             , tail: RawLink::none()\n             , _ty_marker: PhantomData\n             , length: 0 }\n    }\n\n    /// Returns the length of the list\n    #[inline] pub fn len(&self) -> usize {\n        self.length\n    }\n\n    /// Borrows the first element of the list as an `Option`\n    ///\n    /// # Returns\n    ///   - `Some(&N)` if the list has elements\n    ///   - `None` if the list is empty.\n    #[inline] pub fn front(&self) -> Option<&N> {\n        unsafe { self.head.resolve() }\n    }\n\n\n    /// Borrows the last element of the list as an `Option`\n    ///\n    /// # Returns\n    ///   - `Some(&N)` if the list has elements\n    ///   - `None` if the list is empty.\n    #[inline] pub fn back(&self) -> Option<&N> {\n        unsafe { self.tail.resolve() }\n    }\n\n    /// Mutably borrows the first element of the list as an `Option`\n    ///\n    /// # Returns\n    ///   - `Some(&mut N)` if the list has elements\n    ///   - `None` if the list is empty.\n    #[inline] pub fn front_mut(&mut self) -> Option<&mut N> {\n        unsafe { self.head.resolve_mut() }\n    }\n\n    /// Mutably borrows the last element of the list as an `Option`\n    ///\n    /// # Returns\n    ///   - `Some(&mut N)` if the list has elements\n    ///   - `None` if the list is empty.\n    #[inline] pub fn back_mut(&mut self) -> Option<&mut N> {\n        unsafe { self.tail.resolve_mut() }\n    }\n\n    /// Returns true if the list is empty.\n    #[inline] pub fn is_empty(&self) -> bool {\n        self.head.is_none()\n    }\n\n    /// Push an element to the front of the list.\n    // TODO: should this really be called \"prepend\"?\n    pub fn push_front(&mut self, mut item: T) {\n        unsafe {\n            match self.head.resolve_mut() {\n                None => {\n                    // If this node's head is empty, set the pushed item's\n                    // links to None, and make this node's tail point to the\n                    // pushed item\n                    *item.get_mut().next_mut() = RawLink::none();\n                    *item.get_mut().prev_mut() = RawLink::none();\n                    self.tail = RawLink::some(item.get_mut());\n                }\n              , Some(head) => {\n                    // If this node is not empty, set the pushed item's tail\n                    // to point at the head node, and make the head node's tail\n                    // point to the pushed item\n                    *item.get_mut().next_mut() = RawLink::some(head);\n                    *item.get_mut().prev_mut() = RawLink::none();\n                    *head.prev_mut() = RawLink::some(item.get_mut());\n                }\n            }\n            // then, set this node's head pointer to point to the pushed item\n            self.head = RawLink::some(item.get_mut());\n            item.take();\n            self.length += 1;\n        }\n    }\n\n    /// Push an element to the back of the list.\n    //  TODO: should this really be called \"append\"?\n    //  (the Rust standard library uses `append` to refer to the \"drain all the\n    //  elements of another list and push them to this list\" operation, but I\n    //  think that that function is more properly called `concat`...)\n    pub fn push_back(&mut self, mut item: T) {\n        unsafe {\n            match self.tail.resolve_mut() {\n                None => {\n                    // If this node's tail is empty, set the pushed item's\n                    // links to  None, and make this node's head point to the\n                    // pushed item\n                    *item.get_mut().next_mut() = RawLink::none();\n                    *item.get_mut().prev_mut() = RawLink::none();\n                    self.head = RawLink::some(item.get_mut());\n                }\n              , Some(tail) => {\n                    // If this node is not empty, set the pushed item's head\n                    // to point at the tail node, and make the tail node's head\n                    // point to the pushed item\n                    *item.get_mut().next_mut() = RawLink::none();\n                    *item.get_mut().prev_mut() = RawLink::some(tail);\n                    *tail.next_mut() = RawLink::some(item.get_mut());\n                }\n            }\n            // then, set this node's head pointer to point to the pushed item\n            self.tail = RawLink::some(item.get_mut());\n            item.take();\n            self.length += 1;\n        }\n    }\n\n    /// Removes and returns the element at the front of the list.\n    ///\n    /// # Returns\n    ///   - `Some(T)` containing the element at the front of the list if the\n    ///     list is not empty\n    ///   - `None` if the list is empty\n    pub fn pop_front(&mut self) -> Option<T> {\n        unsafe {\n            self.head.take().resolve_mut()\n                .map(|head| {\n                    // mem::swap( &mut self.head\n                    //          , head.next_mut().resolve_mut()\n                    //                .map(|next| next.prev_mut())\n                    //                .unwrap_or(&mut RawLink::none()) );\n                    match head.next_mut().resolve_mut() {\n                        None => self.tail = RawLink::none()\n                      , Some(next) => {\n                            *next.prev_mut() = RawLink::none();\n                            self.head = RawLink::some(next);\n                        }\n                    }\n                    self.length -= 1;\n                    T::from_raw(head)\n                })\n        }\n    }\n\n    /// Removes and returns the element at the end of the list.\n    ///\n    /// # Returns\n    ///   - `Some(T)` containing the element at the end of the list if the\n    ///     list is not empty\n    ///   - `None` if the list is empty\n    pub fn pop_back(&mut self) -> Option<T> {\n        unsafe {\n            self.tail.take().resolve_mut()\n                .map(|tail| {\n                    match tail.prev_mut().resolve_mut() {\n                        None => self.head = RawLink::none()\n                      , Some(prev) => {\n                            *prev.next_mut() = RawLink::none();\n                            self.tail = RawLink::some(prev);\n                        }\n                    }\n                    self.length -= 1;\n                    T::from_raw(tail)\n                })\n        }\n    }\n\n    /// Borrows the element at the front of the list\n    ///\n    /// # Returns\n    ///   - `Some(&T)` containing the element at the end of the list if the\n    ///     list is not empty\n    ///   - `None` if the list is empty\n    pub fn peek_front(&self) -> Option<&N> {\n        unsafe { self.tail.resolve() }\n    }\n\n    /// Returns a cursor for iterating over or modifying the list.\n    pub fn cursor_mut<'a>(&'a mut self) -> ListCursorMut<'a, T, N> {\n        ListCursorMut { list: self\n                      , current: RawLink::none() }\n    }\n\n}\n\nimpl<T, N> iter::FromIterator<T> for List<T, N>\nwhere T: OwnedRef<N>\n    , N: Node {\n        fn from_iter<I: IntoIterator<Item=T>>(iterator: I) -> Self {\n            let mut list: Self = List::new();\n            for item in iterator { list.push_front(item) }\n            list\n        }\n}\n\npub trait Cursor {\n    type Item;\n\n    fn next(&mut self) -> Option<Self::Item>;\n    fn prev(&mut self) -> Option<Self::Item>;\n    fn get(&self) -> Option<Self::Item>;\n    fn seek_forward(&mut self, n: usize) -> Option<Self::Item>;\n    fn seek_backward(&mut self, n: usize) -> Option<Self::Item>;\n\n}\n\n/// A cursor for an intrusive linked list.\n///\n/// A cursor functions similarly to an iterator, except that it can seek back\n/// and forth rather than just advancing through the list, and it can mutate\n/// the element \"under\" the cursor.\n///\n/// A cursor begins before the first element in the list, and once it has been\n/// advanced past the last element of the list, it \"loops around\" back to the\n/// first element.\n// TODO: can we implement `Iterator` for cursors?\npub struct ListCursorMut<'a, T, N>\nwhere T: OwnedRef<N>\n    , T: 'a\n    , N: Node\n    , N: 'a {\n        list: &'a mut List<T, N>\n      , current: RawLink<N>\n}\n\nimpl<'a, T, N> ListCursorMut<'a, T, N>\nwhere T: OwnedRef<N>\n    , T: 'a\n    , N: Node\n    , N: 'a {\n\n    /// Advances the cursor to the next element and borrows it mutably.\n    ///\n    /// If the cursor is at the end of the list, this advances it back to the\n    /// first element.\n    ///\n    /// # Returns\n    ///   - `Some(&mut N)` if the list is not empty\n    ///   - `None` if the list is empty\n    pub fn next(&mut self) -> Option<&mut N> {\n        unsafe {\n            match self.current.take().resolve_mut() {\n                // The cursor has no current element, so we are sitting in the\n                // cursor's start position. The next element should be the head\n                // of the list...\n                None => self.list.head.resolve_mut()\n                            .and_then(|head| {\n                                // if we resolved a head element, make it the\n                                // current element and return a reference to it\n                                self.current = RawLink::some(head);\n                                self.current.resolve_mut()\n                            })\n                // The cursor did have a current element, so try to advance\n                // to that item's next element\n              , Some(thing) => {\n                    // Set the current element under the cursor to either\n                    // the element after the old current, or None if this is\n                    // the last element.\n                    self.current = match thing.next_mut().resolve_mut() {\n                        None => RawLink::none()\n                      , Some(other_thing) => RawLink::some(other_thing)\n                    };\n                    // and return it\n                    self.current.resolve_mut()\n                }\n            }\n        }\n    }\n\n    /// Steps back the cursor to the previous element and borrows it mutably.\n    ///\n    /// # Returns\n    ///   - `Some(&mut N)` if the list is not empty\n    ///   - `None` if the list is empty\n    pub fn prev(&mut self) -> Option<&mut N> {\n        unimplemented!()\n    }\n\n    /// Borrows the next element in the list without advancing the cursor.\n    ///\n    /// If the cursor is at the end of the list, this returns the first element\n    /// instead.\n    ///\n    /// # Returns\n    ///   - `Some(&N)` if the list is not empty\n    ///   - `None` if the list is empty\n    pub fn peek_next(&self) -> Option<&N> {\n        unsafe {\n            self.current.resolve()\n                .map_or( self.list.front()\n                       , |curr| curr.next().resolve())\n        }\n    }\n\n    /// Borrows the previous element without stepping back the cursor.\n    ///\n    /// If the cursor is at the head of the list, this returns `None`.\n    ///\n    /// # Returns\n    ///   - `Some(&N)` if the list is not empty\n    ///   - `None` if the list is empty or if the cursor is at the head\n    ///     of the list\n    pub fn peek_prev(&self) -> Option<&N> {\n        unsafe {\n            self.current.resolve()\n                .and_then(|curr| curr.prev().resolve())\n        }\n    }\n\n    /// Removes the element currently under the cursor and returns it.\n    ///\n    /// # Returns\n    ///   - `Some(T)` if the there is an element currently under the cursor\n    ///     (i.e., the list is not empty)\n    ///   - `None` if the list is empty.\n    pub fn remove(&mut self) -> Option<T> {\n        unsafe {\n            match self.current.resolve_mut() {\n                None    => self.list.pop_front()\n              , Some(c) =>\n                    c.next_mut().take().resolve_mut()\n                     .map(|p| {\n                        match p.next_mut().resolve_mut() {\n                            None => self.list.tail = RawLink::some(c)\n                          , Some(n) => {\n                                *n.prev_mut() = RawLink::some(c);\n                                *c.next_mut() = RawLink::some(n);\n                            }\n                        }\n                        T::from_raw(p)\n                    })\n            }\n        }\n    }\n\n    /// Searches for and removes the first element matching a predicate.\n    ///\n    /// # Arguments\n    ///   - `p`: A predicate (function of the form `&N -> bool`) that returns\n    ///     true if the element should be removed and false if it should not.\n    ///\n    /// # Returns\n    ///   - `Some(T)` if an element matching the predicate was found\n    ///   - `None` if no elements matched the predicate (or if the list is\n    ///     empty.)\n    pub fn find_and_remove<P>(&mut self, predicate: P) -> Option<T>\n    where P: Fn(&N) -> bool {\n        while self.peek_next().is_some() {\n            if predicate(self.peek_next().unwrap()) == true {\n                return self.remove()\n            } else {\n                self.next();\n            }\n        }\n        None\n    }\n\n    /// Advances the cursor `n` elements and mutably borrows the final element.\n    ///\n    /// This will wrap the cursor around the list if `n` > the length of\n    /// the list.\n    pub fn seek_forward(&mut self, n: usize) -> Option<&mut N> {\n        for _ in 0 .. (n - 1) { self.next(); }\n        self.next()\n    }\n\n    /// Moves the cursor back `n` times and mutably borrows the final element.\n    ///\n    /// This will wrap the cursor around the list if `n` > the length of\n    /// the list.\n    pub fn seek_backward(&mut self, n: usize) -> Option<&mut N> {\n        for _ in 0 .. (n - 1) { self.prev(); }\n        self.prev()\n    }\n\n}\n\n// impl<'a, T, N> Iterator for ListCursorMut<'a, T, N>\n// where T: OwnedRef<N>\n//     , T: 'a\n//     , N: Node\n//     , N: 'a {\n//     type Item = &'a mut N;\n//\n//     fn next<'b: 'a>(&'b mut self) -> Option<&'a mut N> {\n//         self.next()\n//     }\n// }\n\n//\n// unsafe impl<T> OwnedRef for Unique<T> where T: Node {\n//\n//     #[inline]\n//     fn take(self) {}\n//\n//     unsafe fn from_raw(ptr: *mut T) -> Self {\n//         Unique::new(ptr)\n//     }\n// }\n//\n// unsafe impl<'a, T> OwnedRef<T> for &'a mut T {\n//     #\n//     #[inline] unsafe fn from_raw(raw: *mut T) -> &'a mut T {\n//         &mut *raw\n//     }\n//\n//     #[inline] unsafe fn take(self) {\n//         forget(self);\n//     }\n// }\n//\n\nunsafe impl<T> OwnedRef<T> for Unique<T>  {\n    #[inline]\n    fn get(&self) -> &T {\n        unsafe { self.as_ref() }\n    }\n\n    #[inline] fn get_mut(&mut self) -> &mut T {\n        unsafe { self.as_mut() }\n    }\n\n    #[inline]\n    unsafe fn take(self) {}\n\n    unsafe fn from_raw(ptr: *mut T) -> Self {\n        Unique::new(ptr)\n            // TODO: probably don't panic here.\n            .expect(\"null pointer passed to OwnedRef::from_raw!\")\n    }\n}\n\n#[cfg(any(test, feature = \"use-std\"))]\nunsafe impl<T> OwnedRef<T> for ::std::boxed::Box<T> {\n\n    fn get(&self) -> &T { &**self }\n    fn get_mut(&mut self) -> &mut T { &mut **self }\n\n    #[inline] unsafe fn take(self) {\n        ::std::boxed::Box::into_raw(self);\n    }\n\n    unsafe fn from_raw(ptr: *mut T) -> Self {\n        ::std::boxed::Box::from_raw(ptr)\n    }\n}\n"
  },
  {
    "path": "sos_intrusive/src/list/test.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza Weisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\n\nuse list::Node;\nuse rawlink::RawLink;\n\n#[derive(Debug)]\npub struct NumberedNode {\n    pub number: usize,\n    prev: RawLink<NumberedNode>,\n    next: RawLink<NumberedNode>,\n}\n\nimpl NumberedNode {\n    pub fn new(number: usize) -> Self {\n        NumberedNode {\n            number: number,\n            prev: RawLink::none(),\n            next: RawLink::none(),\n        }\n    }\n}\n\nimpl Node for NumberedNode {\n    fn prev(&self) -> &RawLink<Self> {\n        &self.prev\n    }\n\n    fn next(&self) -> &RawLink<Self> {\n        &self.next\n    }\n\n    fn prev_mut(&mut self) -> &mut RawLink<Self> {\n        &mut self.prev\n    }\n\n    fn next_mut(&mut self) -> &mut RawLink<Self> {\n        &mut self.next\n    }\n}\n\nimpl PartialEq for NumberedNode {\n    fn eq(&self, rhs: &Self) -> bool { self.number == rhs.number }\n}\n\nmod boxed {\n    use std::boxed::Box;\n\n    use list::List;\n    use super::*;\n\n    type TestList = List<Box<NumberedNode>, NumberedNode>;\n\n    #[test]\n    fn not_empty_after_push() {\n        let mut list = TestList::new();\n\n        assert_eq!(list.front(), None);\n        assert_eq!(list.back(), None);\n\n        assert!(list.is_empty());\n\n        list.push_front(box NumberedNode::new(1));\n\n        assert!(!list.is_empty());\n    }\n\n    #[test]\n    fn contents_after_first_push() {\n        let mut list = TestList::new();\n\n        list.push_front(box NumberedNode::new(1));\n\n        assert_eq!(list.front().unwrap().number, 1);\n    }\n\n\n    #[test]\n    fn head_tail_same_first_push() {\n        let mut list = TestList::new();\n\n        list.push_front(box NumberedNode::new(1));\n\n        assert_eq!(list.front().unwrap().number, 1);\n        assert_eq!(list.back().unwrap().number, 1);\n        assert_eq!(list.front().unwrap(), list.back().unwrap());\n    }\n\n    #[test]\n    fn head_tail_not_same_second_push() {\n        let mut list = TestList::new();\n\n        list.push_front(box NumberedNode::new(0));\n        list.push_front(box NumberedNode::new(1));\n\n        assert!(list.front().unwrap() != list.back().unwrap());\n    }\n\n\n    #[test]\n    fn contents_after_pushes() {\n        let mut list = TestList::new();\n\n        list.push_front(box NumberedNode::new(0));\n        list.push_front(box NumberedNode::new(1));\n\n        assert_eq!(list.back().unwrap().number, 0);\n        assert_eq!(list.front().unwrap().number, 1);\n\n        list.push_back(box NumberedNode::new(2));\n        assert_eq!(list.back().unwrap().number, 2);\n        assert_eq!(list.front().unwrap().number, 1);\n\n        list.push_back(box NumberedNode::new(3));\n        assert_eq!(list.back().unwrap().number, 3);\n        assert_eq!(list.front().unwrap().number, 1);\n\n        assert!(!list.is_empty());\n    }\n\n    #[test]\n    fn test_pop_front() {\n        let mut list = TestList::new();\n\n        assert_eq!(list.front(), None);\n        assert_eq!(list.back(), None);\n        assert!(list.is_empty());\n\n        list.push_front(Box::new(NumberedNode::new(2)));\n\n        assert!(!list.is_empty());\n        assert_eq!(list.front(), list.back());\n\n        list.push_front(Box::new(NumberedNode::new(1)));\n        list.push_front(Box::new(NumberedNode::new(0)));\n\n        assert_eq!(list.front().unwrap().number, 0);\n        assert_eq!(list.back().unwrap().number, 2);\n\n        list.push_back(Box::new(NumberedNode::new(3)));\n        assert_eq!(list.back().unwrap().number, 3);\n\n        list.push_back(Box::new(NumberedNode::new(4)));\n        assert_eq!(list.back().unwrap().number, 4);\n\n        assert!(!list.is_empty());\n\n        assert_eq!(list.pop_front().unwrap().number, 0);\n        assert_eq!(list.pop_front().unwrap().number, 1);\n        assert_eq!(list.pop_front().unwrap().number, 2);\n        assert_eq!(list.pop_front().unwrap().number, 3);\n        assert_eq!(list.pop_front().unwrap().number, 4);\n\n        assert!(list.is_empty());\n        assert_eq!(list.pop_front(), None);\n    }\n\n    #[test]\n    fn test_pop_back() {\n        let mut list = TestList::new();\n\n        assert_eq!(list.front(), None);\n        assert_eq!(list.back(), None);\n        assert!(list.is_empty());\n\n        list.push_front(Box::new(NumberedNode::new(2)));\n\n        assert!(!list.is_empty());\n        assert_eq!(list.front(), list.back());\n\n        list.push_front(Box::new(NumberedNode::new(1)));\n        list.push_front(Box::new(NumberedNode::new(0)));\n\n        assert_eq!(list.front().unwrap().number, 0);\n        assert_eq!(list.back().unwrap().number, 2);\n\n        list.push_back(Box::new(NumberedNode::new(3)));\n        assert_eq!(list.back().unwrap().number, 3);\n\n        list.push_back(Box::new(NumberedNode::new(4)));\n        assert_eq!(list.back().unwrap().number, 4);\n\n        assert!(!list.is_empty());\n\n        assert_eq!(list.pop_back().unwrap().number, 4);\n        assert_eq!(list.pop_back().unwrap().number, 3);\n        assert_eq!(list.pop_back().unwrap().number, 2);\n        assert_eq!(list.pop_back().unwrap().number, 1);\n        assert_eq!(list.pop_back().unwrap().number, 0);\n\n        assert!(list.is_empty());\n        assert_eq!(list.pop_back(), None);\n    }\n\n\n}\n\n// mod mut_ptr {\n//     use list::List;\n//     use super::*;\n//\n//     type TestList<'a> = List<&'a mut NumberedNode, NumberedNode>;\n//\n//     #[test]\n//     fn not_empty_after_push() {\n//         let mut list = TestList::new();\n//\n//         assert_eq!(list.front(), None);\n//         assert_eq!(list.back(), None);\n//\n//         assert!(list.is_empty());\n//\n//         list.push_front(&mut NumberedNode::new(1));\n//\n//         assert!(!list.is_empty());\n//     }\n//\n//     #[test]\n//     fn contents_after_first_push() {\n//         let mut list = TestList::new();\n//\n//         list.push_front(&mut NumberedNode::new(1));\n//\n//         assert_eq!(list.front().unwrap().number, 1);\n//     }\n//\n//\n//     #[test]\n//     fn head_tail_same_first_push() {\n//         let mut list = TestList::new();\n//\n//         list.push_front(&mut NumberedNode::new(1));\n//\n//         assert_eq!(list.front().unwrap().number, 1);\n//         assert_eq!(list.back().unwrap().number, 1);\n//         assert_eq!(list.front().unwrap(), list.back().unwrap());\n//     }\n//\n//     #[test]\n//     fn head_tail_not_same_second_push() {\n//         let mut list = TestList::new();\n//\n//         list.push_front(&mut NumberedNode::new(0));\n//         list.push_front(&mut NumberedNode::new(1));\n//\n//         assert!(list.front().unwrap() != list.back().unwrap());\n//     }\n//\n//\n//     #[test]\n//     fn contents_after_pushes() {\n//         let mut list = TestList::new();\n//\n//         list.push_front(&mut NumberedNode::new(0));\n//         list.push_front(&mut NumberedNode::new(1));\n//\n//         assert_eq!(list.back().unwrap().number, 0);\n//         assert_eq!(list.front().unwrap().number, 1);\n//\n//         list.push_back(&mut NumberedNode::new(2));\n//         assert_eq!(list.back().unwrap().number, 2);\n//         assert_eq!(list.front().unwrap().number, 1);\n//\n//         list.push_back(&mut NumberedNode::new(3));\n//         assert_eq!(list.back().unwrap().number, 3);\n//         assert_eq!(list.front().unwrap().number, 1);\n//\n//         assert!(!list.is_empty());\n//     }\n//\n// }\n"
  },
  {
    "path": "sos_intrusive/src/rawlink.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza Weisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\n//! Implementation of the `RawLink` smart-ish pointer.\n//!\n//! A `RawLink` is a zero-cost abstraction that allows a raw pointer to be used\n//! with an `Option`-esque API.\n//!\n//! TODO: implement all monadic operations over `Option`-esque types (i.e.\n//! `map()`, `and_then()`, etc).\n\nuse core::ptr;\nuse core::fmt;\nuse core::mem;\n\n/// A `RawLink` provides an `Option`-like interface to a raw pointer.\n#[derive(Debug, Copy, Clone, PartialEq)]\npub struct RawLink<T>(*mut T);\n\nunsafe impl<T> Send for RawLink<T>\nwhere T: 'static\n    , T: Send {}\n\nunsafe impl<T> Sync for RawLink<T>\nwhere T: Send\n    , T: Sync {}\n\nimpl<T> Default for RawLink<T> {\n    fn default() -> Self { Self::none() }\n}\n\nimpl<T> fmt::Display for RawLink<T>\nwhere T: fmt::Display {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        if self.0.is_null() {\n            write!(f, \"RawLink::none\")\n        } else {\n            unsafe { write!(f, \"RawLink::some({})\", *self.0) }\n        }\n\n    }\n}\n\nimpl<T> RawLink<T> {\n\n    /// Equivalent of `Option::None` for a `RawLink`\n    ///\n    /// # Returns\n    ///   - A `RawLink<T>` wrapping a null pointer\n    #[inline]\n    pub const fn none() -> RawLink<T> { RawLink(ptr::null_mut()) }\n\n    /// Equivalent of `Option::Some` for a `RawLink`\n    ///\n    /// # Returns\n    ///   - A `RawLink<T>` wrapping a pointer to the specified value\n    #[inline]\n    pub fn some(thing: &mut T) -> RawLink<T> { RawLink(thing) }\n\n    pub const fn from_raw(ptr: *mut T) -> RawLink<T> { RawLink(ptr) }\n\n    /// Resolve the `RawLink` to an `Option`\n    ///\n    /// # Returns\n    ///   - `Some<&'a T>` if the `RawLink` is not a null pointer\n    ///   - `None` if the `RawLink` is a null pointer\n    ///\n    /// # Unsafe due to\n    ///   - Returning a reference with an arbitrary lifetime\n    ///   - Dereferencing a raw pointer\n    #[inline]\n    pub unsafe fn resolve<'a>(&self) -> Option<&'a T> {\n        self.0.as_ref()\n    }\n\n    /// Resolve the `RawLink` to an `Option` on a mutable pointer\n    ///\n    /// # Returns\n    ///   - `Some<&'a mut T>` if the `RawLink` is not a null pointer\n    ///   - `None` if the `RawLink` is a null pointer\n    ///\n    /// # Unsafe due to\n    ///   - Returning a reference with an arbitrary lifetime\n    ///   - Dereferencing a raw pointer\n    #[inline]\n    pub unsafe fn resolve_mut<'a>(&self) -> Option<&'a mut T> {\n        self.0.as_mut()\n    }\n\n    /// Please don't do this.\n    ///\n    /// # Returns\n    ///   - The underlying raw pointer (`*mut T`) behind this `RawLink`\n    ///\n    /// # Unsafe due to\n    ///   - Returning a reference with an arbitrary lifetime\n    ///   - Dereferencing a raw pointer\n    ///   - Please don't do this\n    #[inline]\n    pub unsafe fn as_raw(&self) -> *mut T { self.0 }\n\n    #[inline]\n    pub fn is_some(&self) -> bool { !self.is_none() }\n\n    #[inline]\n    pub fn is_none(&self) -> bool { self.0.is_null() }\n\n    /// Returns the `RawLink` and replaces it with `RawLink::none()`.\n    #[inline]\n    pub fn take(&mut self) -> Self { mem::replace(self, Self::none()) }\n\n    pub unsafe fn map<U, F: FnOnce(T) -> U>(self, _f: F) -> RawLink<U> {\n        unimplemented!()\n    }\n}\n//\n// impl<T> ops::Deref for RawLink<T> {\n//     type Target = T;\n//\n//     fn deref(&self) -> &Self::Target { unsafe { self.resolve().unwrap() } }\n// }\n"
  },
  {
    "path": "sos_intrusive/src/stack/mod.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2017 Eliza Weisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\n//! An intrusive singly-linked list implementation using `RawLink`s.\n//!\n//! An _intrusive_ list is a list structure wherein the type of element stored\n//! in the list holds references to other nodes. This means that we don't have\n//! to store a separate node data type that holds the stored elements and\n//! pointers to other nodes, reducing the amount of memory allocated. We can\n//! use intrusive lists in code that runs without the kernel memory allocator,\n//! like the allocator implementation itself, since each list element manages\n//! its own memory.\nuse ::{RawLink, OwnedRef};\n\nuse core::marker::PhantomData;\nuse core::iter;\n#[cfg(test)] mod test;\n\n\n/// This trait defines a node in an intrusive list.\n///\n/// A Node must be capable of providing mutable and immutable references to\n/// the next node in the stack\npub trait Node: Sized {\n    fn next(&self) -> &RawLink<Self>;\n    fn next_mut(&mut self) -> &mut RawLink<Self>;\n}\n\n/// The `Stack` struct is our way of interacting with an intrusive list.\n///\n/// It stores a pointer to the head of the stack, the length of the\n/// list, and a `PhantomData` marker for the list's `OwnedRef` type. It\n/// provides the methods for pushing, popping, and indexing the list.\npub struct Stack<T, N>\nwhere T: OwnedRef<N>\n    , N: Node {\n    head: RawLink<N>\n  , _ty_marker: PhantomData<T>\n  , length: usize\n }\n\nimpl<T, N> Stack<T, N>\nwhere T: OwnedRef<N>\n    , N: Node {\n\n    /// Construct a new `Stack<T, N>` with zero elements\n    pub const fn new() -> Self {\n        Stack { head: RawLink::none()\n             , _ty_marker: PhantomData\n             , length: 0 }\n    }\n\n    /// Returns the length of the list\n    #[inline] pub fn len(&self) -> usize {\n        self.length\n    }\n\n    /// Borrows the first element of the list as an `Option`\n    ///\n    /// # Returns\n    ///   - `Some(&N)` if the list has elements\n    ///   - `None` if the list is empty.\n    #[inline] pub fn peek(&self) -> Option<&N> {\n        unsafe { self.head.resolve() }\n    }\n\n\n    /// Mutably borrows the first element of the list as an `Option`\n    ///\n    /// # Returns\n    ///   - `Some(&mut N)` if the list has elements\n    ///   - `None` if the list is empty.\n    #[inline] pub fn peek_mut(&mut self) -> Option<&mut N> {\n        unsafe { self.head.resolve_mut() }\n    }\n\n    /// Returns true if the list is empty.\n    #[inline] pub fn is_empty(&self) -> bool {\n        self.head.is_none()\n    }\n\n    /// Push an element to the front of the stack\n    pub fn push(&mut self, mut item: T) {\n        // set the pushed item to point to the head element of the stack\n        *item.get_mut().next_mut() = self.head.take();\n        // then, set this node's head pointer to point to the pushed item\n        self.head = RawLink::some(item.get_mut());\n        unsafe { item.take(); };\n        self.length += 1;\n    }\n\n    /// Removes and returns the element at the front of the list.\n    ///\n    /// # Returns\n    ///   - `Some(T)` containing the element at the front of the list if the\n    ///     list is not empty\n    ///   - `None` if the list is empty\n    pub fn pop(&mut self) -> Option<T> {\n        unsafe {\n            self.head.take().resolve_mut()\n                .map(|head| {\n                    if let Some(next) = head.next_mut().resolve_mut() {\n                        self.head = RawLink::some(next);\n                    }\n                    self.length -= 1;\n                    T::from_raw(head)\n                })\n        }\n    }\n\n}\n\nimpl<T, N> iter::FromIterator<T> for Stack<T, N>\nwhere T: OwnedRef<N>\n    , N: Node {\n    fn from_iter<I: IntoIterator<Item=T>>(iterator: I) -> Self {\n        let mut list: Self = Stack::new();\n        for item in iterator { list.push(item) }\n        list\n    }\n}\n"
  },
  {
    "path": "sos_intrusive/src/stack/test.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2017 Eliza Weisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\n\nuse stack::Node;\nuse rawlink::RawLink;\n\n#[derive(Debug)]\npub struct NumberedNode {\n    pub number: usize,\n    next: RawLink<NumberedNode>,\n}\n\nimpl NumberedNode {\n    pub fn new(number: usize) -> Self {\n        NumberedNode {\n            number: number,\n            next: RawLink::none(),\n        }\n    }\n}\n\nimpl Node for NumberedNode {\n\n    fn next(&self) -> &RawLink<Self> {\n        &self.next\n    }\n\n    fn next_mut(&mut self) -> &mut RawLink<Self> {\n        &mut self.next\n    }\n}\n\nimpl PartialEq for NumberedNode {\n    fn eq(&self, rhs: &Self) -> bool { self.number == rhs.number }\n}\n\nmod boxed {\n    use std::boxed::Box;\n\n    use super::super::Stack;\n    use super::*;\n\n    type TestStack = Stack<Box<NumberedNode>, NumberedNode>;\n\n    #[test]\n    fn not_empty_after_push() {\n        let mut list = TestStack::new();\n\n        assert_eq!(list.peek(), None);\n\n        assert!(list.is_empty());\n\n        list.push(box NumberedNode::new(1));\n\n        assert!(!list.is_empty());\n    }\n\n    #[test]\n    fn contents_after_first_push() {\n        let mut list = TestStack::new();\n\n        list.push(box NumberedNode::new(1));\n\n        assert_eq!(list.peek().unwrap().number, 1);\n    }\n\n\n    #[test]\n    fn contents_after_pushes() {\n        let mut list = TestStack::new();\n\n        list.push(box NumberedNode::new(0));\n        assert_eq!(list.peek().unwrap().number, 0);\n        list.push(box NumberedNode::new(1));\n\n        assert_eq!(list.peek().unwrap().number, 1);\n\n        assert!(!list.is_empty());\n    }\n\n    #[test]\n    fn test_pop_front() {\n        let mut list = TestStack::new();\n\n        assert_eq!(list.peek(), None);\n        assert!(list.is_empty());\n\n        list.push(Box::new(NumberedNode::new(4)));\n        assert!(!list.is_empty());\n        assert_eq!(list.peek().unwrap().number, 4);\n\n        list.push(Box::new(NumberedNode::new(3)));\n        assert!(!list.is_empty());\n        assert_eq!(list.peek().unwrap().number, 3);\n\n        list.push(Box::new(NumberedNode::new(2)));\n        assert!(!list.is_empty());\n        assert_eq!(list.peek().unwrap().number, 2);\n\n        list.push(Box::new(NumberedNode::new(1)));\n        assert!(!list.is_empty());\n        assert_eq!(list.peek().unwrap().number, 1);\n\n        list.push(Box::new(NumberedNode::new(0)));\n        assert!(!list.is_empty());\n        assert_eq!(list.peek().unwrap().number, 0);\n\n        assert_eq!(list.pop().unwrap().number, 0);\n        assert_eq!(list.pop().unwrap().number, 1);\n        assert_eq!(list.pop().unwrap().number, 2);\n        assert_eq!(list.pop().unwrap().number, 3);\n        assert_eq!(list.pop().unwrap().number, 4);\n\n        assert!(list.is_empty());\n        assert_eq!(list.pop(), None);\n    }\n\n\n}\n"
  },
  {
    "path": "src/arch/README.md",
    "content": "Architecture-specific implementation:\n + `arch/x86` contains implementation for x86 32-bit protected mode (not yet implemented)\n + `arch/x86_64` contains implementation for x86 64-bit long mode CPUs\n + `arch/x86_all` contains common code for all x86 architectures\n"
  },
  {
    "path": "src/arch/mod.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza Weisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\n//! Architecture-specific implementation.\n//!\n//! This module consists of a number of modules containing\n//! architecture-specific code for each targeted architecture. The `arch`\n//! module uses conditional compilation to re-export the implementation for\n//! which the kernel is currently being compiled.\n//!\n//! In order for the rest of the kernel to work properly, an\n//! architecture-specific implementation module should define a number of\n//! specific items. If these are not defined, the platform-independant kernel\n//! implementation cannot function properly.\n//!\n//! Please note that currently only the architecture-specific implementation\n//! for `x86_64` (long mode) is implemented. The `armv7` and `x86` (protected\n//! mode) modules are currently much less complete.\n\n// 64-bit x86_64 (long mode)\n#[cfg(target_arch=\"x86_64\")] mod x86_64;\n#[cfg(target_arch=\"x86_64\")] pub use self::x86_64::*;\n\n// 32-bit x86 (protected mode)\n// TODO: NYI\n#[cfg(target_arch = \"x86\")] mod x86;\n#[cfg(target_arch = \"x86\")] pub use self::x86::*;\n\n// ARM v7\n// TODO: NYI\n#[cfg(target_arch = \"armv7\")] mod armv7;\n#[cfg(target_arch = \"armv7\")] pub use self::x86::*;\n"
  },
  {
    "path": "src/arch/x86_64/boot.asm",
    "content": "%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 to the second\n%macro  page_map 2\n\n        mov     eax, %2\n        or      eax, 0b11 ; present + writable\n        mov     [%1], eax\n\n%endmacro\n\n%macro  export  1\n\n        global %1\n        %1:\n\n%endmacro\n\n\nglobal start\n\nextern arch_init\n\nsection .text\nbits 32\n\n; == start the kernel ========================================================\n; this is the beginning of our boot process called by GRUB.\nstart:\n    ; 0. Move the stack pointer to the top of the stack. ---------------------\n    mov     esp, stack_top\n\n    ; 1. Move Multiboot info pointer to edi ----------------------------------\n    mov     edi, ebx\n\n    ; 2. Make sure that the system supports SOS. -----------------------------\n    call    is_multiboot ; check that multiboot is supported\n    call    is_cpuid     ; check CPUID is supported (to check for long mode)\n    call    is_long_mode ; check if long mode (64-bit) is available.\n\n    ; 3. if everything is okay, create the page tables and start long mode\n    call    create_page_tables\n    call    set_long_mode\n\n    ; 4. load the 64-bit GDT\n    lgdt    [gdt64.ptr]\n\n    ; 5. update selectors\n    mov     ax, 16\n    mov     ss, ax  ; stack selector\n    mov     ds, ax  ; data selector\n    mov     es, ax  ; extra selector\n\n    ; 6. print `OK` to screen and jump to the 64-bit boot subroutine.\n    mov     dword [0xb8000], 0x2f4b2f4f\n\n    jmp     gdt64.code:arch_init\n\n; == Tests whether or not multiboot is enabled ==============================\nis_multiboot:\n    cmp     eax, 0x36d76289\n    jne     .no_multiboot\n    ret\n.no_multiboot:\n    mov     al, \"0\"\n    jmp     err\n\n\n; == Tests whether or not long mode is available ==============================\n; If long mode is not available, die (we are a long mode OS).\nis_long_mode:\n    mov     eax, 0x80000000   ; Set the A-register to 0x80000000.\n    cpuid                     ; CPU identification.\n    cmp     eax, 0x80000001   ; Compare the A-register with 0x80000001.\n    jb      .no_long_mode     ; It is less, there is no long mode.\n    mov     eax, 0x80000001   ; Set the A-register to 0x80000001.\n    cpuid                     ; Do the CPUID thing once more.\n    test    edx, 1 << 29      ; Test if the LM-bit, (bit 29), is set in edx.\n    jz      .no_long_mode     ; If it isn't, there is no long mode,\n    ret                       ; and we are left with only the void for company.\n.no_long_mode:\n    mov     al, \"2\"\n    jmp     err\n\n; == Tests wether or not CPUID is available ==================================\n; If the system does not support CPUID, we cannot boot, since we need to use\n; CPUID to check if we can switch to 64-bit long mode\nis_cpuid:\n    pushfd                  ; Store the FLAGS-register.\n    pop     eax             ; Restore the A-register.\n    mov     ecx, eax        ; Set the C-register to the A-register.\n    xor     eax, 1 << 21    ; Flip the ID-bit, which is bit 21.\n    push    eax             ; Store the A-register.\n    popfd                   ; Restore the FLAGS-register.\n    pushfd                  ; Store the FLAGS-register.\n    pop     eax             ; Restore the A-register.\n    push    ecx             ; Store the C-register.\n    popfd                   ; Restore the FLAGS-register.\n    xor     eax, ecx        ; Do a XOR  A-register andC-register.\n    jz      .no_cpuid       ; The zero flag is set, no CPUID.\n    ret                     ; CPUID is available for use.\n.no_cpuid:\n    mov al, \"1\"\n    jmp err\n\n; == Prints a boot error code to the VGA buffer ==============================\nerr:\n    mov     dword [0xb8000], 0x4f524f45\n    mov     byte  [0xb8004], al\n    hlt\n\n; == Creates the page tables =================================================\n; Map the following:\n;   - the first PML4 entry -> PDP\n;   - the first PDP entry -> PD\n;   - each PD entry to its own 2mB page\ncreate_page_tables:\n    ; recursive map last entry in PML4 ---------------------------------------\n    mov         eax, pml4_table\n    or          eax, 0b11\n    mov         [pml4_table + 511 * 8], eax\n\n    page_map    pml4_table, pdp_table   ; map first PML4 entry to PDP table\n    page_map    pdp_table,  pd_table    ; map first PDP entry to PD table\n\n    ; map each PD table entry to its own 2mB page\n    mov         ecx, 0\n\n.pd_table_map: ; maps the PD table -----------------------------------------\n    mov     eax, 0x200000   ; 2 mB\n    mul     ecx             ; times the start address of the page\n    or      eax, 0b10000011 ; check if present + writable + huge\n\n    mov     [pd_table + ecx * 8], eax ; map nth entry from pd -> own page\n\n    ; increment counter and check if done\n    inc     ecx\n    cmp     ecx, 512\n    jne     .pd_table_map\n\n    ret\n\n; == Sets long mode and enables paging =======================================\n; In order to do this, we must first create the initial page tables.\nset_long_mode:\n\n    ; load PML4 addr to cr3 register -----------------------------------------\n    mov     eax, pml4_table\n    mov     cr3, eax\n\n    ; enable PAE-flag in cr4 (Physical Address Extension) --------------------\n    mov     eax, cr4\n    or      eax, 1 << 5\n    mov     cr4, eax\n\n    ; set the long mode bit in the EFER MSR (model specific register) --------\n    mov     ecx, 0xC0000080\n    rdmsr\n    or      eax, 1 << 8\n    wrmsr\n\n    ; enable paging in the cr0 register -------------------------------------\n    mov     eax, cr0\n    or      eax, 1 << 31\n    or      eax, 1 << 16\n    mov     cr0, eax\n\n    ret\n\nsection .bss\nalign 4096\n; == page tables =============================================================\n; Page-Map Level-4 Table\npml4_table:\n    resb    PAGE_TABLE_SIZE\n; Page Directory Pointer Table\npdp_table:\n    resb    PAGE_TABLE_SIZE\n; Page-Directory Table\npd_table:\n    resb    PAGE_TABLE_SIZE\n ; Page Table\npage_table:\n    resb    PAGE_TABLE_SIZE\n\n; == kernel stack =============================================================\nstack_base:\n    resb    PAGE_SIZE * 4 ; reserve 2 pages for the kernel stack\n    ; for some unspeakable reason, doubling the kernel stack size\n    ; magically fixes all of the memory allocator bugs? i suspect\n    ; the Malloc Gods interpret the extra stack space as a\n    ; sacrifice. my mind grows weary of this treatchery.\n    ; 𐅃 𐅐𐆂𐅛𐅜𐅀𐅂𐅲𐅯𐅊𐅭𐅙 𐅗 𐅏 𐅽𐅆 𐅲𐆇𐅿𐅚𐆁𐅐𐅶𐅬𐅯𐅴𐅮𐅼 𐅊𐅦 𐅒𐅉 𐅻𐅷𐅘 𐅊𐅗 𐅤𐆁𐅛𐅒𐅎𐅅𐅨𐅓𐅵𐅯𐅺𐅐𐆀\n    ; 𐅵𐅿 𐅘 𐅈𐅘𐅁 𐅫 𐅟𐅸 𐅥𐅣𐅑𐅼𐅷𐅻𐆁 𐆊 𐆉𐆇𐆅𐅐 𐅦𐅕 𐅢𐅷𐅗𐅤𐅧 𐅣𐅖𐅺 𐅁𐅿𐅩𐅣 𐅥 𐆄𐅱𐅕 𐅈 𐅙𐅀 𐅋\n    ; 𐅩𐅿𐅋𐅫𐅌𐆆𐅊𐆇 𐅜𐅦𐅲 𐅷 𐅱𐆁𐅓𐅞\nstack_top:\n\n; == kernel heap =============================================================\nheap_base:\n    resb    4 * 1024 * 1024 ; reserved space for the kernel heap\nheap_top:\n\nsection .rodata\n\nexport gdt64\n    dq 0 ; zero entry\n.code: equ $ - gdt64 ; new\n    dq (1<<44) | (1<<47) | (1<<41) | (1<<43) | (1<<53) ; code segment\n.data: equ $ - gdt64 ; new\n    dq (1<<44) | (1<<47) | (1<<41) ; data segment\n.ptr:\n    dw $ - gdt64 - 1\n    dq gdt64\n\n; GDT offset location exported to Rust kernel\nexport gdt64_offset\n    dq gdt64.code\n\nexport stack_base_addr\n    dq stack_base\n\nexport stack_top_addr\n    dq stack_top\n\nexport heap_base_addr\n    dq heap_base\n\nexport heap_top_addr\n    dq heap_top\n\nexport pml4_table_addr\n    dq pml4_table\n"
  },
  {
    "path": "src/arch/x86_64/drivers/mod.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2016 Eliza eisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\npub mod serial;\npub mod vga;\n"
  },
  {
    "path": "src/arch/x86_64/drivers/serial.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza Weisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\n//! Serial port driver\n//!\n//! Create new serial ports by calling `PortNum::new()`. If the system supports\n//! that port, `Some(Port)` will be returned. Otherwise, if the system\n//! does not have that port number (such as `COM3` and `COM4`) on many machines,\n//! `PortNum::new()` returns `None`.\n//!\n//! See [the OS Dev wiki](http://wiki.osdev.org/Serial_Ports) for more\n//! information.\n\nuse spin::Mutex;\n\nuse core::fmt;\n\nuse ::arch::bda;\nuse cpu::Port;\n// use ::io;\nuse util::{io, Void};\n//\n// /// Address of the BIOS Data Area (BDA)\n// /// where the serial port addresses are stored.\n// const BDA_ADDR: usize = 0x400;\n//\n\npub struct Serial(Option<SerialPort>);\n\nimpl fmt::Write for Serial {\n    #[inline]\n    fn write_str(&mut self, s: &str) -> fmt::Result {\n        if let Some(ref mut p) = self.0 {\n            p.write_str(s)\n        } else {\n            Err(fmt::Error)\n        }\n    }\n}\n\nlazy_static! {\n    // static ref BDA_SERIAL_INFO: [u16; 4]\n    //     = unsafe { *(BDA_ADDR as *const [u16; 4]) };\n    // TODO: serial ports are currently behind a mutex; can they be read-write\n    //       locked instead? I think multiple threads should be able to read\n    //       from a serial port at the same time without causing trouble?\n    //          - eliza, 10/9/2016\n    pub static ref COM1: Mutex<Serial>\n        = Mutex::new(Serial(bda::ports::com1().map(SerialPort::new)));\n\n    pub static ref COM2: Mutex<Serial>\n        = Mutex::new(Serial(bda::ports::com2().map(SerialPort::new)));\n\n    pub static ref COM3: Mutex<Serial>\n        = Mutex::new(Serial(bda::ports::com3().map(SerialPort::new)));\n\n    pub static ref COM4: Mutex<Serial>\n        = Mutex::new(Serial(bda::ports::com4().map(SerialPort::new)));\n}\n\n\n\n/// A serial port\npub struct SerialPort { data_port: Port<u8>\n                      , status_port: Port<u8>\n                      }\n\nimpl SerialPort {\n\n    fn new(port: u16) -> SerialPort {\n         // Disable all interrupts\n        Port::<u8>::new(port + 1).write(0x00);\n        // Enable DLAB (set baud rate divisor)\n        Port::<u8>::new(port + 3).write(0x80);\n        // Set divisor to 38400 baud\n        Port::<u8>::new(port + 0).write(0x03); // divisor hi byte\n        Port::<u8>::new(port + 1).write(0x00); // divisor lo byte\n        // 8 bits, no parity, one stop bit\n        Port::<u8>::new(port + 3).write(0x03);\n        // Enable FIFO, clear them, with 14-byte threshold\n        Port::<u8>::new(port + 2).write(0xC7);\n        // IRQs enabled, RTS/DSR set\n        Port::<u8>::new(port + 4).write(0x0B);\n        Port::<u8>::new(port + 1).write(0x01);\n\n        SerialPort { data_port: Port::<u8>::new(port)\n                   , status_port: Port::<u8>::new(port + 5)\n                   }\n    }\n\n    /// Returns true if the serial port has recieved data\n    #[inline]\n    pub fn has_byte(&self) -> bool {\n        self.status_port.read() & 1 != 0\n    }\n\n    #[inline]\n    pub fn is_empty(&self) -> bool {\n        self.status_port.read() & 0x20 == 0x20\n    }\n\n    #[inline]\n    pub fn read_byte(&self) -> u8 {\n        while !self.has_byte() {};\n        self.data_port.read()\n    }\n\n    #[inline]\n    pub fn write_byte(&self, byte: u8) {\n        while !self.is_empty() {};\n        self.data_port.write(byte)\n    }\n}\n\nimpl io::Read for SerialPort {\n    type Error = Void;\n\n    /// Reads a single byte into the given buffer\n    fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {\n        Ok(match &mut *buf {\n            // if the length of the buffer is 0, then obviously\n            // no bytes were read\n            &mut []                  => 0\n            // otherwise, read one byte into the head of the buffer\n          , &mut [ref mut head, _..] => { *head = self.read_byte(); 1 }\n        })\n    }\n\n    /// Reads a new byte into each position in the buffer.\n    fn read_all(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {\n        let mut read_bytes = 0;\n        for idx in buf.iter_mut() {\n            // for each index in the buffer, read another byte from the port\n            *idx = self.read_byte();\n            // and increment the number of bytes read (this should be faster\n            // than calling `buf.len()` later; as we only need 1 loop)\n            read_bytes += 1;\n        }\n        Ok(read_bytes)\n    }\n}\n\nimpl io::Write for SerialPort {\n    type Error = Void;\n\n    fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {\n        let mut written_bytes = 0;\n        for byte in buf {\n            // write each byte in the buffer to the port\n            self.write_byte(*byte);\n            // and increment the number of bytes written (this should be faster\n            // than calling `buf.len()` later; as we only need 1 loop)\n            written_bytes += 1;\n        }\n        Ok(written_bytes)\n    }\n}\n\nimpl fmt::Write for SerialPort {\n    fn write_str(&mut self, s: &str) -> fmt::Result {\n        for byte in s.bytes() {\n            // TODO: more robust error handling here\n            self.write_byte(byte);\n        }\n        Ok(())\n    }\n}\n"
  },
  {
    "path": "src/arch/x86_64/drivers/vga.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza Weisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\n//! Arch-specific VGA port port driver\n\nuse vga::{Palette, Color, Terminal};\nuse spin::Mutex;\n\n// extern {\n//     #[link_section = \".__vga_buffer\"]\n//     static mut BUFFER: vga::Buffer;\n// }\n\n/// The system's global VGA terminal\npub static CONSOLE: Mutex<Terminal>\n    = Mutex::new(unsafe { Terminal::new(\n         Palette::new(Color::LightGrey, Color::Black )\n       , 0x8000\n    )});\n\npub fn clear() {\n    CONSOLE.lock().clear();\n}\n"
  },
  {
    "path": "src/arch/x86_64/grub.cfg",
    "content": "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",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza Weisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\n\nuse cpu::interrupts::pics;\nuse cpu::interrupts::idt::{Gate, Idt};\n\nuse cpu::context::InterruptFrame;\nuse cpu::dtable::DTable;\n\n\n//==--------------------------------------------------------------------------==\n// Top-level interrupt handling\n\n/// Initialize interrupt handling.\n///\n/// This function initializes the PICs, populates the IDT with interrupt\n/// handlers, loads the IDT pointer, and enables interrupts.\n///\n/// This is called from the kernel during the init process.\n// TODO: make the result returned by this meaningful?\n#[inline]\npub unsafe fn initialize() -> Result<(), ()>{\n\n    pics::initialize();\n   // TODO: consider loading double-fault handler before anything else in case\n   //       a double fault occurs during init?\n    IDT.load();         // Load the IDT pointer\n    //\n    // debug!(\"Testing interrupt handling\");\n    // asm!(\"int $0\" :: \"N\" (0xff));\n\n    Idt::enable_interrupts(); // enable interrupts\n    Ok(())\n\n}\n\nmacro_rules! exception_inner {\n    ($title:expr, $kind:expr, $source:expr, $f:expr) => {\n        use vga::{CONSOLE, Color};\n        use core::fmt::Write;\n        let _ = write!( CONSOLE.lock()\n                               .set_colors(Color::White, Color::Blue)\n                      , \"EVERYTHING IS FINE: {}{} at {:p}\\n\\\n                         Source: {}.\\nThis is fine.\\n\\n\\\n                         {:?}\"\n                         , $title, $kind\n                         , (*$f).rip\n                         , $source\n                         , *$f);\n    };\n    ($title:expr, $kind:expr, $source:expr, $f:expr, $e:expr) => {\n        use vga::{CONSOLE, Color};\n        use core::fmt::Write;\n        let _ = write!( CONSOLE.lock()\n                               .set_colors(Color::White, Color::Blue)\n                      , \"EVERYTHING IS FINE: {}{} at {:p}\\n\\\n                         Source: {}.\\n\n                         Error code: {:x}\\nThis is fine.\\n\\n\\\n                         {:?}\"\n                         , $title, $kind\n                         , (*$f).rip\n                         , $source\n                         , $e\n                         , *$f);\n    };\n}\n\nmacro_rules! exceptions {\n    ( fault: $name:ident, $title:expr, $source:expr, $($tail:tt)* ) => {\n        #[doc=$title]\n        extern \"x86-interrupt\" fn $name(frame: &InterruptFrame) {\n            exception_inner! ($title, \"Fault\", $source, frame);\n            loop {}\n        }\n\n        exceptions! {  $($tail)* }\n    };\n     ( fault (code): $name:ident, $title:expr, $source:expr, $($tail:tt)* ) => {\n        #[doc=$title]\n        extern \"x86-interrupt\" fn $name( frame: &InterruptFrame\n                                       , error_code: usize) {\n           exception_inner! ($title, \"Fault\", $source, frame, error_code);\n           loop {}\n       }\n       exceptions! { $($tail)* }\n   };\n     ( trap: $name:ident, $title:expr, $source:expr, $($tail:tt)* ) => {\n         #[doc=$title]\n         extern \"x86-interrupt\" fn $name(frame: &InterruptFrame) {\n             exception_inner! ($title, \"Trap\", $source, frame);\n         }\n\n         exceptions! { $($tail)* }\n     };\n      ( ) => {};\n\n}\nexceptions! {\n    fault: divide_by_zero, \"Divide by Zero Error\",\n           \"DIV or IDIV instruction\",\n    fault: nmi, \"Non-Maskable Interrupt\",\n          \"Non-maskable external interrupt\",\n    trap: overflow, \"Overflow\", \"INTO instruction\",\n    fault: bound_exceeded, \"BOUND range exceeded\",\n          \"BOUND instruction\",\n    fault: undefined_opcode, \"Undefined Opcode\",\n           \"UD2 instruction or reserved opcode\",\n    fault: device_not_available, \"Device Not Available\"\n         , \"Floating-point or WAIT/FWAIT instruction \\\n            (no math coprocessor)\",\n    fault (code): double_fault, \"Double Fault\"\n         , \"Any instruction that can generate an exception, a NMI, or \\\n            an INTR\",\n    fault (code): invalid_tss, \"Invalid TSS\"\n         , \"Task switch or TSS access\",\n    fault (code): segment_not_present, \"Segment Not Present\"\n         , \"Loading segment registers or accessing \\\n            system segments\",\n    fault (code): general_protection_fault, \"General Protection Fault\"\n         , \"Any memory reference or other protection checks\",\n    fault (code): stack_segment_fault, \"Stack Segment Fault\"\n         , \"Stack operations and SS register loads\",\n    fault: floating_point_error\n         , \"x87 FPU Floating-Point Error (Math Fault)\"\n         , \"x87 FPU floating-point or WAIT/FWAIT instruction\",\n    fault: machine_check, \"Machine Check\"\n         , \"Model-dependent (probably hardware!)\",\n    fault (code): alignment_check, \"Alignment Check\"\n         , \"Any data reference in memory\",\n    fault: simd_fp_exception, \"SIMD Floating-Point Exception\"\n         , \"SSE/SSE2/SSE3 floating-point instructions\",\n}\n\nlazy_static! {\n    static ref IDT: Idt = {\n        let mut idt = Idt::new();\n        use cpu::interrupts::*;\n\n        // TODO: log each handler as it's added to the IDT? that way we can\n        //       trace faults occurring during IDT population (if any)\n        //          - eliza, 5/22/2017\n        idt.divide_by_zero = Gate::from(divide_by_zero as InterruptHandler);\n        idt.nmi = Gate::from(nmi as InterruptHandler);\n        idt.overflow = Gate::from(overflow as InterruptHandler);\n        idt.overflow.set_trap();\n        idt.bound_exceeded = Gate::from(bound_exceeded as InterruptHandler);\n        idt.undefined_opcode = Gate::from(undefined_opcode as InterruptHandler);\n        idt.device_not_available = Gate::from(device_not_available as InterruptHandler);\n        idt.double_fault = Gate::from(double_fault as ErrorCodeHandler);\n        idt.invalid_tss = Gate::from(invalid_tss as ErrorCodeHandler);\n        idt.segment_not_present = Gate::from(segment_not_present as ErrorCodeHandler);\n        idt.stack_segment_fault = Gate::from(stack_segment_fault as ErrorCodeHandler);\n        idt.general_protection_fault = Gate::from(general_protection_fault as ErrorCodeHandler);\n        idt.page_fault = Gate::from(page_fault as ErrorCodeHandler);\n\n        idt.floating_point_error = Gate::from(floating_point_error as InterruptHandler);\n        idt.alignment_check = Gate::from(alignment_check as ErrorCodeHandler);\n        idt.machine_check = Gate::from(machine_check as InterruptHandler);\n        idt.simd_fp_exception = Gate::from(simd_fp_exception as InterruptHandler);\n\n        idt.breakpoint = Gate::from(breakpoint as InterruptHandler);\n        idt.page_fault = Gate::from(page_fault as ErrorCodeHandler);\n\n        idt.interrupts[0x20 - 32] = Gate::from(timer as InterruptHandler);\n        idt.interrupts[0x21 - 32] = Gate::from(keyboard as InterruptHandler);\n        idt.interrupts[0xff - 32] = Gate::from(test as InterruptHandler);\n\n        kinfoln!( dots: \" . . \", target: \"Adding interrupt handlers to IDT\"\n                , \"[ OKAY ]\");\n        idt\n    };\n}\n\n\n#[no_mangle] #[inline(never)]\npub extern \"x86-interrupt\" fn keyboard(_frame: &InterruptFrame) {\n    use io::keyboard;\n\n    // println!(\"keyboard happened\");\n    if let Some(input) = keyboard::read_char() {\n        if input == '\\r' {\n            println!(\"\");\n        } else {\n            print!(\"{}\", input);\n        }\n    }\n   // send the PICs the end interrupt signal\n   unsafe {\n       pics::end_pic_interrupt(0x21);\n   }\n}\n\n#[no_mangle] #[inline(never)]\npub extern \"x86-interrupt\" fn breakpoint(frame: &InterruptFrame) {\n    println!(\"Breakpoint! Frame: {:#?}\", frame);\n   // send the PICs the end interrupt signal\n   unsafe {\n       pics::end_pic_interrupt(0x03);\n   }\n}\n\n/// Empty dummy handler for undefined interrupts.\n#[no_mangle] #[inline(never)]\npub extern \"x86-interrupt\" fn empty_handler(_frame: &InterruptFrame) {\n    // TODO: it would be nice to know *which vector* the dummy interrupt\n    //      fired on, for debugging purposes...\n    //          - eliza, 05/25/2017\n    debug!(\"an empty interrupt fired!\")\n}\n"
  },
  {
    "path": "src/arch/x86_64/linker.ld",
    "content": "/* Based on http://blog.phil-opp.com/rust-os/multiboot-kernel.html\n *\n * Used to specify a custom linking layout that puts our multiboot header\n * before everything else.\n */\n\nENTRY(_start)\n\nSECTIONS {\n\n    /* Load the kernel reasonably high in memory to avoid special addresses. */\n    . = 1M;\n\n    .rodata :\n    {\n        /* This goes first. */\n        KEEP(*(.multiboot_header))\n        *(.rodata .rodata.*)\n        . = ALIGN(4K);\n    }\n\n    .boot : ALIGN(4K)\n    {\n        KEEP(*(.boot._start))\n        libboot.a(*)\n        KEEP(*(.gdt))\n        . = ALIGN(4K);\n    }\n\n    .text :\n    {\n     /* NOTE we use KEEP here to prevent the linker from dropping\n        these symbols\n      */\n        KEEP(*(.text.arch_init))\n        *(.text .text.*)\n        . = ALIGN(4K);\n    }\n\n     .data :\n     {\n       *(.data .data.*)\n       . = ALIGN(4K);\n     }\n\n     .bss :\n     {\n         *(.bss .bss.*)\n         . = ALIGN(4K);\n        /* Page-Map Level-4 Table (PML4) */\n        pml4_table = .;\n        . += 4K;\n        /* Page-Directory Pointer Table (PDP) */\n        pdp_table = .;\n        . += 4K;\n        /* Page-Directory Table (PD) */\n        pd_table = .;\n        . += 4K;\n            . = ALIGN(4K);\n        stack_base = .;\n        . += 4K * 8;\n        stack_top = .;\n            . = ALIGN(4K);\n        heap_base_addr = .;\n        . += 4K * 2K;\n        heap_top_addr = .;\n        . = ALIGN(4K);\n     }\n\n    .got :\n    {\n      *(.got)\n      . = ALIGN(4K);\n    }\n\n    .got.plt :\n    {\n      *(.got.plt)\n      . = ALIGN(4K);\n    }\n\n    .data.rel.ro : ALIGN(4K) {\n      *(.data.rel.ro.local*) *(.data.rel.ro .data.rel.ro.*)\n      . = ALIGN(4K);\n    }\n\n    .gcc_except_table : ALIGN(4K) {\n      *(.gcc_except_table)\n      . = ALIGN(4K);\n}\n}\n"
  },
  {
    "path": "src/arch/x86_64/mod.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza Weisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\n//! `x86_64` architecture-specific implementation.\n// pub mod cpu;\npub mod drivers;\npub mod interrupts;\n\n#[path = \"../x86_all/bda.rs\"] pub mod bda;\n#[path = \"../x86_all/multiboot2.rs\"] pub mod multiboot2;\n\npub const ARCH_BITS: u8 = 64;\n\nextern {\n    // TODO: It would be really nice if there was a less ugly way of doing\n    // this... (read: after the Revolution when we add memory regions to the\n    // heap programmatically.)\n    #[link_name = \"heap_base_addr\"]\n    #[linkage = \"external\"]\n    pub static HEAP_BASE: *mut u8;\n    #[link_name = \"heap_top_addr\"]\n    #[linkage = \"external\"]\n    pub static HEAP_TOP: *mut u8;\n    // Of course, we will still need to export the kernel stack addresses like\n    // this, but it would be nice if they could be, i dont know, not mut u8s\n    // pointers, like God intended.\n    #[link_name = \"stack_base\"]\n    pub static STACK_BASE: *mut u8;\n    #[link_name = \"stack_top\"]\n    pub static STACK_TOP: *mut u8;\n}\n\nuse memory::PAddr;\n\n/// Trampoline to ensure we have a correct stack frame for calling [`arch_init`]\n///\n/// I have no idea why this works, but it does.\n///\n/// [`arch_init`]: fn.arch_init\n#[naked]\n#[no_mangle]\npub unsafe extern \"C\" fn long_mode_init() {\n    asm!(\"movabsq $$(stack_top), %rsp\");\n    asm!(\"mov ax, 0\n          mov ss, ax\n          mov ds, ax\n          mov es, ax\n          mov fs, ax\n          mov gs, ax\n          call arch_init\"\n        :::: \"intel\");\n\n}\n\n/// Entry point for architecture-specific kernel init\n///\n/// This expects to be passed the address of a valid\n/// Multiboot 2 info struct. It's the bootloader's responsibility to ensure\n/// that this is passed in the correct register as expected by the calling\n/// convention (`edi` on x86). If this isn't there, you can expect to have a\n/// bad problem and not go to space today.\n#[no_mangle]\npub extern \"C\" fn arch_init(multiboot_addr: PAddr) {\n    use cpu::{control_regs, msr};\n    use params::{InitParams, mem};\n\n    kinfoln!(dots: \" . \", \"Beginning `arch_init()` for x86_64\");\n\n    ::io::term::CONSOLE.lock().clear();\n    ::logger::initialize()\n        .expect(\"Could not initialize logger!\");\n\n\n    // -- Unpack multiboot tag ------------------------------------------------\n    kinfoln!( dots: \" . \"\n            , \"trying to unpack multiboot info at {:?}\"\n            , multiboot_addr);\n\n    // try to interpret the structure at the multiboot address as a multiboot\n    // info struct. if it's invalid, fail.\n    let boot_info\n        = unsafe { multiboot2::Info::from(multiboot_addr)\n                    .expect(\"Could not unpack multiboot2 information!\") };\n\n    // Extract ELF sections tag from the multiboot info\n    let elf_sections_tag\n        = boot_info.elf_sections()\n                   .expect(\"ELF sections tag required!\");\n\n    kinfoln!(dots: \" . \", \"Detecting kernel ELF sections:\");\n\n    // Extract kernel ELF sections from  multiboot info\n    let mut n_elf_sections = 0;\n\n    let kernel_begin\n        = elf_sections_tag.sections()\n            // .filter(|s| s.is_allocated())\n            .map(|s| {\n                kinfoln!( dots: \" . . \", \"{}\", s );\n                kinfoln!( dots: \" . . . \", \"flags: [ {:?} ]\", s.flags());\n                s.address() })\n            .min()\n            .expect(\"Could not find kernel start section!\\\n                    \\nSomething is deeply wrong.\");\n\n\n    let kernel_end\n        = elf_sections_tag.sections()\n            // .filter(|s| s.is_allocated())\n            .map(|s| { n_elf_sections += 1; s.end_address() })\n            .max()\n            .expect(\"Could not find kernel end section!\\\n                    \\nSomething is deeply wrong.\");\n\n    kinfoln!( dots: \" . \", \"Detected {} kernel ELF sections.\", n_elf_sections);\n    kinfoln!( dots: \" . . \", \"Kernel begins at {:#p} and ends at {:#p}.\"\n            , kernel_begin, kernel_end );\n\n    let multiboot_end = multiboot_addr + boot_info.length as u64;\n\n    kinfoln!( dots: \" . . \", \"Multiboot info begins at {:#x} and ends at {:#x}.\"\n            , multiboot_addr, multiboot_end);\n\n    let mut params = InitParams { kernel_base: kernel_begin\n                            , kernel_top: kernel_end\n                            , multiboot_start: Some(multiboot_addr)\n                            , multiboot_end: Some(multiboot_end)\n                            , heap_base: unsafe { PAddr::from(HEAP_BASE) }\n                            , heap_top: unsafe { PAddr::from(HEAP_TOP) }\n                            , stack_base: unsafe { PAddr::from(STACK_BASE) }\n                            , stack_top: unsafe { PAddr::from(STACK_TOP) }\n                            , elf_sections: Some(elf_sections_tag.sections())\n                            , ..Default::default()\n                        };\n\n    // Extract the memory map tag from the multiboot info\n    let mem_map = boot_info.mem_map()\n                           .expect(\"Memory map tag required!\");\n\n    kinfoln!(dots: \" . \", \"Detected memory areas:\");\n    for area in mem_map {\n        kinfoln!( dots: \" . . \", \"{}\", area);\n        let a: mem::Area = area.into();\n        if a.is_usable == true { params.mem_map.push(a); }\n    }\n\n     //-- enable flags needed for paging ------------------------------------\n     unsafe {\n        //  control_regs::cr0::enable_write_protect(true);\n        //  kinfoln!(dots: \" . \", \"Page write protect ENABED\" );\n\n        let efer = msr::read(msr::IA32_EFER);\n        trace!(\"EFER = {:#x}\", efer);\n        msr::write(msr::IA32_EFER, efer | (1 << 11));\n        let efer = msr::read(msr::IA32_EFER);\n        trace!(\"EFER = {:#x}\", efer);\n        kinfoln!(dots: \" . \", \"Page no execute bit ENABLED\");\n     }\n\n    kinfoln!(dots: \" . \", \"Transferring to `kernel_init()`.\");\n    ::kernel_init(&params);\n}\n"
  },
  {
    "path": "src/arch/x86_all/bda.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2016 Eliza Weisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\n//! BIOS Data Area\n//!\n//! see [the OS Dev Wiki]\n//! (http://wiki.osdev.org/Memory_Map_(x86)#BIOS_Data_Area_.28BDA.29)\n//! for more information.\n\ntype Word = u16;\n\npub mod ports {\n    use super::Word;\n    const PORTS_ADDR: usize = 0x0400;\n\n    lazy_static! {\n        /// BIOS Data Area that stores the addresses of serial and parallel ports\n        static ref PORTS: &'static Ports\n            = unsafe { &*(PORTS_ADDR as *const Ports) };\n    }\n\n    unsafe impl Send for Ports {}\n    unsafe impl Sync for Ports {}\n\n    /// Addresses of ports stored in the BIOS Data Area.\n    ///\n    #[repr(C)]\n    struct Ports {\n        /// Port address of the `COM1` serial port\n        com1: Word\n      , /// Port address of the `COM2` serial port\n        com2: Word\n      , /// Port address of the `COM3` serial port\n        com3: Word\n      , /// Port address of the `COM4` serial port\n        com4: Word\n      , /// Port address of the `LPT1` parallel port\n        lpt1: Word\n      , /// Port address of the `LPT2` parallel port\n        lpt2: Word\n      , /// Port address of the `LPT3` parallel port\n        lpt3: Word\n    }\n    macro_rules! port_addr {\n        ( $($name: ident),+ ) => { $(\n            #[inline]\n            pub fn $name() -> Option<u16> {\n                    match PORTS.$name {\n                        0 => None\n                      , n => Some(n)\n                    }\n                }\n        )+ }\n    }\n\n    port_addr! { com1, com2, com3, com4, lpt1, lpt2, lpt3 }\n\n\n}\n"
  },
  {
    "path": "src/arch/x86_all/multiboot2.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza Weisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\n//! Code for reading & extracting data from Multiboot 2 boot information.\n//!\n//! Consult the [Multiboot Specification](http://nongnu.askapache.com/grub/phcoder/multiboot.pdf)\n//! for more information.\nuse memory::{PAddr, PhysicalPage, FrameRange};\nuse elf::section::{Sections, HeaderRepr as SectionHeader};\nuse params::mem;\n\nuse core::convert::Into;\nuse core::iter::IntoIterator;\nuse core::fmt;\n\nconst END_TAG_LEN: u32 = 8;\n\nconst HEADER_LEN: u32 = 24;\n\npub const MAGIC: u32 = 0xe85250d6;\n\n#[repr(u32)]\npub enum HeaderArch {\n      I386 = 0\n    , Mips = 4\n}\n\n#[repr(C)]\npub struct Header {\n      pub magic: u32\n    , pub arch: HeaderArch\n    , pub header_length: u32\n    , pub checksum: u32\n    , pub end_tag: Tag\n}\n\n#[linkage = \"external\"]\n#[link_section = \".multiboot_header\"]\npub static HEADER: Header = Header {\n    magic: MAGIC\n  , arch: HeaderArch::I386\n  , header_length: HEADER_LEN\n  , checksum: -((MAGIC + 0 + HEADER_LEN) as i32) as u32\n  , end_tag: Tag { ty: TagType::End\n                 , length: END_TAG_LEN\n                 }\n};\n\n#[repr(C)]\npub struct Info { pub length: u32\n                , _pad: u32\n                , tag_start: Tag\n                }\n\nimpl Info {\n\n    #[inline]\n    pub fn start_addr(&self) -> PAddr {\n        PAddr::from(self as *const _ as u64)\n    }\n\n    pub fn end_addr(&self) -> PAddr {\n        PAddr::from(self.start_addr() + self.length as u64)\n    }\n\n    /// TODO: rewrite this as a `TryFrom` implementation (see issue #85)\n    //          - eliza, 03/09/2017\n    pub unsafe fn from(addr: PAddr) -> Result<&'static Self, &'static str> {\n        let info: &Info = &*(addr.into(): u64 as *const Info);\n        // TODO: check if the multiboot tag *exists* at this location as well?\n        //       since if we pass in the wrong address, we'll still make the\n        //       \"no end tag\" error.\n        //\n        //       which, i suppose is *technically* correct, but not very\n        //       helpful...\n        //          - eliza, 03/04/2017\n        if info.has_end() {\n            Ok(info)\n        } else {\n            Err( \"Multiboot info structure at {:?} had no end tag!\")\n        }\n    }\n\n    /// Finds the tag with the given tag type.\n    ///\n    /// This is actually safe since the tag types are constrained by The\n    /// `TagType` enum\n    ///\n    /// # Returns\n    ///  - `Some(tag)` if a tag of the given type could be found.\n    ///  - `None` if no tag of the given type could be found.\n    pub fn get_tag(&'static self, tag_type: TagType) -> Option<&'static Tag> {\n        self.tags()\n            .find(|t| t.ty == tag_type)\n    }\n\n    /// Finds the memory map tag.\n    ///\n    ///  # Returns\n    ///  - `Some(MemMapTag)` if a memory map tag could be found\n    ///  - `None` if no tag of the given type could be found.\n    #[inline]\n    pub fn mem_map(&'static self) -> Option<&'static MemMapTag> {\n        self.get_tag(TagType::MemoryMap)\n            .map(|tag| unsafe { &*((tag as *const Tag) as *const MemMapTag) })\n    }\n\n    /// Finds the ELF sections tag.\n    ///\n    ///  # Returns\n    ///  - `Some(ElfSectionsTag)` if a memory map tag could be found\n    ///  - `None` if no tag of the given type could be found.\n    #[inline]\n    pub fn elf_sections(&'static self) -> Option<&'static ElfSectionsTag> {\n        self.get_tag(TagType::ELFSections)\n            .map(|tag| unsafe {\n                &*((tag as *const Tag) as *const ElfSectionsTag)\n            })\n    }\n\n    /// Returns an iterator over all Multiboot tags.\n    #[inline]\n    fn tags(&'static self) -> Tags { Tags(&self.tag_start as *const Tag) }\n\n    /// Returns true if the multiboot structure has a valid end tag.\n    fn has_end(&self) -> bool {\n        // TODO: we should be able to use ptr::offset() here?\n        //          - eliza, 03/05/2017\n        let end_tag_addr\n            = self as *const _ as usize +\n              (self.length as usize - END_TAG_LEN as usize);\n        let end_tag = unsafe {&*(end_tag_addr as *const Tag)};\n        end_tag.ty == TagType::End && end_tag.length == 8\n    }\n\n    /// Returns the kernel frame range from the Multiboot 2 ELF Sections\n    pub fn kernel_frames(&'static self) -> Result<FrameRange, &'static str> {\n        let sections_tag = self.elf_sections()\n                               .ok_or(\"ELF sections tag required!\")?;\n\n        let kernel_start = sections_tag.sections()\n                              .map(|s| s.address())\n                              .min()\n                              .ok_or(\"Couldn't find kernel start section!\")?;\n        let kernel_end = sections_tag.sections()\n                              .map(|s| s.address())\n                              .max()\n                              .ok_or(\"Couldn't find kernel end section!\")?;\n\n        Ok(PhysicalPage::from(kernel_start) .. PhysicalPage::from(kernel_end))\n    }\n}\n\nimpl IntoIterator for &'static Info {\n    type IntoIter = Tags;\n    type Item = &'static Tag;\n    #[inline]  fn into_iter(self) -> Self::IntoIter { self.tags() }\n\n}\n\n\n/// A Multiboot tag.\n///\n/// From the specification:\n///\n/// Boot information consists of a fixed part and a series of tags.\n/// Its start is 8-bytes aligned. Fixed part is as following:\n///\n///<rawtext>\n///\n///             +-------------------+\n///     u32     | total_size        |\n///     u32     | reserved          |\n///             +-------------------+\n///</rawtext>\n///\n/// `total_size` contains the total size of boot information including this\n/// field and terminating tag in bytes.\n/// `reserved` is always set to zero and must be ignored by OS image.\n///\n///  Every tag begins with following fields:\n///<rawtext>\n///\n///             +-------------------+\n///     u32     | type              |\n///     u32     | size              |\n///             +-------------------+\n///</rawtext>\n/// `type` contains an identifier of contents of the rest of the tag. `size`\n/// contains the size of tag including header fields but not including padding.\n/// Tags follow one another padded when necessary in order for each tag to\n/// start at 8-bytes aligned address. Tags are terminated by a tag of type `0`\n/// and size `8`.\n#[repr(C)]\n#[derive(Debug)]\npub struct Tag { /// the type of this tag.\n                 pub ty: TagType\n               , length: u32\n               }\n\n/// Types of Multiboot tags\n///\n/// Refer to Chapter 3 of the Multiboot 2 spec\n#[repr(u32)]\n#[derive(Debug, Eq, PartialEq)]\npub enum TagType { /// Tag that indicates the end of multiboot tags\n                   End              = 0\n                 , /// Command line passed to the bootloader\n                   CommandLine      = 1\n                 , BootloaderName   = 2\n                 , Modules          = 3\n                 , BasicMemInfo     = 4\n                 , BIOSBootDev      = 5\n                 , MemoryMap        = 6\n                 , VBEInfo          = 7\n                 , FramebufferInfo  = 8\n                 , ELFSections      = 9\n                 , APMTable         = 10\n                 }\n\n/// An iterator over Multiboot 2 tags.\npub struct Tags(*const Tag);\n\nimpl Tags {\n    #[inline] fn advance(&mut self, size: u32) {\n        let next_addr = self.0 as usize + size as usize;\n        self.0 = (((next_addr-1) & !0x7) + 0x8) as *const _;\n    }\n}\n\nimpl Iterator for Tags {\n    type Item = &'static Tag;\n\n    #[inline]\n    fn next(&mut self) -> Option<Self::Item> {\n        match unsafe { &*self.0 } {\n            &Tag { ty: TagType::End, length: END_TAG_LEN } => None\n          , tag => {\n              self.advance(tag.length);\n              Some(tag)\n            }\n        }\n    }\n}\n\n/// A Memory Map tag\n#[repr(C)]\npub struct MemMapTag { tag: Tag\n                     , pub entry_size: u32\n                     , pub entry_version: u32\n                     , first_entry: MemArea\n                     }\n\nimpl MemMapTag {\n\n    /// Returns an iterator over all the memory areas in this tag.\n    #[inline] pub fn areas(&'static self) -> MemAreas {\n        MemAreas { curr: (&self.first_entry) as *const MemArea\n                    // TODO: we should be able to use ptr::offset() here?\n                    //          - eliza, 03/05/2017\n                 , last: ((self as *const MemMapTag as u32) +\n                         self.tag.length - self.entry_size)\n                         as *const MemArea\n                 , size: self.entry_size\n                 }\n    }\n}\n\nimpl IntoIterator for &'static MemMapTag {\n    type Item = &'static MemArea;\n    type IntoIter = MemAreas;\n\n    #[inline] fn into_iter(self) -> Self::IntoIter { self.areas() }\n\n}\n\n\n/// A tag that stores the boot command line.\n#[repr(C)]\npub struct CommandLineTag { tag: Tag\n                          , /// The boot command line.\n                            ///\n                            /// The command line is a normal C-style zero-\n                            /// terminated UTF-8 string.\n                            pub command_line: [u8]\n                          }\n\n\n#[repr(C)]\npub struct ModulesTag { tag: Tag\n                      , /// The address at which the module begins.\n                        pub mod_begin: PAddr\n                      , /// The address at which the module ends.\n                        pub mod_end: PAddr\n                      , /// A string (typically a command line)\n                        pub string: [u8]\n                      }\n\n#[repr(u32)]\n#[derive(Debug, Eq, PartialEq, Ord, PartialOrd)]\npub enum MemAreaType { Available = 1\n                     , Acpi      = 3\n                     , Preserve  = 4\n                     }\n\n/// A multiboot 2 memory area\n#[repr(C)]\n#[derive(Debug)]\npub struct MemArea { /// the starting address of the memory area\n                     pub base: PAddr\n                   , /// the length of the memory area\n                     pub length: PAddr\n                   , /// the type of the memory area\n                     pub ty: MemAreaType\n                   , _pad: u32\n                   }\n\nimpl MemArea {\n    #[inline] pub fn address(&self) -> PAddr {\n        self.base + self.length - 1\n    }\n}\n\nimpl<'a> Into<mem::Area> for &'a MemArea {\n    #[inline]\n    fn into(self) -> mem::Area {\n        mem::Area {\n            start_addr: self.base\n          , end_addr: self.address()\n          , is_usable: if let MemAreaType::Available = self.ty { true }\n                       else { false }\n        }\n    }\n}\n\nimpl fmt::Display for MemArea {\n    #[inline]\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        write!( f, \"{:?} from {:#08x} to {:#08x}\"\n              , self.ty, self.base, self.address())\n    }\n}\n\n/// An iterator over memory areas\n#[derive(Clone)]\npub struct MemAreas { curr: *const MemArea\n                    , last: *const MemArea\n                    , size: u32\n                    }\n\nimpl Iterator for MemAreas {\n    type Item = &'static MemArea;\n\n    fn next(&mut self) -> Option<&'static MemArea> {\n        if self.curr > self.last {\n            None\n        } else {\n            let current = unsafe { &*self.curr };\n            // TODO: we should be able to use ptr::offset() here.\n            //          - eliza, 03/05/2017\n            self.curr = (self.curr as u32 + self.size) as *const MemArea;\n            // if current.ty == MemAreaType::Available {\n            // NOTE: this used to skip over unavailable or ACPI memory areas,\n            //       but i've disabled that as we may want to iterate over thsoe\n            //       memory areas. we can use `filter` on this iterator to get\n            //       only available memory areas.\n            //          - eliza, 03/05/2017\n            Some(current)\n            // } else {\n            //      self.next()\n            // }\n        }\n    }\n}\n\n#[cfg(target_pointer_width = \"32\")]\npub type Word = u32;\n#[cfg(target_pointer_width = \"64\")]\npub type Word = u64;\n\n/// A Multiboot 2 ELF sections tag\n#[derive(Debug)]\n#[repr(packed)]\npub struct ElfSectionsTag { tag: Tag\n                          , /// the number of sections pointed to by this tag\n                            pub n_sections: u32\n                          , /// the size of each ELF section\n                            pub section_size: u32\n                          , stringtable_idx: u32\n                          , first_section: SectionHeader<Word>\n                          }\n\nimpl ElfSectionsTag {\n    /// Returns an iterator over the ELF sections pointed to by this tag.\n    //  TODO: can the &'static bound be reduced to &'a? is there any reason to?\n    //          - eliza, 03/04/2017\n    #[inline] pub fn sections(&'static self) -> Sections<'static, Word> {\n        Sections::new( &self.first_section\n                     , self.n_sections - 1\n                     , self.section_size\n                     )\n    }\n}\n\nimpl IntoIterator for &'static ElfSectionsTag {\n    //  TODO: can the &'static bound be reduced to &'a? is there any reason to?\n    //          - eliza, 03/04/2017\n    type Item = <Self::IntoIter as Iterator>::Item;\n    type IntoIter = Sections<'static, Word>;\n\n    #[inline] fn into_iter(self) -> Self::IntoIter { self.sections() }\n\n}\n"
  },
  {
    "path": "src/heap.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza Weisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\nuse params::InitParams;\n\n/// Initialise the kernel heap.\n//  TODO: this is the Worst Thing In The Universe. De-stupid-ify it.\npub unsafe fn initialize<'a>(params: &InitParams) -> Result<&'a str, &'a str> {\n    // let heap_base_ptr = params.heap_base.as_mut_ptr();\n    let heap_size: u64 = (params.heap_top - params.heap_base).into();\n    // buddy::system::init_heap(heap_base_ptr, heap_size as usize);\n    Ok(\"[ OKAY ]\")\n}\n"
  },
  {
    "path": "src/io/keyboard.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza Weisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\n//! PS/2 keyboard driver\nuse cpu::Port;\nuse spin::Mutex;\n\nuse core::default::Default;\n\n/// PS/2 keyboard scancode\n#[derive(Copy,Clone,Debug)]\npub struct Scancode(u8);\n\nimpl Scancode {\n    fn to_ascii(&self) -> Option<u8> {\n        match self.0 {\n            0x01 ... 0x0e => Some(TO_ASCII_LOW[self.0 as usize - 0x01])\n          , 0x0f ... 0x1c => Some(TO_ASCII_MID1[self.0 as usize - 0x0f])\n          , 0x1e ... 0x28 => Some(TO_ASCII_MID2[self.0 as usize - 0x1e])\n          , 0x2c ... 0x35 => Some(TO_ASCII_HIGH[self.0 as usize - 0x2c])\n          , 0x39 => Some(b' ')\n          , _ => None\n        }\n    }\n}\n\n/// A PS/2 keyboard state\npub struct Keyboard { /// Port for reading data from the keyboard\n                      data_port: Port<u8>\n                    // , /// Port for sending control signals to the keyboard\n                    //   control_port: Port\n                    , /// The keyboard's modifier keys\n                      pub state: Modifiers\n                    }\n\nimpl Keyboard {\n    #[inline] pub fn read_scancode(&self) -> Scancode {\n        Scancode(self.data_port.read())\n    }\n}\n\n/// Scancodes range 0x01 ... 0x1c\nconst TO_ASCII_LOW: &'static [u8; 17]\n    = b\"\\x1B1234567890-=\\0x02\";\n\nconst TO_ASCII_MID1: &'static [u8; 14] = b\"\\tqwertyuiop[]\\r\";\n\n/// Scancodes range 0x1E ... 0x28\nconst TO_ASCII_MID2: &'static [u8; 11] = b\"asdfghjkl;'\";\n\n/// Scancodes range 0x2C ... 0x35\nconst TO_ASCII_HIGH: &'static [u8; 10] = b\"zxcvbnm,./\";\n\n\nbitflags! {\n    pub flags Modifiers: u8 { const L_SHIFT  = 0b1000_0000\n                            , const R_SHIFT  = 0b0100_0000\n                            , const SHIFT    = L_SHIFT.bits | R_SHIFT.bits\n                            , const R_CTRL   = 0b0010_0000\n                            , const L_CTRL   = 0b0001_0000\n                            , const CTRL     = L_CTRL.bits | R_CTRL.bits\n                            , const R_ALT    = 0b0000_1000\n                            , const L_ALT    = 0b0000_0100\n                            , const ALT      = L_ALT.bits | R_ALT.bits\n                            , const CAPSLOCK = 0b0000_0010\n                            , const NUMLOCK  = 0b0000_0001\n                            }\n}\n\nimpl Default for Modifiers {\n    #[inline] fn default() -> Self { Modifiers::new() }\n}\n\nimpl Modifiers {\n\n    pub const fn new() -> Self {\n        Modifiers { bits: 0b0000_0000 }\n    }\n\n    /// Returns true if either shift key is pressed.\n    #[inline] pub fn is_shifted(&self) -> bool {\n        self.contains(SHIFT)\n    }\n\n    /// Returns true if the keyboard's state is currently uppercase.\n    #[inline] pub fn is_uppercase(&self) -> bool {\n        self.is_shifted() ^ self.contains(CAPSLOCK)\n    }\n\n    /// Updates the modifiers state from a given scancode.\n    fn update(&mut self, scancode: Scancode) {\n        match scancode { Scancode(0x1D) => self.insert(L_CTRL)\n                       , Scancode(0x2A) => self.insert(L_SHIFT)\n                       , Scancode(0x36) => self.insert(R_SHIFT)\n                       , Scancode(0x38) => self.insert(L_ALT)\n                         // Caps lock toggles on leading edge\n                       , Scancode(0x3A) => self.toggle(CAPSLOCK)\n                       , Scancode(0x9D) => self.remove(L_CTRL)\n                       , Scancode(0xAA) => self.remove(L_SHIFT)\n                       , Scancode(0xB6) => self.remove(R_SHIFT)\n                       , Scancode(0xB8) => self.remove(L_ALT)\n                       , _    => {}\n        }\n    }\n\n    /// Apply the keyboard's modifiers to an ASCII scancode.\n    fn modify(&self, ascii: u8) -> u8 {\n        match ascii {\n            b'a' ... b'z' if self.is_uppercase() => ascii - b'a' + b'A'\n          , b'1' ... b'9' if self.is_shifted()   => ascii - b'1' + b'!'\n          , b'0' if self.is_shifted()            => b')'\n          , _ => ascii\n        }\n    }\n}\n\n/// Our global keyboard state, protected by a mutex.\n//  TODO: can this be thread local?\nstatic KEYBOARD: Mutex<Keyboard> = Mutex::new(Keyboard {\n    data_port: Port::<u8>::new(0x60)\n  , state: Modifiers::new()\n});\n\npub fn read_char() -> Option<char> {\n    let mut lock = KEYBOARD.lock();\n\n    let code = lock.read_scancode();\n    lock.state.update(code);\n\n    code.to_ascii()\n        .map(|ascii| lock.state.modify(ascii) as char)\n}\n"
  },
  {
    "path": "src/io/mod.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza Weisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\n//! Kernel IO.\n//!\n//! This module should eventually abstract over architecture-specific\n//! implementation.\npub mod term;\npub mod keyboard;\n"
  },
  {
    "path": "src/io/term.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza Weisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\nextern {\n    pub static __vga_buffer: u8;\n}\n/// The system's global VGA terminal\npub use vga::CONSOLE;\n"
  },
  {
    "path": "src/logger.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza Weisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\nuse log;\nuse log::{LogRecord, LogLevel, LogMetadata, LogLevelFilter};\nuse arch::drivers::serial;\n\nuse core::fmt::Write;\n\nstruct SerialLogger;\n\npub fn initialize() -> Result<(), log::SetLoggerError> {\n    unsafe {\n        log::set_logger_raw(|max_log_level| {\n            max_log_level.set(LogLevelFilter::Trace);\n            &SerialLogger\n        })\n    }\n}\npub fn shutdown() -> Result<(), log::ShutdownLoggerError> {\n    log::shutdown_logger_raw().map(|_logger| {\n    })\n}\n\n\n#[cfg(debug_assertions)]\nimpl log::Log for SerialLogger {\n\n    #[inline] fn enabled(&self, _metadata: &LogMetadata) -> bool {\n        true // TODO: for now?\n    }\n\n    #[inline]\n    fn log(&self, record: &LogRecord) {\n        let meta = record.metadata();\n        match record.level() {\n            LogLevel::Trace if self.enabled(meta) => {\n                let location = record.location();\n                let _ = write!( *serial::COM1.lock()\n                              , \"[ TRACE ][ {}:{} ] {}: {}\\n\"\n                              , location.module_path(), location.line()\n                              , meta.target()\n                              , record.args() );\n            }\n          , LogLevel::Debug if self.enabled(meta) => {\n                let _ = write!( *serial::COM1.lock()\n                              , \"[ DEBUG ] {}: {}\\n\"\n                              , meta.target()\n                              , record.args() );\n            }\n          , level => {\n                let target = meta.target();\n                let args = record.args();\n                let _ = write!( *serial::COM1.lock()\n                              , \"[ {} ] {}: {}\\n\"\n                              , level, target, args );\n                // println!(\"{}: {}\", target, args );\n            }\n        }\n    }\n\n}\n\n#[cfg(not(debug_assertions))]\nimpl log::Log for SerialLogger {\n\n    #[inline] fn enabled(&self, metadata: &LogMetadata) -> bool {\n        false // TODO: for now\n    }\n\n    #[inline]\n    fn log(&self, record: &LogRecord) {\n        let meta = record.metadata();\n        if self.enabled(meta) {\n            println!(\"{}: {}\", target, args );\n            // TODO: should we log for com1 also?\n        }\n    }\n\n}\n"
  },
  {
    "path": "src/main.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza Weisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\n//! # SOS kernel\n//! This crate contains the kernel for SOS, the Stupid Operating System.\n//!\n//! # SOS: the Stupid Operating System\n//! SOS is a simple, tiny toy OS implemented in Rust. It targets the `x86`,\n//! `x86_64`, and ARM v7 CPU architectures.\n//!\n//! I'm writing this mostly for fun, to learn more about OS design and kernel\n//! hacking, so don't expect anything new or exciting out of this project.\n//!\n//! SOS is copyright 2015-2017 Eliza Weisman, and is released under the terms\n//! of the MIT license.\n\n#![crate_name = \"sos_kernel\"]\n\n#![doc(html_root_url = \"https://hawkw.github.io/sos-kernel/\")]\n\n#![feature( lang_items, asm, naked_functions )]\n#![feature( linkage )]\n#![feature( const_fn\n          , slice_patterns\n          , associated_consts\n          , type_ascription\n          , custom_derive )]\n#![feature(alloc)]\n\n#![cfg_attr(feature=\"clippy\", feature(plugin))]\n#![cfg_attr(feature=\"clippy\", plugin(clippy))]\n#![cfg_attr( any(target_arch = \"x86_64\", target_arch=\"x86\")\n           , feature(abi_x86_interrupt))]\n\n#![no_std]\n#![cfg_attr(not(test), no_main)]\n\n// -- non-SOS dependencies --------------------------------------------------\n#[macro_use] extern crate lazy_static;\n#[macro_use] extern crate bitflags;\n#[macro_use] extern crate log;\n\nextern crate alloc;\nextern crate rlibc;\nextern crate spin;\n\n// -- SOS dependencies ------------------------------------------------------\n#[macro_use] extern crate vga;\n\nextern crate sos_alloc;\nextern crate cpu;\nextern crate elf;\nextern crate paging;\nextern crate params;\nextern crate memory;\nextern crate util;\n\n#[macro_use] pub mod io;\n\npub mod heap;\npub mod arch;\npub mod logger;\n\nuse params::InitParams;\n\n/// SOS version number\npub const VERSION_STRING: &'static str\n    = concat!(\"Stupid Operating System v\", env!(\"CARGO_PKG_VERSION\"));\n\n\n/// Kernel main loop\npub fn kernel_main() -> ! {\n    // let mut a_vec = collections::vec::Vec::<usize>::new();\n    // info!(target: \"test\", \"Created a vector in kernel space! {:?}\", a_vec);\n    // a_vec.push(1);\n    // info!(target: \"test\", \"pushed to vec: {:?}\", a_vec);\n    // a_vec.push(2);\n    // info!(target: \"test\", \"pushed to vec: {:?}\", a_vec);\n\n    // let mut frame_allocator = frame_alloc::FrameAllocator::new();\n    // paging::test_paging(&mut frame_allocator);\n\n    loop { }\n}\n\n/// Kernel initialization function called into by architecture-specific init\n///\n/// Our initialization process essentially looks like this:\n///\n/// ```text\n/// +-------------+\n/// | bootloader  |\n/// | (multiboot) |\n/// +------|------+\n/// +------V------+\n/// | start.asm   |\n/// +------|------+\n/// +------|--------------------------------------------------------+\n/// |      |           RUST-LAND KERNEL FUNCTIONS                   |\n/// |      V                                                        |\n/// | arch_init() ----------> kernel_init() --------> kernel_main() |\n/// | + collects boot info   + initializes interrupts               |\n/// |   from arch-specific   + initializes the heap                 |\n/// |   sources              + remaps the kernel into the higher    |\n/// | + some CPU-specific      half of the address space            |\n/// |   configuration                                               |\n/// +---------------------------------------------------------------+\n/// ```\npub fn kernel_init(params: &InitParams) {\n    use sos_alloc::frame::mem_map::MemMapAllocator;\n    use ::paging::kernel_remap;\n\n    kinfoln!(\"Hello from the kernel!\");\n    // kinfoln!(\"Got init params: {:#?}\", params );\n\n    // -- remap the kernel ----------------------------------------------------\n    let mut frame_allocator = MemMapAllocator::from(params);\n    kinfoln!(dots: \" . \", \"Remapping the kernel...\");\n    let page_table = match kernel_remap(&params, &mut frame_allocator) {\n        Ok(p) => {\n            kinfoln!(dots: \" . \", target: \"Remapping the kernel\", \"[ OKAY ]\");\n            p\n        }\n      , Err(why) => {\n            kinfoln!(dots: \" . \", target: \"Remapping the kernel\", \"[ FAIL ]\");\n            panic!( \"Could not remap kernel: {:?}\", why)\n        }\n    };\n\n    attempt!(paging::test_paging(&mut frame_allocator) =>\n             dots: \" . . \", \"Testing paging...\");\n\n    // -- initialize the heap ------------------------------------------------\n    attempt!( unsafe { heap::initialize(params) } =>\n             dots: \" . \", \"Intializing heap...\");\n    kinfoln!( dots: \" . . \"\n            , \"Heap begins at {:#x} and ends at {:#x}\"\n            , params.heap_base, params.heap_top);\n\n\n    // -- initialize interrupts ----------------------------------------------\n    // attempt!( unsafe { arch::interrupts::initialize() } =>\n    //           \"Initializing interrupts...\", dots: \" . \" );\n\n    println!(\"\\n{} {}-bit\\n\", VERSION_STRING, arch::ARCH_BITS);\n\n    // -- call into kernel main loop ------------------------------------------\n    // (currently, this does nothing)\n    kernel_main()\n}\n\n\n/// This fake `main` function exists only to placate `cargo test`.\n#[cfg(test)]\nfn main() {\n\n}\n"
  },
  {
    "path": "targets/x86_32-sos-bootstrap-gnu.json",
    "content": "{\n    \"llvm-target\": \"i386-unknown-unknown-elf\",\n    \"executables\": true,\n    \"linker-flavor\": \"gcc\",\n    \"target-endian\": \"little\",\n    \"target-word-size\": \"32\",\n    \"target-pointer-width\": \"32\",\n    \"target-c-int-width\": \"32\",\n    \"data-layout\": \"e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128\",\n    \"os\": \"sos\",\n    \"arch\": \"x86\",\n    \"features\": \"-mmx,-sse,-sse2,+soft-float\",\n    \"code-model\":\"kernel\",\n    \"relocation-model\": \"static\",\n    \"disable-redzone\": true,\n    \"eliminate-frame-pointer\": false,\n    \"no-compiler-rt\": true,\n    \"linker\": \"no-linker\",\n    \"pre-link-args\": [],\n    \"post-link-args\": [],\n    \"archive-format\": \"gnu\"\n}\n"
  },
  {
    "path": "targets/x86_64-sos-kernel-gnu.json",
    "content": "{\n    \"llvm-target\": \"x86_64-unknown-none-gnu\",\n    \"executables\": true,\n    \"target-endian\": \"little\",\n    \"target-pointer-width\": \"64\",\n    \"target-c-int-width\": \"32\",\n    \"data-layout\": \"e-m:e-i64:64-f80:128-n8:16:32:64-S128\",\n    \"code-model\":\"kernel\",\n    \"relocation-model\": \"static\",\n    \"os\": \"sos\",\n    \"arch\": \"x86_64\",\n    \"linker-flavor\": \"gcc\",\n    \"pre-link-args\": {\n        \"gcc\": [ \"-Tsrc/arch/x86_64/linker.ld\"\n               , \"-Wl,-n\"\n               , \"-nostartfiles\"\n               , \"-nostdlib\"\n               , \"-ffreestanding\"\n               ]\n    },\n    \"cpu\": \"x86-64\",\n    \"features\": \"-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-3dnow,-3dnowa,-avx,-avx2,+soft-float\",\n    \"disable-redzone\": true,\n    \"eliminate-frame-pointer\": false,\n    \"no-compiler-rt\": true,\n    \"archive-format\": \"gnu\"\n}\n"
  },
  {
    "path": "tokamak.toml",
    "content": "[helper]\npath = \"\"                                  # Reserved for future helper path and configurations\n[options]\nsave_buffers_before_run = true             # Saving buffers before every cargo command run\ngeneral_warnings = true                    # Show general warnings\n[project]\nauto_format_timing = 5                     # Run auto formatting for project for specified interval (seconds)\n"
  },
  {
    "path": "util/Cargo.toml",
    "content": "[package]\nname = \"util\"\nversion = \"0.0.1\"\nauthors = [ \"Eliza Weisman <eliza@elizas.website>\" ]\n\n[profile.dev]\nopt-level = 3\ndebug = true\nrpath = false\nlto = false\ndebug-assertions = true\ncodegen-units = 1\npanic = \"abort\"\n\n[profile.release]\nopt-level = 3\ndebug = true\nrpath = false\nlto = false\npanic = \"abort\"\n\n# [dependencies.vga]\n# path = \"../vga\"\n# features = [\"system_term\"]\n# optional = true\n"
  },
  {
    "path": "util/src/io.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2016 Eliza Weisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\n\n\n/// The `Read` trait allows for reading bytes from a source.\n///\n/// Implementors of the `Read` trait are sometimes called 'readers'.\n///\n/// Readers are defined by one required method, `read()`. Each call to `read`\n/// will attempt to pull bytes from this source into a provided buffer. A\n/// number of other methods are implemented in terms of `read()`, giving\n/// implementors a number of ways to read bytes while only needing to implement\n/// a single method.\n///\n/// This is basically a brain-dead reimplementation of the standard\n/// library's `Read` trait. Most of the methods available on the\n/// standard lib's `Read` are not yet implemented.\npub trait Read {\n    type Error;\n    /// Pull some bytes from this source into the specified buffer, returning\n    /// how many bytes were read.\n    ///\n    /// This function does not provide any guarantees about whether it blocks\n    /// waiting for data, but if an object needs to block for a read but cannot\n    /// it will typically signal this via an `Err` return value.\n    ///\n    /// If the return value of this method is `Ok(n)`, then it must be\n    /// guaranteed that `0 <= n <= buf.len()`. A nonzero `n` value indicates\n    /// that the buffer `buf` has been filled in with `n` bytes of data from\n    /// this source. If `n` is `0`, then it can indicate one of two scenarios:\n    ///\n    /// 1. This reader has reached its \"end of file\" and will likely no longer\n    ///    be able to produce bytes. Note that this does not mean that the\n    ///    reader will *always* no longer be able to produce bytes.\n    /// 2. The buffer specified was 0 bytes in length.\n    ///\n    /// No guarantees are provided about the contents of `buf` when this\n    /// function is called, implementations cannot rely on any property of the\n    /// contents of `buf` being true. It is recommended that implementations\n    /// only write data to `buf` instead of reading its contents.\n    ///\n    /// # Errors\n    ///\n    /// If this function encounters any form of I/O or other error, an error\n    /// variant will be returned. If an error is returned then it must be\n    /// guaranteed that no bytes were read.\n    fn read(&mut self, buf: &mut [u8])     -> Result<usize, Self::Error>;\n\n    /// Read all bytes until EOF in this source, placing them into `buf`.\n    ///\n    /// All bytes read from this source will be appended to the specified buffer\n    /// `buf`. This function will continuously call `read` to append more data\n    /// to `buf` until `read` returns either `Ok(0)` or an error.\n    ///\n    /// If successful, this function will return the total number of bytes read.\n    fn read_all(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error>;\n}\n\n/// A trait for objects which are byte-oriented sinks.\n///\n/// Implementors of the `Write` trait are sometimes called 'writers'.\n///\n/// Writers are defined by two required methods, `write()` and `flush()`:\n///\n/// * The `write()` method will attempt to write some data into the object,\n///   returning how many bytes were successfully written.\n///\n/// * The `flush()` method is useful for adaptors and explicit buffers\n///   themselves for ensuring that all buffered data has been pushed out to the\n///   'true sink'.\n///\n/// This is basically a brain-dead reimplementation of the standard\n/// library's `Write` trait. Most of the methods available on the\n/// standard lib's `Write` are not yet implemented.\npub trait Write {\n    type Error;\n\n    /// Write a buffer into this object, returning how many bytes were written.\n    ///\n    /// This function will attempt to write the entire contents of `buf`, but\n    /// the entire write may not succeed, or the write may also generate an\n    /// error. A call to `write` represents *at most one* attempt to write to\n    /// any wrapped object.\n    ///\n    /// Calls to `write` are not guaranteed to block waiting for data to be\n    /// written, and a write which would otherwise block can be indicated through\n    /// an `Err` variant.\n    ///\n    /// If the return value is `Ok(n)` then it must be guaranteed that\n    /// `0 <= n <= buf.len()`. A return value of `0` typically means that the\n    /// underlying object is no longer able to accept bytes and will likely not\n    /// be able to in the future as well, or that the buffer provided is empty.\n    ///\n    /// # Errors\n    ///\n    /// Each call to `write` may generate an I/O error indicating that the\n    /// operation could not be completed. If an error is returned then no bytes\n    /// in the buffer were written to this writer.\n    ///\n    /// It is **not** considered an error if the entire buffer could not be\n    /// written to this writer.\n    fn write(&mut self, buf: &[u8])       -> Result<usize, Self::Error>;\n}\n"
  },
  {
    "path": "util/src/lib.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2016 Eliza Weisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\n//! General purpose stuff I couldn't find a better home for.\n#![crate_name = \"util\"]\n#![no_std]\n\n#![feature(step_trait)]\n// #[cfg(not(test))] extern crate vga;\n\nuse core::{fmt, ops};\nuse ops::*;\nuse core::iter::Step;\n// use core::num::One;\n\npub mod io;\n\n#[macro_use] pub mod macros;\n\n/// The unreachable Void type.\npub enum Void {}\nimpl fmt::Debug for Void {\n    fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result {\n        unreachable!()\n    }\n}\n\npub trait Align: Sized + Copy //+ One\n               + Add<Output=Self> + Sub<Output=Self>\n               + BitAnd<Output=Self> + Not<Output=Self>\n               + Step\n{\n    #[inline] fn align_up(&self, to: Self) -> Self {\n        let align = to.sub_one();\n        (*self + align) & !align\n    }\n    #[inline] fn align_down(&self, to: Self) -> Self {\n        *self & !to.sub_one()\n    }\n}\n\nimpl Align for u64 { }\nimpl Align for u32 { }\nimpl Align for usize { }\n"
  },
  {
    "path": "util/src/macros/mod.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza Weisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\n\n#![allow(missing_docs)]\n#[macro_export]\nmacro_rules! expr { ($e:expr) => { $e } }\n\n#[macro_use] pub mod newtype_impl;\n// #[macro_use] pub mod log;\n"
  },
  {
    "path": "util/src/macros/newtype_impl.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza Weisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\n\n#[macro_export]\nmacro_rules! forward_ref_binop {\n    ($imp:ident, $method:ident for $t:ty, $u:ty) => {\n            impl<'a> ::core::ops::$imp<$u> for &'a $t {\n                type Output = <$t as ::core::ops::$imp<$u>>::Output;\n                #[inline]\n                fn $method(self, other: $u)\n                          -> <$t as ::core::ops::$imp<$u>>::Output {\n                    ::core::ops::$imp::$method(*self, other)\n                }\n            }\n\n            impl<'a> ::core::ops::$imp<&'a $u> for $t {\n                type Output = <$t as ::core::ops::$imp<$u>>::Output;\n                #[inline]\n                fn $method(self, other: &'a $u)\n                          -> <$t as ::core::ops::$imp<$u>>::Output {\n                    ::core::ops::$imp::$method(self, *other)\n                }\n            }\n\n            impl<'a, 'b> ::core::ops::$imp<&'a $u> for &'b $t {\n                type Output = <$t as ::core::ops::$imp<$u>>::Output;\n\n                #[inline]\n                fn $method(self, other: &'a $u) -> <$t as ::core::ops::$imp<$u>>::Output {\n                    ::core::ops::$imp::$method(*self, *other)\n                }\n            }\n    };\n}\n#[macro_export]\nmacro_rules! impl_ops {\n    ($($name:ident, $fun:ident, $op:tt for $ty:ident, $size:ty)*) => {$(\n        impl ::core::ops::$name<$ty> for $ty {\n            type Output = $ty;\n\n            #[inline] fn $fun(self, rhs: $ty) -> $ty {\n                $ty(expr!(self.0 $op rhs.0))\n            }\n        }\n        impl ::core::ops::$name<$size> for $ty {\n            type Output = $ty;\n\n            #[inline] fn $fun(self, rhs: $size) -> $ty {\n                $ty(expr!(self.0 $op rhs))\n            }\n        }\n\n        forward_ref_binop! {\n            $name, $fun for $ty, $ty\n        }\n        forward_ref_binop! {\n            $name, $fun for $ty, $size\n        }\n    )*}\n}\n#[macro_export]\nmacro_rules! impl_assign_ops {\n    ($($name:ident, $fun:ident, $op:tt for $ty:ident, $size:ty)*) => {$(\n        impl ::core::ops::$name<$ty> for $ty {\n\n            #[inline] fn $fun(&mut self, rhs: $ty) {\n                expr!(self.0 $op rhs.0);\n            }\n        }\n        impl ::core::ops::$name<$size> for $ty {\n\n            #[inline] fn $fun(&mut self, rhs: $size) {\n                expr!(self.0 $op rhs);\n            }\n        }\n    )*}\n}\n#[macro_export]\nmacro_rules! impl_fmt {\n    ($($name:ident for $ty:ty)*) => {$(\n        impl ::core::fmt::$name for $ty {\n            fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {\n                self.0.fmt(f)\n            }\n        }\n    )*}\n}\n"
  },
  {
    "path": "vga/Cargo.toml",
    "content": "[package]\nname = \"vga\"\nversion = \"0.1.0\"\nauthors = [\"Eliza Weisman <eliza@elizas.website>\"]\n\n[features]\ndefault = []\nsystem_term = [\"spin\"]\nkinfo = [\"system_term\", \"log\"]\n\n[dependencies.spin]\nversion = \"0.4.6\"\noptional = true\n\n[dependencies.log]\nversion = \"0.3.6\"\ndefault-features = false\nfeatures = [\"release_max_level_info\"]\noptional = true\n"
  },
  {
    "path": "vga/src/kinfo.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2016 Eliza Weisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\n//! Macros for kernel-level logging\n\n#[macro_export]\nmacro_rules! attempt {\n    ($task:expr => dots: $dots:expr, $msg:expr ) => ({\n            use $crate::status::Status;\n            print!(\"{}{}\", $dots, $msg);\n            match $task {\n               Ok(result) => {\n                    $crate::CONSOLE.lock()\n                        .okay()\n                        .expect(\"Could not write to VGA buffer! Something's \\\n                                 really wrong!\");\n                    info!(\"{} [ OKAY ]\", $msg);\n                    result\n                }\n              , Err(why) => {\n                    $crate::CONSOLE.lock()\n                        .fail()\n                        .expect(\"Could not write to VGA buffer! Something's \\\n                                 really wrong!\");\n                    panic!(\"{:?}\", why);\n              }\n        }\n    });\n    ($task:expr => dots: $dots:expr, $($msg:tt)* ) => {\n        attempt!($task => dots: $dots, format_args!($($msg)*))\n    };\n\n}\n#[macro_export]\nmacro_rules! kinfo {\n    ( dots: $dots:expr, target: $target:expr, \"[ OKAY ]\") => {\n        // {\n        //     use core::fmt::Write;\n        //\n        //     // suppress warnings because we don't care if there's no serial port\n        //     let _ = write!( $crate::arch::drivers::serial::COM1.lock()\n        //                   , \"[info] {}: {} {}\"\n        //                   , module_path!()\n        //                   , $msg, $status);\n            print!(\"{:<38}{:>40}\", concat!($dots, $target));\n            {\n                use $crate::status::Status;\n                $crate::CONSOLE.lock().okay()\n                    .expect(\"Could not write to VGA buffer! Something's \\\n                             really wrong!\");\n            }\n            info!(target: $target, $status);\n        // }\n    };\n    ( dots: $dots:expr, target: $target:expr, \"[ FAIL ]\") => {\n        // {\n        //     use core::fmt::Write;\n        //\n        //     // suppress warnings because we don't care if there's no serial port\n        //     let _ = write!( $crate::arch::drivers::serial::COM1.lock()\n        //                   , \"[info] {}: {} {}\"\n        //                   , module_path!()\n        //                   , $msg, $status);\n            print!(\"{:<38}{:>40}\", concat!($dots, $target));\n            {\n                use $crate::status::Status;\n                $crate::CONSOLE.lock().fail()\n                    .expect(\"Could not write to VGA buffer! Something's \\\n                             really wrong!\");\n            }\n            info!(target: $target, $status);\n        // }\n    };\n    ( dots: $dots:expr, $($args:tt)* ) => {\n        // {\n        //     use core::fmt::Write;\n        //\n        //     // suppress warnings because we don't care if there's no serial port\n        //     let _ = write!( $crate::arch::drivers::serial::COM1.lock()\n        //                   , \"[info] {}: {}\"\n        //                   , module_path!()\n        //                   , format_args!($($args)*));\n            print!(\"{}{}\", $dots, format_args!($($args)*));\n            info!( ($args)* );\n        // }\n    };\n    ( $($args:tt)* ) => {\n    //     {\n    //         use core::fmt::Write;\n    //\n    //         // suppress warnings because we don't care if there's no serial port\n    //         let _ = write!( $crate::arch::drivers::serial::COM1.lock()\n    //                       , \"[info] {}: {}\"\n    //                       , module_path!()\n    //                       , format_args!($($args)*));\n            print!( $($args)* );\n            info!( $($args)* );\n        // }\n    };\n}\n#[macro_export]\nmacro_rules! kinfoln {\n    ( dots: $dots:expr, target: $target:expr, $status:expr ) => {\n        // {\n        //     use core::fmt::Write;\n        //\n        //     // suppress warnings because we don't care if there's no serial port\n        //     let _ = write!( $crate::arch::drivers::serial::COM1.lock()\n        //                   , \"[info] {}: {} {}\"\n        //                   , module_path!()\n        //                   , $msg, $status);\n            println!(\"{:<39}{:>40}\", concat!($dots, $target), $status );\n            info!(target: $target, $status);\n        // }\n    };\n    ( dots: $dots:expr, $($args:tt)* ) => {\n        // {\n        //     use core::fmt::Write;\n        //\n        //     // suppress warnings because we don't care if there's no serial port\n        //     let _ = write!( $crate::arch::drivers::serial::COM1.lock()\n        //                   , \"[info] {}: {}\"\n        //                   , module_path!()\n        //                   , format_args!($($args)*));\n            println!(\"{}{}\", $dots, format_args!($($args)*));\n            info!( $($args)* );\n        // }\n    };\n    ( $($args:tt)* ) => {\n    //     {\n    //         use core::fmt::Write;\n    //\n    //         // suppress warnings because we don't care if there's no serial port\n    //         let _ = write!( $crate::arch::drivers::serial::COM1.lock()\n    //                       , \"[info] {}: {}\"\n    //                       , module_path!()\n    //                       , format_args!($($args)*));\n            println!( $($args)* );\n            info!( $($args)* );\n        // }\n    };\n}\n"
  },
  {
    "path": "vga/src/lib.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza Weisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\n//! # SOS VGA\n//! Code for interacting with the system's VGA buffer.\n//!\n//! # Features\n//! This crate exposes the following feature flags:\n//! + `system_term`: Use the VGA buffer as the system terminal. This provides\n//!   implementations of the `print!` and `println!` macros.\n//! + `log`: provides a `log!` macro for kernel log messages.\n#![crate_name = \"vga\"]\n#![crate_type = \"lib\"]\n#![feature( slice_patterns\n          , unique )]\n#![feature(ptr_internals)]\n#![feature( const_fn\n          , const_unique_new )]\n#![cfg_attr(feature = \"system_term\", feature(lang_items))]\n#![cfg_attr(feature = \"clippy\", feature(plugin))]\n#![cfg_attr(feature = \"clippy\", plugin(clippy))]\n#![no_std]\n\n#[cfg(feature = \"system_term\")]\nextern crate spin;\n\n\n\nuse core::{mem, ptr};\nuse core::fmt::{Write, Result};\n// use core::ptr::Unique;\n\n#[cfg(feature = \"system_term\")]\nuse spin::Mutex;\n#[cfg(feature = \"kinfo\")]\n#[macro_use] extern crate log;\n\n#[cfg(all( feature = \"system_term\"\n          , not(test)))]\npub mod panic;\n\n/// Macro for printing to the standard output.\n///\n/// Equivalent to the `println!` macro except that a newline is not printed at\n/// the end of the message.\n///\n/// # Panics\n///\n/// Panics if writing to the VGA console fails.\n///\n#[cfg(feature = \"system_term\")]\n#[macro_export]\nmacro_rules! println {\n    ($fmt:expr) => (print!(concat!($fmt, \"\\n\")));\n    ($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, \"\\n\"), $($arg)*));\n}\n\n/// Macro for printing to the standard output.\n///\n/// Equivalent to the `println!` macro except that a newline is not printed at\n/// the end of the message.\n///\n/// # Panics\n///\n/// Panics if writing to the VGA console fails.\n#[cfg(feature = \"system_term\")]\n#[macro_export]\nmacro_rules! print {\n    ($($arg:tt)*) => ({\n            use core::fmt::Write;\n            $crate::CONSOLE.lock()\n                           .write_fmt(format_args!($($arg)*))\n                           .unwrap();\n    });\n}\n\n\n#[cfg(feature = \"kinfo\")]\n#[macro_use] pub mod kinfo;\npub mod status;\n\n\n/// The system's global VGA terminal\n/// TODO: should this live in the kernel instead?\n#[cfg(feature = \"system_term\")]\npub static CONSOLE: Mutex<Terminal>\n    = Mutex::new(unsafe { Terminal::new(\n         Palette::new(Color::LightGrey, Color::Black )\n       , 0xB8000\n    )});\n\n\n\n// TODO: support varying VGA screen sizes?\npub const X_MAX: usize = 80;\npub const Y_MAX: usize = 25;\n\n/// The type signature fot the actual VGA buffer\npub type Buffer = [[Char; X_MAX]; Y_MAX];\n\nconst ANSI_ESCAPE: &'static str = \"\\x1b\";\nconst FG_MASK: u8 = 0b0000_1111;\nconst BG_MASK: u8 = 0b1111_0000;\n\n/// VGA color codes\n#[derive(Eq, PartialEq, Ord, PartialOrd, Copy, Clone)]\n#[repr(u8)]\npub enum Color { Black = 0\n               , Blue = 1\n               , Green = 2\n               , Cyan = 3\n               , Red = 4\n               , Magenta = 5\n               , Brown = 6\n               , LightGrey = 7\n               , DarkGrey = 8\n               , LightBlue = 9\n               , LightGreen = 10\n               , LightCyan = 11\n               , LightRed = 12\n               , LightMagenta = 13\n               , Yellow = 14\n               , White = 15\n               }\n\n#[derive(Eq, PartialEq, Ord, PartialOrd, Copy, Clone)]\npub struct Palette(u8);\n\nimpl Palette {\n    /// Returns a `Palette` with the given foreground and background color.\n    pub const fn new(fg: Color, bg: Color) -> Self {\n        Palette( (bg as u8) << 4 | (fg as u8) )\n    }\n\n    /// Returns a new `Palette` with this palette's background color, and\n    /// the specified foreground color.\n    pub fn set_foreground(&self, fg: Color) -> Self {\n        Palette( ( self.0 & BG_MASK) | (fg as u8 & FG_MASK) )\n    }\n\n    /// Returns a new `Palette` with this palette's foreground color, and\n    /// the specified background color.\n    pub fn set_background(&self, bg: Color) -> Self {\n        Palette( ( (bg as u8) << 4 & BG_MASK) | (self.0 & FG_MASK) )\n    }\n\n    /// Returns this `Palette`'s foreground color.\n    pub fn foreground(&self) -> Color {\n        unsafe { mem::transmute(self.0 & FG_MASK) }\n    }\n\n    /// Returns this `Palette`'s background color.\n    pub fn background(&self) -> Color {\n        unsafe { mem::transmute((self.0 & BG_MASK) >> 4) }\n    }\n\n}\n/// A colored VGA character.\n#[derive(Copy, Clone)]\n#[repr(C)]\npub struct Char { pub ascii: u8\n                , pub colors: Palette\n                }\n\nimpl Char {\n    #[inline(always)]\n    pub const fn empty() -> Self {\n        Char { ascii: 0, colors: Palette(0) }\n    }\n}\n\npub struct Terminal { buffer: ptr::Unique<Buffer>\n                    , x: usize\n                    , y: usize\n                    , colors: Palette\n                    }\nimpl Terminal {\n\n    #[inline]\n    pub fn x_position(&self) -> usize {\n        self.x\n    }\n\n    /// Constructs a new `Terminal` for abuffer starting at the given address.\n    ///\n    /// # Arguments\n    /// + `colors`: the default color palette for the terminal\n    /// + `buffer_start`: the address of the to the memory location where\n    ///                   the terminal's VGA buffer begins\n    ///\n    /// # Unsafe due to:\n    /// + Casting a raw address to an array\n    /// + Constructing a `ptr::Unique` from an unchecked mut pointer.\n    pub const unsafe fn new( colors: Palette\n                           , buffer_start: usize)\n                            -> Terminal {\n        Terminal { x: 0, y: 0\n                 , colors\n                    // TODO: this probably shouldn't be unchecked, but this\n                    //  can't be a const fn otherwise...\n                 , buffer: ptr::Unique::new_unchecked(buffer_start as *mut _)\n                 }\n    }\n\n    #[inline]\n    fn buffer(&mut self) -> &mut  Buffer {\n        unsafe { self.buffer.as_mut() }\n    }\n\n    /// Set the color palette used for writing subsequent characters.\n    pub fn set_colors(&mut self, bg: Color, fg: Color) -> &mut Self {\n        self.colors = Palette::new(bg,fg);\n        self\n    }\n\n    /// Scrolls the terminal one row.\n    fn scroll(&mut self) {\n        // // construct an iterator over the whole buffer\n        // let mut rows = self.buffer()\n        //                    .iter_mut();\n        //\n        // // the current row in the buffer\n        // let mut current = rows.next()\n        //                    .unwrap();\n        //\n        // while let Some(next) = rows.next() {\n        //     // while there are rows remaining in the iterator, swap the\n        //     // next row with the current one (moving it back by one)\n        //     mem::swap(current, next);\n        //     // and advance our pointer to the current row.\n        //     current = next;\n        // }\n        let buffer: &mut _ = self.buffer();\n        for row in 1..Y_MAX {\n            for col in 0 .. X_MAX {\n                unsafe {\n                    let last = ptr::read_volatile(&buffer[row][col]);\n                    ptr::write_volatile( &mut buffer[row - 1][col], last);\n                }\n            }\n        }\n        // empty the last line in the buffer\n        unsafe {\n            for col in 0..X_MAX {\n                ptr::write_volatile(&mut buffer[Y_MAX - 1][col], Char::empty());\n            }\n        }\n    }\n\n    /// Clear the terminal\n    #[inline]\n    pub fn clear(&mut self) -> &mut Self {\n        // to clear the terminal, we just zero out the whole buffer.\n        {\n            let buffer: &mut _ =self.buffer();\n            for row in 0..Y_MAX {\n                for col in 0 .. X_MAX {\n                    unsafe {\n                        ptr::write_volatile(\n                            &mut buffer[row][col], Char::empty()\n                        );\n                    }\n                }\n            }\n        }\n\n        self.x = 0;\n        self.y = 0;\n        self\n    }\n\n    /// Write the given byte to the terminal, and advance the cursor position.\n    pub fn write_byte(&mut self, byte: u8) -> &mut Self {\n        if byte == b'\\n' {\n            // if the byte is a newline, we just advance to the next line\n            // and reset the column position.\n            self.x = 0;\n            self.y += 1;\n        } else {\n            // otherwise, it's a regular character, so we just set the\n            // byte at the current position in the buffer to that\n            // character (with the current color palette)\n            //\n            let y = self.y;\n            let x = self.x;\n            unsafe {\n                ptr::write_volatile( &mut (self.buffer()[y][x])\n                                   , Char { ascii: byte, colors: self.colors }\n                                   );\n            }\n            // and advance our column position by one\n            self.x += 1;\n\n            if self.x >= X_MAX {\n                // if we've reached the end of the line, advance to the next\n                self.x = 0;\n                self.y += 1;\n            }\n        }\n        if self.y >= Y_MAX {\n            // if we've reached the bottom of the terminal, scroll.\n            self.scroll();\n            self.y -= 1;\n        }\n        self\n    }\n\n    fn handle_ansi_escape(&self, escape_code: &str) -> Result {\n        match escape_code.as_bytes() {\n            // `\\x1b[3Nm` sets the foreground color to N.\n            &[0x1b, b'[', b'3', n, b'm'] => {\n                unsafe { self.colors\n                             .set_foreground(mem::transmute(n - 48)); }\n                Ok(())\n            }\n            // `\\x1b[4Nm` sets the background color to N\n          , &[0x1b, b'[', b'4', n, b'm'] => {\n                unsafe { self.colors\n                             .set_background(mem::transmute(n - 48)); }\n                Ok(())\n            }\n          , _ => unimplemented!()\n        }\n        // let escape_seq: &str = bytes.take_while(|b| b != b'm')\n        //                       .collect::<&str>();\n        // match escape_seq {\n        //     [b'3', n] => unsafe {\n        //         self.colors.set_foreground(mem::transmute(n - 48))\n        //     }\n        // }\n        // while let Some(byte) = bytes.next() {\n        //     match *byte {\n        //         // we've recieved an ANSI escape sequence.\n        //         // this basically enters a mediocre FSM for matching ANSI\n        //         // control codes.\n        //         0x1b => match *next_ansi_byte!(bytes) {\n        //             // handle multi-char ANSI escapes\n        //             b'[' => match *next_ansi_byte!(bytes) {\n        //                 // foreground color code\n        //                 fg @ 30 ... 37 => {\n        //                     if !(*next_ansi_byte!(bytes) == b'm') {\n        //                         unsafe {\n        //                             let color: vga::Color\n        //                                 = mem::transmute(fg - 30);\n        //                             self.colors\n        //                                 .set_foreground(color);\n        //                         }\n        //\n        //                     }\n        //                 }\n        //                 // background color code\n        //               , 40 ... 47 => {\n        //\n        //                 }\n        //               , _ => unimplemented!()\n        //             }\n        //           , _    => unimplemented!()\n        //         }\n        //         // otherwise, treat the byte as a normal ASCII char\n        //       , b => { self.write_byte(b); }\n        //     }\n        // }\n\n    }\n\n}\n\nstruct AnsiEscapeIter<'a> { curr_slice: &'a str\n                          , in_escape: bool\n                          }\n\nimpl<'a> AnsiEscapeIter<'a> {\n\n    pub fn new(s: &'a str) -> Self {\n        AnsiEscapeIter { curr_slice: s\n                       , in_escape: false\n                       }\n    }\n}\n\nimpl<'a> Iterator for AnsiEscapeIter<'a> {\n    type Item = &'a str;\n\n    fn next(&mut self) -> Option<Self::Item> {\n        if self.curr_slice.len() == 0 {\n            // if the remaining string is empty, we just return `None`\n            None\n        } else {\n            // otherwise, find the next index to chunk on.\n            let maybe_idx\n                = if self.in_escape {\n                     // if we're in an escape code, we split the chunk at the\n                     // index of the next 'm' character, adding 1 so that the\n                     // 'm' is in the escape code chunk.\n                    self.curr_slice.find('m')\n                        .map(|idx| idx + 1)\n                } else {\n                    // otherwise, split at the next ANSI escape sequence\n                    self.curr_slice.find(ANSI_ESCAPE)\n                };\n\n            // if we found another index to chunk on, map over that index;\n            // otherwise, we just yield the rest of the string\n            maybe_idx.map_or(\n                Some(self.curr_slice) // remainder (if no index to chunk on)\n              , |idx| { // otherwise, chunk along that index...\n                    let (chunk, next_slice) = self.curr_slice\n                                                  .split_at(idx);\n                    self.curr_slice = next_slice; // update current chunk\n                    Some(chunk)                   // return the chunk\n                })\n        }\n\n\n    }\n}\n\nimpl Write for Terminal {\n\n    fn write_str(&mut self, s: &str) -> Result {\n\n        if s.contains(ANSI_ESCAPE) {\n            // if the segment contains an ANSI escape, construct an iterator\n            // over each chunk containing either an escape sequence or text\n            for segment in AnsiEscapeIter::new(s) {\n                if segment.starts_with(ANSI_ESCAPE) {\n                    // if the current segment is an ANSI escape code,\n                    // try to handle the escape and fail if it is malformed\n                    self.handle_ansi_escape(segment)?\n                } else {\n                    // otherwise, just write each chunk in the string.\n                    for byte in segment.as_bytes() {\n                        self.write_byte(*byte);\n                    }\n                }\n            }\n        } else {\n            // otherwise, if there are no ANSI escape codes,\n            // we can just write each byte in the string.\n            for byte in s.as_bytes() {\n                self.write_byte(*byte);\n            }\n        }\n        Ok(())\n    }\n\n}\n"
  },
  {
    "path": "vga/src/panic.rs",
    "content": "//\n//  SOS: the Stupid Operating System\n//  by Eliza Weisman (eliza@elizas.website)\n//\n//  Copyright (c) 2015-2017 Eliza Weisman\n//  Released under the terms of the MIT license. See `LICENSE` in the root\n//  directory of this repository for more information.\n//\n//! Panic handling.\n//!\n//! This module contains the `panic_fmt` language item. This function handles\n//! panics at runtime.\n\nuse core::fmt::{Arguments, Write};\nuse super::{Color, CONSOLE};\n\n/// Called to handle a panic.\n///\n/// Since kernel panics are non-recoverable, this function prints out\n/// the error message and hangs forever.\n///\n/// Eventually – way in the future – when we have disk I/O and stuff,\n/// we'll probably want to write out some core dumps here as well.\n#[lang = \"panic_fmt\"]\n#[no_mangle] #[inline(never)] #[cold]\npub extern \"C\" fn rust_begin_unwind( args: Arguments\n                                   , file: &'static str\n                                   , line: usize )\n                                   -> ! {\n    let _ = write!( CONSOLE.lock()\n                        .set_colors(Color::White, Color::Red)\n                  , \"Something has gone horribly wrong in {} at line {}. \\\n                    \\n{}\\n\\\n                    This is fine.\"\n                  , file, line, args\n                  );\n    error!(target: file, \"{}\", args);\n    loop { }\n}\n"
  },
  {
    "path": "vga/src/status.rs",
    "content": "use super::{Terminal, Color};\nuse core::fmt::{Result, Write};\n\npub trait Status {\n    fn okay(&mut self) -> Result ;\n    fn fail(&mut self) -> Result ;\n}\n\nimpl Status for Terminal {\n    fn okay(&mut self) -> Result {\n        while self.x_position() < 71 { self.write_byte(b' '); }\n        self.write_str(\"[ \")?;\n        self.set_colors(Color::Green, Color::Black, );\n        self.write_str(\"OKAY\")?;\n        self.set_colors(Color::LightGrey, Color::Black);\n        self.write_str(\" ]\\n\")?;\n        Ok(())\n    }\n    fn fail(&mut self) -> Result {\n        while self.x_position() < 71 { self.write_byte(b' '); }\n        self.write_str(\"[ \")?;\n        self.set_colors(Color::Red, Color::Black);\n        self.write_str(\"FAIL\")?;\n        self.set_colors(Color::LightGrey, Color::Black);\n        self.write_str(\" ]\\n\")?;\n        Ok(())\n    }\n}\n"
  }
]