Repository: ashleygwilliams/x86-kernel
Branch: master
Commit: e4f53e367f63
Files: 12
Total size: 12.6 KB
Directory structure:
gitextract_bzkp4t38/
├── .gitignore
├── Cargo.toml
├── LICENSE
├── Makefile
├── README.md
├── Vagrantfile
└── src/
├── arch/
│ └── x86_64/
│ ├── boot.asm
│ ├── grub.cfg
│ ├── linker.ld
│ ├── long_mode_init.asm
│ └── multiboot_header.asm
└── lib.rs
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
multiboot_header
boot
*.o
*.bin
*.iso
.vagrant
target
================================================
FILE: Cargo.toml
================================================
[package]
name = "my_os"
version = "1.0.0"
authors = ["ag_dubs"]
[lib]
crate-type = ["staticlib"]
[dependencies]
rlibc = "0.1.4"
================================================
FILE: LICENSE
================================================
The MIT License (MIT)
Copyright (c) 2015 ashley williams
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: Makefile
================================================
arch ?= x86_64
kernel := build/kernel-$(arch).bin
iso := build/os-$(arch).iso
target ?= $(arch)-unknown-linux-gnu
rust_os := target/$(target)/debug/libmy_os.a
linker_script := src/arch/$(arch)/linker.ld
grub_cfg := src/arch/$(arch)/grub.cfg
assembly_source_files := $(wildcard src/arch/$(arch)/*.asm)
assembly_object_files := $(patsubst src/arch/$(arch)/%.asm, \
build/arch/$(arch)/%.o, $(assembly_source_files))
.PHONY: all clean run iso
all: $(kernel)
clean:
@rm -r build
run: $(iso)
@qemu-system-x86_64 -hda $(iso)
iso: $(iso)
$(iso): $(kernel) $(grub_cfg)
@mkdir -p build/isofiles/boot/grub
@cp $(kernel) build/isofiles/boot/kernel.bin
@cp $(grub_cfg) build/isofiles/boot/grub
@grub-mkrescue -o $(iso) build/isofiles 2> /dev/null
@rm -r build/isofiles
$(kernel): cargo $(rust_os) $(assembly_object_files) $(linker_script)
@ld -n --gc-sections -T $(linker_script) -o $(kernel) $(assembly_object_files) $(rust_os)
cargo:
@cargo rustc --target $(target) -- -Z no-landing-pads
build/arch/$(arch)/%.o: src/arch/$(arch)/%.asm
@mkdir -p $(shell dirname $@)
@nasm -felf64 $< -o $@
================================================
FILE: README.md
================================================
# x86 kernel
> a simple x86 kernel, extended with Rust
this is my work following along with a [@phil-opp][2]'s blog post series ["A minimal x86 kernel"][1]
## prerequisites
### virtualization
> (if you are on OSX, ChromeOS, Windows, etc)
- [Vagrant]: development environment manager
- [VirtualBox]: virtualizer
- [XQuartz]: X11 Graphics
### linux dependencies
- `nasm`: assembler (assembly -> binary)
- `ld`: linker (makes binary out of other files)
- `grub`: creates the bootable iso
- `xorriso`: req'd by grub, filesystem manipulator
- `QEMU`: fake-computer emulator
### utilities
you don't need these, but they are nice for viewing
generated code.
- `hexdump`: allows you to view generated binary
- `objdump`: a nicer viewer for .o files
## up and running
1. fork and clone this repository
2. navigate into the repo directory: `cd x86-kernel`
3. `$ vagrant up`
4. `$ vagrant ssh -- -Y`
`-- -Y` forwards graphics
5. `$ multirust default nightly-2015-11-19`
Sets your default rust to a stable nightly.
The features needed to do OS work in Rust are
not yet in a stable release, so you must use
a nightly build.
6. `$ cd /vagrant`
The `/vagrant` directory is the virtualized directory
that is synced with the `/` directory on your HD.
7. `$ make run`
[Vagrant]: https://www.vagrantup.com/
[VirtualBox]: https://www.virtualbox.org/
[XQuartz]: http://www.xquartz.org/
[1]: http://blog.phil-opp.com/rust-os/multiboot-kernel.html
[2]: https://github.com/phil-opp
================================================
FILE: Vagrantfile
================================================
# -*- mode: ruby -*-
# vi: set ft=ruby :
# All Vagrant configuration is done below. The "2" in Vagrant.configure
# configures the configuration version (we support older styles for
# backwards compatibility). Please don't change it unless you know what
# you're doing.
Vagrant.configure(2) do |config|
# The most common configuration options are documented and commented below.
# For a complete reference, please see the online documentation at
# https://docs.vagrantup.com.
# Every Vagrant development environment requires a box. You can search for
# boxes at https://atlas.hashicorp.com/search.
config.vm.box = "debian/jessie64"
# Disable automatic box update checking. If you disable this, then
# boxes will only be checked for updates when the user runs
# `vagrant box outdated`. This is not recommended.
# config.vm.box_check_update = false
# Create a forwarded port mapping which allows access to a specific port
# within the machine from a port on the host machine. In the example below,
# accessing "localhost:8080" will access port 80 on the guest machine.
# config.vm.network "forwarded_port", guest: 80, host: 8080
# Create a private network, which allows host-only access to the machine
# using a specific IP.
# config.vm.network "private_network", ip: "192.168.33.10"
# Create a public network, which generally matched to bridged network.
# Bridged networks make the machine appear as another physical device on
# your network.
# config.vm.network "public_network"
# Share an additional folder to the guest VM. The first argument is
# the path on the host to the actual folder. The second argument is
# the path on the guest to mount the folder. And the optional third
# argument is a set of non-required options.
# config.vm.synced_folder "../data", "/vagrant_data"
# Provider-specific configuration so you can fine-tune various
# backing providers for Vagrant. These expose provider-specific options.
# Example for VirtualBox:
#
# config.vm.provider "virtualbox" do |vb|
# # Display the VirtualBox GUI when booting the machine
# vb.gui = true
#
# # Customize the amount of memory on the VM:
# vb.memory = "1024"
# end
#
# View the documentation for the provider you are using for more
# information on available options.
# Define a Vagrant Push strategy for pushing to Atlas. Other push strategies
# such as FTP and Heroku are also available. See the documentation at
# https://docs.vagrantup.com/v2/push/atlas.html for more information.
# config.push.define "atlas" do |push|
# push.app = "YOUR_ATLAS_USERNAME/YOUR_APPLICATION_NAME"
# end
# Enable provisioning with a shell script. Additional provisioners such as
# Puppet, Chef, Ansible, Salt, and Docker are also available. Please see the
# documentation for more information about their specific syntax and use.
config.vm.provision "shell", inline: <<-SHELL
sudo apt-get update
sudo apt-get install nasm -y
sudo apt-get install xorriso -y
sudo apt-get install git -y
sudo apt-get install vim -y
sudo apt-get install -y qemu
curl -sf https://raw.githubusercontent.com/brson/multirust/master/blastoff.sh | sh -s -- --yes
multirust default nightly-2015-11-19
SHELL
config.ssh.forward_x11 = true
end
================================================
FILE: src/arch/x86_64/boot.asm
================================================
global start
extern long_mode_start
section .text
bits 32
start:
mov esp, stack_top
; tests
call test_multiboot
call test_cpuid
call test_long_mode
; paging
call setup_page_tables
call enable_paging
lgdt [gdt64.pointer]
; update selectors
mov ax, gdt64.data
mov ss, ax ; stack selector
mov ds, ax ; data selector
mov es, ax ; extra selector
jmp gdt64.code:long_mode_start ; "trampoline"
hlt
; prints `ERR: ` + error code
; parameter: error code (in ascii) in al
error:
mov dword [0xb8000], 0x4f524f45
mov dword [0xb8004], 0x4f3a4f52
mov dword [0xb8008], 0xff204f20
mov byte [0xb800a], al
hlt
test_multiboot:
cmp eax, 0x36d76289
jne .no_multiboot
ret
.no_multiboot:
mov al, "0"
jmp error
test_cpuid:
pushfd ; Store the FLAGS-register.
pop eax ; Restore the A-register.
mov ecx, eax ; Set the C-register to the A-register.
xor eax, 1 << 21 ; Flip the ID-bit, which is bit 21.
push eax ; Store the A-register.
popfd ; Restore the FLAGS-register.
pushfd ; Store the FLAGS-register.
pop eax ; Restore the A-register.
push ecx ; Store the C-register.
popfd ; Restore the FLAGS-register.
xor eax, ecx ; Do a XOR-operation on the A-register and the C-register.
jz .no_cpuid ; The zero flag is set, no CPUID.
ret ; CPUID is available for use.
.no_cpuid:
mov al, "1"
jmp error
test_long_mode:
mov eax, 0x80000000 ; Set the A-register to 0x80000000.
cpuid ; CPU identification.
cmp eax, 0x80000001 ; Compare the A-register with 0x80000001.
jb .no_long_mode ; It is less, there is no long mode.
mov eax, 0x80000001 ; Set the A-register to 0x80000001.
cpuid ; CPU identification.
test edx, 1 << 29 ; Test if the LM-bit, which is bit 29, is set in the D-register.
jz .no_long_mode ; They aren't, there is no long mode.
ret
.no_long_mode:
mov al, "2"
jmp error
setup_page_tables:
; map p4 to p3
mov eax, p3_table
or eax, 0b11
mov [p4_table], eax
; map p3 to p2
mov eax, p2_table
or eax, 0b11
mov [p3_table], eax
mov ecx, 0
.map_p2_table:
mov eax, 0x200000
mul ecx
or eax, 0b10000011
mov [p2_table + ecx * 8], eax
; for loop, increment, compare(=512)
inc ecx
cmp ecx, 512
jne .map_p2_table
ret
enable_paging:
; load P4 to cr3 register (cpu uses this to access the P4 table)
mov eax, p4_table
mov cr3, eax
; enable PAE-flag in cr4 (Physical Address Extension)
mov eax, cr4
or eax, 1 << 5
mov cr4, eax
; set the long mode bit in the EFER MSR (model specific register)
mov ecx, 0xC0000080
rdmsr
or eax, 1 << 8
wrmsr
; enable paging in the cr0 register
mov eax, cr0
or eax, 1 << 31
mov cr0, eax
ret
section .bss
align 4096
p4_table:
resb 4096
p3_table:
resb 4096
p2_table:
resb 4096
stack_bottom:
resb 64
stack_top:
section .rodata
gdt64:
dq 0 ; zero entry
.code: equ $ - gdt64
dq (1<<44) | (1<<47) | (1<<41) | (1<<43) | (1<<53) ; code segment
.data: equ $ - gdt64
dq (1<<44) | (1<<47) | (1<<41) ; data segment
.pointer:
dw $ - gdt64 - 1
dq gdt64
================================================
FILE: src/arch/x86_64/grub.cfg
================================================
set timeout=0
set default=0
menuentry "my os" {
multiboot2 /boot/kernel.bin
boot
}
================================================
FILE: src/arch/x86_64/linker.ld
================================================
ENTRY(start)
SECTIONS {
/* sets load address to MiB (convention) */
. = 1M;
.boot : {
/* put the header at the beginning */
KEEP(*(.multiboot_header))
}
.text : {
*(.text)
}
}
================================================
FILE: src/arch/x86_64/long_mode_init.asm
================================================
global long_mode_start
section .text
bits 64
long_mode_start:
extern rust_main
call setup_SSE
call rust_main
.os_returned:
; rust main returned, print `OS returned!`
mov rax, 0x4f724f204f534f4f
mov [0xb8000], rax
mov rax, 0x4f724f754f744f65
mov [0xb8008], rax
mov rax, 0x4f214f644f654f6e
mov [0xb8010], rax
hlt
error:
mov rbx, 0x4f4f4f524f524f45
mov [0xb8000], rbx
mov rbx, 0x4f204f204f3a4f52
mov [0xb8008], rbx
mov byte [0xb800e], al
hlt
jmp error
setup_SSE:
; check for SSE
mov rax, 0x1
cpuid
test edx, 1<<25
jz .no_SSE
; enable SSE
mov rax, cr0
and ax, 0xFFFB ; clear coprocessor emulation CR0.EM
or ax, 0x2 ; set coprocessor monitoring CR0.MP
mov cr0, rax
mov rax, cr4
or ax, 3 << 9 ; set CR4.OSFXSR and CR4.OSXMMEXCPT at the same time
mov cr4, rax
ret
.no_SSE:
mov al, "a"
jmp error
================================================
FILE: src/arch/x86_64/multiboot_header.asm
================================================
section .multiboot_header
header_start:
dd 0xe85250d6 ; magic number (multiboot 2)
dd 0 ; architecture 0 (protected mode i386)
dd header_end - header_start ; header length
; checksum (magic number + architecture + header length)
; we subtract from 0x1... to account for signedness
dd 0x100000000 - (0xe85250d6 + 0 + (header_end - header_start))
; required end tag (u16, u16, u32)
dw 0 ; type
dw 0 ; flags
dd 8 ; size
header_end:
================================================
FILE: src/lib.rs
================================================
#![feature(no_std)]
#![feature(lang_items)]
#![no_std]
extern crate rlibc;
#[no_mangle]
pub extern fn rust_main() {
let hello = b"Hello World!";
let color_byte = 0x1f;
let mut hello_colored = [color_byte; 24];
for (i, char_byte) in hello.into_iter().enumerate() {
hello_colored[i * 2] = *char_byte;
}
let buffer_ptr = (0xb8000 +1988) as *mut _;
unsafe { *buffer_ptr = hello_colored };
loop{}
}
#[lang = "eh_personality"] extern fn eh_personality() {}
#[lang = "panic_fmt"] extern fn panic_fmt() -> ! { loop{} }
gitextract_bzkp4t38/
├── .gitignore
├── Cargo.toml
├── LICENSE
├── Makefile
├── README.md
├── Vagrantfile
└── src/
├── arch/
│ └── x86_64/
│ ├── boot.asm
│ ├── grub.cfg
│ ├── linker.ld
│ ├── long_mode_init.asm
│ └── multiboot_header.asm
└── lib.rs
SYMBOL INDEX (3 symbols across 1 files)
FILE: src/lib.rs
function rust_main (line 8) | pub extern fn rust_main() {
function eh_personality (line 23) | extern fn eh_personality() {}
function panic_fmt (line 24) | extern fn panic_fmt() -> ! { loop{} }
Condensed preview — 12 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (14K chars).
[
{
"path": ".gitignore",
"chars": 54,
"preview": "multiboot_header\nboot\n*.o\n*.bin\n*.iso\n.vagrant\ntarget\n"
},
{
"path": "Cargo.toml",
"chars": 131,
"preview": "[package]\nname = \"my_os\"\nversion = \"1.0.0\"\nauthors = [\"ag_dubs\"]\n\n[lib]\ncrate-type = [\"staticlib\"]\n\n[dependencies]\nrlibc"
},
{
"path": "LICENSE",
"chars": 1083,
"preview": "The MIT License (MIT)\n\nCopyright (c) 2015 ashley williams\n\nPermission is hereby granted, free of charge, to any person o"
},
{
"path": "Makefile",
"chars": 1099,
"preview": "arch ?= x86_64\nkernel := build/kernel-$(arch).bin\niso := build/os-$(arch).iso\ntarget ?= $(arch)-unknown-linux-gnu\nrust_o"
},
{
"path": "README.md",
"chars": 1506,
"preview": "# x86 kernel\n> a simple x86 kernel, extended with Rust \n\nthis is my work following along with a [@phil-opp][2]'s blog po"
},
{
"path": "Vagrantfile",
"chars": 3340,
"preview": "# -*- mode: ruby -*-\n# vi: set ft=ruby :\n\n# All Vagrant configuration is done below. The \"2\" in Vagrant.configure\n# conf"
},
{
"path": "src/arch/x86_64/boot.asm",
"chars": 3313,
"preview": "global start\nextern long_mode_start\n\nsection .text\nbits 32\nstart:\n mov esp, stack_top \n\n ; tests\n call test_multiboot"
},
{
"path": "src/arch/x86_64/grub.cfg",
"chars": 88,
"preview": "set timeout=0\nset default=0\n\nmenuentry \"my os\" {\n multiboot2 /boot/kernel.bin\n boot\n}\n"
},
{
"path": "src/arch/x86_64/linker.ld",
"chars": 203,
"preview": "ENTRY(start)\n\nSECTIONS {\n /* sets load address to MiB (convention) */\n . = 1M;\n\n .boot : {\n /* put the header at t"
},
{
"path": "src/arch/x86_64/long_mode_init.asm",
"chars": 946,
"preview": "global long_mode_start\n\nsection .text\nbits 64\nlong_mode_start:\n extern rust_main\n call setup_SSE\n call rust_main \n\n.o"
},
{
"path": "src/arch/x86_64/multiboot_header.asm",
"chars": 569,
"preview": "section .multiboot_header\nheader_start:\n dd 0xe85250d6 ; magic number (multiboot 2)\n dd 0 "
},
{
"path": "src/lib.rs",
"chars": 538,
"preview": "#![feature(no_std)]\n#![feature(lang_items)]\n#![no_std]\n\nextern crate rlibc;\n\n#[no_mangle]\npub extern fn rust_main() {\n "
}
]
About this extraction
This page contains the full source code of the ashleygwilliams/x86-kernel GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 12 files (12.6 KB), approximately 4.2k tokens, and a symbol index with 3 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.