├── .gitignore
├── .gitlab-ci.yml
├── .gitmodules
├── .helix
├── config.toml
└── languages.toml
├── ARM-AARCH64-PORT-OUTLINE.md
├── Cargo.lock
├── Cargo.toml
├── LICENSE
├── Makefile
├── README.md
├── build.rs
├── clippy.sh
├── config.toml.example
├── linkers
├── aarch64.ld
├── i686.ld
├── riscv64.ld
└── x86_64.ld
├── res
└── unifont.font
├── rustfmt.toml
├── src
├── acpi
│ ├── gtdt.rs
│ ├── hpet.rs
│ ├── madt
│ │ ├── arch
│ │ │ ├── aarch64.rs
│ │ │ ├── other.rs
│ │ │ └── x86.rs
│ │ └── mod.rs
│ ├── mod.rs
│ ├── rsdp.rs
│ ├── rsdt.rs
│ ├── rxsdt.rs
│ ├── sdt.rs
│ ├── spcr.rs
│ └── xsdt.rs
├── allocator
│ ├── linked_list.rs
│ ├── mod.rs
│ └── slab.rs
├── arch
│ ├── aarch64
│ │ ├── consts.rs
│ │ ├── debug.rs
│ │ ├── device
│ │ │ ├── cpu
│ │ │ │ ├── mod.rs
│ │ │ │ └── registers
│ │ │ │ │ ├── control_regs.rs
│ │ │ │ │ └── mod.rs
│ │ │ ├── generic_timer.rs
│ │ │ ├── irqchip
│ │ │ │ ├── gic.rs
│ │ │ │ ├── gicv3.rs
│ │ │ │ ├── irq_bcm2835.rs
│ │ │ │ ├── irq_bcm2836.rs
│ │ │ │ ├── mod.rs
│ │ │ │ └── null.rs
│ │ │ ├── mod.rs
│ │ │ ├── rtc.rs
│ │ │ ├── serial.rs
│ │ │ └── uart_pl011.rs
│ │ ├── interrupt
│ │ │ ├── exception.rs
│ │ │ ├── handler.rs
│ │ │ ├── irq.rs
│ │ │ ├── mod.rs
│ │ │ ├── syscall.rs
│ │ │ └── trace.rs
│ │ ├── ipi.rs
│ │ ├── macros.rs
│ │ ├── misc.rs
│ │ ├── mod.rs
│ │ ├── paging
│ │ │ ├── entry.rs
│ │ │ ├── mapper.rs
│ │ │ └── mod.rs
│ │ ├── rmm.rs
│ │ ├── start.rs
│ │ ├── stop.rs
│ │ ├── time.rs
│ │ └── vectors.rs
│ ├── mod.rs
│ ├── riscv64
│ │ ├── consts.rs
│ │ ├── debug.rs
│ │ ├── device
│ │ │ ├── cpu
│ │ │ │ └── mod.rs
│ │ │ ├── irqchip
│ │ │ │ ├── clint.rs
│ │ │ │ ├── clint_sbi.rs
│ │ │ │ ├── hlic.rs
│ │ │ │ ├── mod.rs
│ │ │ │ └── plic.rs
│ │ │ ├── mod.rs
│ │ │ └── serial.rs
│ │ ├── interrupt
│ │ │ ├── exception.rs
│ │ │ ├── handler.rs
│ │ │ ├── mod.rs
│ │ │ ├── syscall.rs
│ │ │ └── trace.rs
│ │ ├── ipi.rs
│ │ ├── macros.rs
│ │ ├── misc.rs
│ │ ├── mod.rs
│ │ ├── paging
│ │ │ ├── entry.rs
│ │ │ ├── mapper.rs
│ │ │ └── mod.rs
│ │ ├── rmm.rs
│ │ ├── start.rs
│ │ ├── stop.rs
│ │ └── time.rs
│ ├── x86
│ │ ├── consts.rs
│ │ ├── gdt.rs
│ │ ├── interrupt
│ │ │ ├── exception.rs
│ │ │ ├── handler.rs
│ │ │ ├── irq.rs
│ │ │ ├── mod.rs
│ │ │ └── syscall.rs
│ │ ├── macros.rs
│ │ ├── mod.rs
│ │ ├── paging
│ │ │ ├── mapper.rs
│ │ │ └── mod.rs
│ │ ├── rmm.rs
│ │ └── start.rs
│ ├── x86_64
│ │ ├── alternative.rs
│ │ ├── consts.rs
│ │ ├── cpuid.rs
│ │ ├── gdt.rs
│ │ ├── interrupt
│ │ │ ├── exception.rs
│ │ │ ├── handler.rs
│ │ │ ├── irq.rs
│ │ │ ├── mod.rs
│ │ │ └── syscall.rs
│ │ ├── macros.rs
│ │ ├── misc.rs
│ │ ├── mod.rs
│ │ ├── paging
│ │ │ ├── mapper.rs
│ │ │ └── mod.rs
│ │ ├── rmm.rs
│ │ └── start.rs
│ └── x86_shared
│ │ ├── cpuid.rs
│ │ ├── debug.rs
│ │ ├── device
│ │ ├── cpu.rs
│ │ ├── hpet.rs
│ │ ├── ioapic.rs
│ │ ├── local_apic.rs
│ │ ├── mod.rs
│ │ ├── pic.rs
│ │ ├── pit.rs
│ │ ├── rtc.rs
│ │ ├── serial.rs
│ │ ├── system76_ec.rs
│ │ └── tsc.rs
│ │ ├── idt.rs
│ │ ├── interrupt
│ │ ├── ipi.rs
│ │ ├── mod.rs
│ │ └── trace.rs
│ │ ├── ipi.rs
│ │ ├── mod.rs
│ │ ├── pti.rs
│ │ ├── stop.rs
│ │ └── time.rs
├── asm
│ ├── x86
│ │ └── trampoline.asm
│ └── x86_64
│ │ └── trampoline.asm
├── common
│ ├── aligned_box.rs
│ ├── int_like.rs
│ ├── mod.rs
│ └── unique.rs
├── context
│ ├── arch
│ │ ├── aarch64.rs
│ │ ├── riscv64.rs
│ │ ├── x86.rs
│ │ └── x86_64.rs
│ ├── context.rs
│ ├── file.rs
│ ├── memory.rs
│ ├── mod.rs
│ ├── signal.rs
│ ├── switch.rs
│ └── timeout.rs
├── cpu_set.rs
├── cpu_stats.rs
├── debugger.rs
├── devices
│ ├── graphical_debug
│ │ ├── debug.rs
│ │ ├── display.rs
│ │ └── mod.rs
│ ├── mod.rs
│ └── uart_16550.rs
├── dtb
│ ├── irqchip.rs
│ └── mod.rs
├── elf.rs
├── event.rs
├── externs.rs
├── log.rs
├── main.rs
├── memory
│ ├── kernel_mapper.rs
│ └── mod.rs
├── panic.rs
├── percpu.rs
├── profiling.rs
├── ptrace.rs
├── scheme
│ ├── acpi.rs
│ ├── debug.rs
│ ├── dtb.rs
│ ├── event.rs
│ ├── irq.rs
│ ├── memory.rs
│ ├── mod.rs
│ ├── pipe.rs
│ ├── proc.rs
│ ├── root.rs
│ ├── serio.rs
│ ├── sys
│ │ ├── block.rs
│ │ ├── context.rs
│ │ ├── cpu.rs
│ │ ├── exe.rs
│ │ ├── fdstat.rs
│ │ ├── iostat.rs
│ │ ├── irq.rs
│ │ ├── log.rs
│ │ ├── mod.rs
│ │ ├── scheme.rs
│ │ ├── scheme_num.rs
│ │ ├── stat.rs
│ │ ├── syscall.rs
│ │ └── uname.rs
│ ├── time.rs
│ └── user.rs
├── startup
│ ├── memory.rs
│ └── mod.rs
├── sync
│ ├── mod.rs
│ ├── wait_condition.rs
│ └── wait_queue.rs
├── syscall
│ ├── debug.rs
│ ├── fs.rs
│ ├── futex.rs
│ ├── mod.rs
│ ├── privilege.rs
│ ├── process.rs
│ ├── time.rs
│ └── usercopy.rs
└── time.rs
└── targets
├── aarch64-unknown-kernel.json
├── i686-unknown-kernel.json
├── riscv64-unknown-kernel.json
└── x86_64-unknown-kernel.json
/.gitignore:
--------------------------------------------------------------------------------
1 | target
2 | /config.toml
3 | .gitlab-ci-local/
4 |
--------------------------------------------------------------------------------
/.gitlab-ci.yml:
--------------------------------------------------------------------------------
1 | image: "redoxos/redoxer:latest"
2 |
3 | variables:
4 | GIT_SUBMODULE_STRATEGY: recursive
5 |
6 | stages:
7 | - host
8 | - build
9 | - test
10 | # TODO: benchmarks and profiling (maybe manually enabled for relevant MRs)?
11 |
12 | build:
13 | stage: build
14 | script:
15 | - mkdir -p target/${ARCH}
16 | - TARGET=${ARCH}-unknown-redox redoxer env make BUILD=target/${ARCH}
17 | parallel:
18 | matrix:
19 | - ARCH: [x86_64, i686, aarch64, riscv64gc]
20 |
21 | fmt:
22 | stage: host
23 | script:
24 | - rustup component add rustfmt-preview
25 | - cargo fmt -- --check
26 |
27 | unit_test:
28 | stage: test
29 | script:
30 | - TARGET=x86_64-unknown-redox redoxer test
31 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "slab_allocator"]
2 | path = slab_allocator
3 | url = https://gitlab.redox-os.org/redox-os/slab_allocator
4 | [submodule "rmm"]
5 | path = rmm
6 | url = https://gitlab.redox-os.org/redox-os/rmm.git
7 | branch = master
8 | [submodule "redox-path"]
9 | path = redox-path
10 | url = https://gitlab.redox-os.org/redox-os/redox-path.git
11 | branch = main
12 |
--------------------------------------------------------------------------------
/.helix/config.toml:
--------------------------------------------------------------------------------
1 | [editor]
2 | auto-format = false
3 |
--------------------------------------------------------------------------------
/.helix/languages.toml:
--------------------------------------------------------------------------------
1 | [[language]]
2 | name = "rust"
3 |
4 | [[language-server.rust-analyzer.config.cargo]]
5 | extraEnv = ["RUST_TARGET_PATH=targets"]
6 | # Select one of targets to make lsp work for your confguration
7 | # Do not commit this change
8 | # TODO: find a better way to do this
9 | # target = "aarch64-unknown-kernel"
10 |
11 | [[language-server.rust-analyzer.config.check]]
12 | targets = ["x86_64-unknown-kernel", "i686-unknown-kernel", "aarch64-unknown-kernel"]
13 |
14 |
--------------------------------------------------------------------------------
/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "kernel"
3 | version = "0.5.12"
4 | build = "build.rs"
5 | edition = "2021"
6 |
7 | [build-dependencies]
8 | cc = "1.0"
9 | rustc-cfg = "0.5"
10 | toml = "0.8"
11 |
12 | [dependencies]
13 | bitflags = "2"
14 | bitfield = "0.13.2"
15 | hashbrown = { version = "0.14.3", default-features = false, features = ["ahash", "inline-more"] }
16 | linked_list_allocator = "0.9.0"
17 | log = "0.4"
18 | redox-path = "0.2.0"
19 | redox_syscall = { git = "https://gitlab.redox-os.org/redox-os/syscall.git", branch = "master", default-features = false }
20 | slab_allocator = { path = "slab_allocator", optional = true }
21 | spin = "0.9.8"
22 | spinning_top = { version = "0.3", features = ["arc_lock"] }
23 | rmm = { path = "rmm", default-features = false }
24 | arrayvec = { version = "0.7.4", default-features = false }
25 | slab = { version = "0.4", default-features = false }
26 | # TODO: Remove
27 | indexmap = { version = "2.5.0", default-features = false }
28 |
29 | [dependencies.goblin]
30 | version = "0.2.1"
31 | default-features = false
32 | features = ["elf32", "elf64"]
33 |
34 | [dependencies.rustc-demangle]
35 | version = "0.1.16"
36 | default-features = false
37 |
38 | [target.'cfg(any(target_arch = "aarch64", target_arch = "riscv64"))'.dependencies]
39 | byteorder = { version = "1", default-features = false }
40 | fdt = { git = "https://github.com/repnop/fdt.git", rev = "2fb1409edd1877c714a0aa36b6a7c5351004be54" }
41 |
42 | [target.'cfg(any(target_arch = "x86", target_arch = "x86_64"))'.dependencies]
43 | raw-cpuid = "10.2.0"
44 | x86 = { version = "0.47.0", default-features = false }
45 |
46 | [target.'cfg(any(target_arch = "riscv64", target_arch = "riscv32"))'.dependencies]
47 | sbi-rt = "0.0.3"
48 |
49 | [features]
50 | default = [
51 | "acpi",
52 | #TODO: issues with Alder Lake and newer CPUs: "multi_core",
53 | "graphical_debug",
54 | "serial_debug",
55 | "self_modifying",
56 | "x86_kvm_pv",
57 | ]
58 |
59 | # Activates some limited code-overwriting optimizations, based on CPU features.
60 | self_modifying = []
61 |
62 | acpi = []
63 | graphical_debug = []
64 | lpss_debug = []
65 | multi_core = ["acpi"]
66 | profiling = []
67 | #TODO: remove when threading issues are fixed
68 | pti = []
69 | qemu_debug = []
70 | serial_debug = []
71 | system76_ec_debug = []
72 | slab = ["slab_allocator"]
73 | sys_stat = []
74 | x86_kvm_pv = []
75 |
76 | debugger = ["syscall_debug"]
77 | syscall_debug = []
78 |
79 | sys_fdstat = []
80 |
81 | [profile.dev]
82 | # Avoids having to define the eh_personality lang item and reduces kernel size
83 | panic = "abort"
84 |
85 | [profile.release]
86 | # Avoids having to define the eh_personality lang item and reduces kernel size
87 | panic = "abort"
88 |
89 | lto = true
90 |
91 | debug = "full"
92 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Jeremy Soller
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | SOURCE:=$(dir $(realpath $(lastword $(MAKEFILE_LIST))))
2 | BUILD?=$(CURDIR)
3 | export RUST_TARGET_PATH=$(SOURCE)/targets
4 |
5 | ifeq ($(TARGET),)
6 | ARCH?=$(shell uname -m)
7 | else
8 | ARCH?=$(shell echo "$(TARGET)" | cut -d - -f1)
9 | endif
10 |
11 | ifeq ($(ARCH),riscv64gc)
12 | override ARCH:=riscv64
13 | endif
14 | GNU_TARGET=$(ARCH)-unknown-redox
15 |
16 |
17 | all: $(BUILD)/kernel $(BUILD)/kernel.sym
18 |
19 | LD_SCRIPT=$(SOURCE)/linkers/$(ARCH).ld
20 | TARGET_SPEC=$(RUST_TARGET_PATH)/$(ARCH)-unknown-kernel.json
21 |
22 | $(BUILD)/kernel.all: $(LD_SCRIPT) $(TARGET_SPEC) $(shell find $(SOURCE) -name "*.rs" -type f)
23 | cargo rustc \
24 | --bin kernel \
25 | --manifest-path "$(SOURCE)/Cargo.toml" \
26 | --target "$(TARGET_SPEC)" \
27 | --release \
28 | -Z build-std=core,alloc \
29 | -- \
30 | -C link-arg=-T -Clink-arg="$(LD_SCRIPT)" \
31 | -C link-arg=-z -Clink-arg=max-page-size=0x1000 \
32 | --emit link="$(BUILD)/kernel.all"
33 |
34 | $(BUILD)/kernel.sym: $(BUILD)/kernel.all
35 | $(GNU_TARGET)-objcopy \
36 | --only-keep-debug \
37 | "$(BUILD)/kernel.all" \
38 | "$(BUILD)/kernel.sym"
39 |
40 | $(BUILD)/kernel: $(BUILD)/kernel.all
41 | $(GNU_TARGET)-objcopy \
42 | --strip-debug \
43 | "$(BUILD)/kernel.all" \
44 | "$(BUILD)/kernel"
45 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Kernel
2 |
3 | Redox OS Microkernel
4 |
5 | [](https://docs.rs/redox_syscall/latest/syscall/)
6 | [](https://github.com/XAMPPRocky/tokei)
7 | [](./LICENSE)
8 |
9 | ## Requirements
10 |
11 | * [`nasm`](https://nasm.us/) needs to be available on the PATH at build time.
12 |
13 | ## Building The Documentation
14 |
15 | Use this command:
16 |
17 | ```sh
18 | cargo doc --open --target x86_64-unknown-none
19 | ```
20 |
21 | ## Debugging
22 |
23 | ### QEMU
24 |
25 | Running [QEMU](https://www.qemu.org) with the `-s` flag will set up QEMU to listen on port `1234` for a GDB client to connect to it. To debug the redox kernel run.
26 |
27 | ```sh
28 | make qemu gdb=yes
29 | ```
30 |
31 | This will start a virtual machine with and listen on port `1234` for a GDB or LLDB client.
32 |
33 | ### GDB
34 |
35 | If you are going to use [GDB](https://www.gnu.org/software/gdb/), run these commands to load debug symbols and connect to your running kernel:
36 |
37 | ```
38 | (gdb) symbol-file build/kernel.sym
39 | (gdb) target remote localhost:1234
40 | ```
41 |
42 | ### LLDB
43 |
44 | If you are going to use [LLDB](https://lldb.llvm.org/), run these commands to start debugging:
45 |
46 | ```
47 | (lldb) target create -s build/kernel.sym build/kernel
48 | (lldb) gdb-remote localhost:1234
49 | ```
50 |
51 | After connecting to your kernel you can set some interesting breakpoints and `continue`
52 | the process. See your debuggers man page for more information on useful commands to run.
53 |
54 | ## Notes
55 |
56 | - Always use `foo.get(n)` instead of `foo[n]` and try to cover for the possibility of `Option::None`. Doing the regular way may work fine for applications, but never in the kernel. No possible panics should ever exist in kernel space, because then the whole OS would just stop working.
57 |
58 | - If you receive a kernel panic in QEMU, use `pkill qemu-system` to kill the frozen QEMU process.
59 |
60 | ## How To Contribute
61 |
62 | To learn how to contribute to this system component you need to read the following document:
63 |
64 | - [CONTRIBUTING.md](https://gitlab.redox-os.org/redox-os/redox/-/blob/master/CONTRIBUTING.md)
65 |
66 | ## Development
67 |
68 | To learn how to do development with this system component inside the Redox build system you need to read the [Build System](https://doc.redox-os.org/book/build-system-reference.html) and [Coding and Building](https://doc.redox-os.org/book/coding-and-building.html) pages.
69 |
70 | ### How To Build
71 |
72 | To build this system component you need to download the Redox build system, you can learn how to do it on the [Building Redox](https://doc.redox-os.org/book/podman-build.html) page.
73 |
74 | This is necessary because they only work with cross-compilation to a Redox virtual machine, but you can do some testing from Linux.
75 |
76 | ## Funding - _Unix-style Signals and Process Management_
77 |
78 | This project is funded through [NGI Zero Core](https://nlnet.nl/core), a fund established by [NLnet](https://nlnet.nl) with financial support from the European Commission's [Next Generation Internet](https://ngi.eu) program. Learn more at the [NLnet project page](https://nlnet.nl/project/RedoxOS-Signals).
79 |
80 | [
](https://nlnet.nl)
81 | [
](https://nlnet.nl/core)
82 |
--------------------------------------------------------------------------------
/build.rs:
--------------------------------------------------------------------------------
1 | use rustc_cfg::Cfg;
2 | use std::{env, path::Path, process::Command};
3 | use toml::Table;
4 |
5 | fn parse_kconfig(arch: &str) -> Option<()> {
6 | println!("cargo:rerun-if-changed=config.toml");
7 |
8 | assert!(Path::new("config.toml.example").try_exists().unwrap());
9 | if !Path::new("config.toml").try_exists().unwrap() {
10 | std::fs::copy("config.toml.example", "config.toml").unwrap();
11 | }
12 | let config_str = std::fs::read_to_string("config.toml").unwrap();
13 | let root: Table = toml::from_str(&config_str).unwrap();
14 |
15 | let altfeatures = root
16 | .get("arch")?
17 | .as_table()
18 | .unwrap()
19 | .get(arch)?
20 | .as_table()
21 | .unwrap()
22 | .get("features")?
23 | .as_table()
24 | .unwrap();
25 |
26 | let self_modifying = env::var("CARGO_FEATURE_SELF_MODIFYING").is_ok();
27 |
28 | for (name, value) in altfeatures {
29 | let mut choice = value.as_str().unwrap();
30 | assert!(matches!(choice, "always" | "never" | "auto"));
31 |
32 | if !self_modifying && choice == "auto" {
33 | choice = "never";
34 | }
35 |
36 | println!("cargo:rustc-cfg=cpu_feature_{choice}=\"{name}\"");
37 | }
38 |
39 | Some(())
40 | }
41 |
42 | fn main() {
43 | println!("cargo:rustc-env=TARGET={}", env::var("TARGET").unwrap());
44 |
45 | let out_dir = env::var("OUT_DIR").unwrap();
46 | let cfg = Cfg::of(env::var("TARGET").unwrap().as_str()).unwrap();
47 | let arch_str = cfg.target_arch.as_str();
48 |
49 | match arch_str {
50 | "aarch64" => {
51 | println!("cargo:rustc-cfg=dtb");
52 | }
53 | "x86" => {
54 | println!("cargo:rerun-if-changed=src/asm/x86/trampoline.asm");
55 |
56 | let status = Command::new("nasm")
57 | .arg("-f")
58 | .arg("bin")
59 | .arg("-o")
60 | .arg(format!("{}/trampoline", out_dir))
61 | .arg("src/asm/x86/trampoline.asm")
62 | .status()
63 | .expect("failed to run nasm");
64 | if !status.success() {
65 | panic!("nasm failed with exit status {}", status);
66 | }
67 | }
68 | "x86_64" => {
69 | println!("cargo:rerun-if-changed=src/asm/x86_64/trampoline.asm");
70 |
71 | let status = Command::new("nasm")
72 | .arg("-f")
73 | .arg("bin")
74 | .arg("-o")
75 | .arg(format!("{}/trampoline", out_dir))
76 | .arg("src/asm/x86_64/trampoline.asm")
77 | .status()
78 | .expect("failed to run nasm");
79 | if !status.success() {
80 | panic!("nasm failed with exit status {}", status);
81 | }
82 | }
83 | "riscv64" => {
84 | println!("cargo:rustc-cfg=dtb");
85 | }
86 | _ => (),
87 | }
88 |
89 | let _ = parse_kconfig(arch_str);
90 | }
91 |
--------------------------------------------------------------------------------
/clippy.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -e
4 |
5 | export RUST_TARGET_PATH="${PWD}/targets"
6 | export RUSTFLAGS="-C soft-float -C debuginfo=2"
7 | cargo clippy --lib --release --target x86_64-unknown-none "$@"
8 |
--------------------------------------------------------------------------------
/config.toml.example:
--------------------------------------------------------------------------------
1 | [arch.x86_64.features]
2 | smap = "auto"
3 | fsgsbase = "auto"
4 | xsave = "auto"
5 | xsaveopt = "auto"
6 |
7 | # vim: ft=toml
8 |
--------------------------------------------------------------------------------
/linkers/aarch64.ld:
--------------------------------------------------------------------------------
1 | ENTRY(kstart)
2 | OUTPUT_FORMAT("elf64-littleaarch64", "elf64-littleaarch64", "elf64-littleaarch64")
3 |
4 | KERNEL_OFFSET = 0xFFFFFF0000000000;
5 |
6 | SECTIONS {
7 | . = KERNEL_OFFSET;
8 |
9 | . += SIZEOF_HEADERS;
10 |
11 | /* Force the zero page to be part of a segment by creating a
12 | * dummy section in the zero page.
13 | * Limine will map the segment with the lowest vaddr value at
14 | * 0xFFFFFFFF80000000 even if the segment has a higher vaddr.
15 | * As such without the zero page being part of a segment, the
16 | * kernel would be loaded at an offset from the expected
17 | * location. As the redox kernel is not currently relocatable,
18 | * this would result in a crash. A similar issue likely exists
19 | * with multiboot/multiboot2 and the paddr of the segment.
20 | */
21 | .dummy ALIGN(8) : AT(ADDR(.dummy) - KERNEL_OFFSET) {}
22 |
23 | . = ALIGN(4096);
24 |
25 | .text : AT(ADDR(.text) - KERNEL_OFFSET) {
26 | __text_start = .;
27 | *(.text*)
28 | __usercopy_start = .;
29 | *(.usercopy-fns)
30 | __usercopy_end = .;
31 | . = ALIGN(4096);
32 | __text_end = .;
33 | }
34 |
35 | .rodata : AT(ADDR(.rodata) - KERNEL_OFFSET) {
36 | __rodata_start = .;
37 | *(.rodata*)
38 | . = ALIGN(4096);
39 | __rodata_end = .;
40 | }
41 |
42 | .data : AT(ADDR(.data) - KERNEL_OFFSET) {
43 | __data_start = .;
44 | *(.data*)
45 | . = ALIGN(4096);
46 | __data_end = .;
47 | __bss_start = .;
48 | *(.bss*)
49 | . = ALIGN(4096);
50 | __bss_end = .;
51 | }
52 |
53 | __end = .;
54 |
55 | /DISCARD/ : {
56 | *(.comment*)
57 | *(.eh_frame*)
58 | *(.gcc_except_table*)
59 | *(.note*)
60 | *(.rel.eh_frame*)
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/linkers/i686.ld:
--------------------------------------------------------------------------------
1 | ENTRY(kstart)
2 | OUTPUT_FORMAT(elf32-i386)
3 |
4 | KERNEL_OFFSET = 0xC0000000;
5 |
6 | SECTIONS {
7 | . = KERNEL_OFFSET;
8 |
9 | . += SIZEOF_HEADERS;
10 |
11 | /* Force the zero page to be part of a segment by creating a
12 | * dummy section in the zero page.
13 | * Limine will map the segment with the lowest vaddr value at
14 | * 0xFFFFFFFF80000000 even if the segment has a higher vaddr.
15 | * As such without the zero page being part of a segment, the
16 | * kernel would be loaded at an offset from the expected
17 | * location. As the redox kernel is not currently relocatable,
18 | * this would result in a crash. A similar issue likely exists
19 | * with multiboot/multiboot2 and the paddr of the segment.
20 | */
21 | .dummy : AT(ADDR(.dummy) - KERNEL_OFFSET) {}
22 |
23 | .text ALIGN(4K) : AT(ADDR(.text) - KERNEL_OFFSET) {
24 | __text_start = .;
25 | *(.text*)
26 | __usercopy_start = .;
27 | *(.usercopy-fns)
28 | __usercopy_end = .;
29 | }
30 |
31 | .rodata ALIGN(4K) : AT(ADDR(.rodata) - KERNEL_OFFSET) {
32 | __text_end = .;
33 | __rodata_start = .;
34 | *(.rodata*)
35 | }
36 |
37 | .data ALIGN(4K) : AT(ADDR(.data) - KERNEL_OFFSET) {
38 | __rodata_end = .;
39 | __data_start = .;
40 | *(.data*)
41 | . = ALIGN(4K);
42 | __data_end = .;
43 | __bss_start = .;
44 | *(.bss*)
45 | . = ALIGN(4K);
46 | }
47 |
48 | __end = .;
49 |
50 | /DISCARD/ : {
51 | *(.comment*)
52 | *(.eh_frame*)
53 | *(.gcc_except_table*)
54 | *(.note*)
55 | *(.rel.eh_frame*)
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/linkers/riscv64.ld:
--------------------------------------------------------------------------------
1 | ENTRY(kstart)
2 | OUTPUT_FORMAT("elf64-littleriscv", "elf64-littleriscv", "elf64-littleriscv" )
3 |
4 | KERNEL_OFFSET = 0xFFFFFF0000000000;
5 |
6 | SECTIONS {
7 | . = KERNEL_OFFSET;
8 |
9 | . += SIZEOF_HEADERS;
10 |
11 | /* Force the zero page to be part of a segment by creating a
12 | * dummy section in the zero page.
13 | * Linker will map the segment with the lowest vaddr value at
14 | * 0xFFFFFF0000000000 even if the segment has a higher vaddr.
15 | * As such without the zero page being part of a segment, the
16 | * kernel would be loaded at an offset from the expected
17 | * location. As the redox kernel is not currently relocatable,
18 | * this would result in a crash. A similar issue likely exists
19 | * with multiboot/multiboot2 and the paddr of the segment.
20 | */
21 | .dummy ALIGN(8) : AT(ADDR(.dummy) - KERNEL_OFFSET) {}
22 |
23 | . = ALIGN(4096);
24 |
25 | .text : AT(ADDR(.text) - KERNEL_OFFSET) {
26 | __text_start = .;
27 | *(.early_init.text*)
28 | . = ALIGN(4096);
29 | *(.text*)
30 | __usercopy_start = .;
31 | *(.usercopy-fns)
32 | __usercopy_end = .;
33 | . = ALIGN(4096);
34 | __text_end = .;
35 | }
36 |
37 | .rodata : AT(ADDR(.rodata) - KERNEL_OFFSET) {
38 | __rodata_start = .;
39 | *(.rodata*)
40 | . = ALIGN(4096);
41 | __rodata_end = .;
42 | }
43 |
44 | .data : AT(ADDR(.data) - KERNEL_OFFSET) {
45 | __data_start = .;
46 | *(.data*)
47 | *(.sdata*)
48 | . = ALIGN(4096);
49 | __data_end = .;
50 | *(.got*)
51 | . = ALIGN(4096);
52 | __bss_start = .;
53 | *(.bss*)
54 | *(.sbss*)
55 | . = ALIGN(4096);
56 | __bss_end = .;
57 | }
58 |
59 | __end = .;
60 |
61 | /DISCARD/ : {
62 | *(.comment*)
63 | *(.eh_frame*)
64 | *(.gcc_except_table*)
65 | *(.note*)
66 | *(.rel.eh_frame*)
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/linkers/x86_64.ld:
--------------------------------------------------------------------------------
1 | ENTRY(kstart)
2 | OUTPUT_FORMAT(elf64-x86-64)
3 |
4 | KERNEL_OFFSET = 0xFFFFFFFF80000000;
5 |
6 | SECTIONS {
7 | . = KERNEL_OFFSET;
8 |
9 | . += SIZEOF_HEADERS;
10 |
11 | /* Force the zero page to be part of a segment by creating a
12 | * dummy section in the zero page.
13 | * Limine will map the segment with the lowest vaddr value at
14 | * 0xFFFFFFFF80000000 even if the segment has a higher vaddr.
15 | * As such without the zero page being part of a segment, the
16 | * kernel would be loaded at an offset from the expected
17 | * location. As the redox kernel is not currently relocatable,
18 | * this would result in a crash. A similar issue likely exists
19 | * with multiboot/multiboot2 and the paddr of the segment.
20 | */
21 | .dummy : AT(ADDR(.dummy) - KERNEL_OFFSET) {}
22 |
23 | .text ALIGN(4K) : AT(ADDR(.text) - KERNEL_OFFSET) {
24 | __text_start = .;
25 | *(.text*)
26 | __usercopy_start = .;
27 | *(.usercopy-fns)
28 | __usercopy_end = .;
29 | }
30 |
31 | .rodata ALIGN(4K) : AT(ADDR(.rodata) - KERNEL_OFFSET) {
32 | __text_end = .;
33 | __rodata_start = .;
34 | *(.rodata*)
35 | __altcode_start = .;
36 | KEEP(*(.altcode*))
37 | __altcode_end = .;
38 | . = ALIGN(8);
39 | __altrelocs_start = .;
40 | KEEP(*(.altrelocs*))
41 | __altrelocs_end = .;
42 | __altfeatures_start = .;
43 | KEEP(*(.altfeatures*))
44 | __altfeatures_end = .;
45 | }
46 |
47 | .data ALIGN(4K) : AT(ADDR(.data) - KERNEL_OFFSET) {
48 | __rodata_end = .;
49 | __data_start = .;
50 | *(.data*)
51 | . = ALIGN(4K);
52 | __data_end = .;
53 | __bss_start = .;
54 | *(.bss*)
55 | }
56 |
57 | __end = .;
58 |
59 | /DISCARD/ : {
60 | *(.comment*)
61 | *(.eh_frame*)
62 | *(.gcc_except_table*)
63 | *(.note*)
64 | *(.rel.eh_frame*)
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/res/unifont.font:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redox-os/kernel/e67cca7bce085190e538e2141784125bb99ddc2f/res/unifont.font
--------------------------------------------------------------------------------
/rustfmt.toml:
--------------------------------------------------------------------------------
1 | blank_lines_lower_bound = 0 # default
2 | blank_lines_upper_bound = 1 # default
3 | brace_style = "SameLineWhere" # default
4 | disable_all_formatting = false # default
5 | edition = "2021"
6 | empty_item_single_line = true # default
7 | fn_single_line = false # default
8 | force_explicit_abi = true # default
9 | format_strings = false # default
10 | hard_tabs = false # default
11 | show_parse_errors = true # default
12 | imports_granularity = "Crate" # default = Preserve
13 | imports_indent = "Block" # default
14 | imports_layout = "Mixed" # default
15 | indent_style = "Block" # default
16 | max_width = 100 # default
17 | newline_style = "Unix" # default = Auto
18 | skip_children = false # default
19 | tab_spaces = 4 # default
20 | trailing_comma = "Vertical" # default
21 | where_single_line = false # default
22 |
--------------------------------------------------------------------------------
/src/acpi/gtdt.rs:
--------------------------------------------------------------------------------
1 | use alloc::boxed::Box;
2 | use core::mem;
3 |
4 | use super::{find_sdt, sdt::Sdt};
5 | use crate::{
6 | device::generic_timer::GenericTimer,
7 | dtb::irqchip::{register_irq, IRQ_CHIP},
8 | };
9 |
10 | #[derive(Clone, Copy, Debug)]
11 | #[repr(C, packed)]
12 | pub struct Gtdt {
13 | pub header: Sdt,
14 | pub cnt_control_base: u64,
15 | _reserved: u32,
16 | pub secure_el1_timer_gsiv: u32,
17 | pub secure_el1_timer_flags: u32,
18 | pub non_secure_el1_timer_gsiv: u32,
19 | pub non_secure_el1_timer_flags: u32,
20 | pub virtual_el1_timer_gsiv: u32,
21 | pub virtual_el1_timer_flags: u32,
22 | pub el2_timer_gsiv: u32,
23 | pub el2_timer_flags: u32,
24 | pub cnt_read_base: u64,
25 | pub platform_timer_count: u32,
26 | pub platform_timer_offset: u32,
27 | /*TODO: we don't need these yet, and they cause short tables to fail parsing
28 | pub virtual_el2_timer_gsiv: u32,
29 | pub virtual_el2_timer_flags: u32,
30 | */
31 | //TODO: platform timer structure (at platform timer offset, with platform timer count)
32 | }
33 |
34 | impl Gtdt {
35 | pub fn init() {
36 | let gtdt_sdt = find_sdt("GTDT");
37 | let gtdt = if gtdt_sdt.len() == 1 {
38 | match Gtdt::new(gtdt_sdt[0]) {
39 | Some(gtdt) => gtdt,
40 | None => {
41 | log::warn!("Failed to parse GTDT");
42 | return;
43 | }
44 | }
45 | } else {
46 | log::warn!("Unable to find GTDT");
47 | return;
48 | };
49 |
50 | let gsiv = gtdt.non_secure_el1_timer_gsiv;
51 | log::info!("generic_timer gsiv = {}", gsiv);
52 | let mut timer = GenericTimer {
53 | clk_freq: 0,
54 | reload_count: 0,
55 | };
56 | timer.init();
57 | register_irq(gsiv, Box::new(timer));
58 | unsafe { IRQ_CHIP.irq_enable(gsiv as u32) };
59 | }
60 |
61 | pub fn new(sdt: &'static Sdt) -> Option<&'static Gtdt> {
62 | if &sdt.signature == b"GTDT" && sdt.length as usize >= mem::size_of::() {
63 | Some(unsafe { &*((sdt as *const Sdt) as *const Gtdt) })
64 | } else {
65 | None
66 | }
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/src/acpi/madt/arch/aarch64.rs:
--------------------------------------------------------------------------------
1 | use alloc::{boxed::Box, vec::Vec};
2 |
3 | use super::{Madt, MadtEntry};
4 | use crate::{
5 | device::irqchip::{
6 | gic::{GenericInterruptController, GicCpuIf, GicDistIf},
7 | gicv3::{GicV3, GicV3CpuIf},
8 | },
9 | dtb::irqchip::{IrqChipItem, IRQ_CHIP},
10 | memory::{map_device_memory, PhysicalAddress, PAGE_SIZE},
11 | };
12 |
13 | pub(super) fn init(madt: Madt) {
14 | let mut gicd_opt = None;
15 | let mut giccs = Vec::new();
16 | for madt_entry in madt.iter() {
17 | println!(" {:#x?}", madt_entry);
18 | match madt_entry {
19 | MadtEntry::Gicc(gicc) => {
20 | giccs.push(gicc);
21 | }
22 | MadtEntry::Gicd(gicd) => {
23 | if gicd_opt.is_some() {
24 | log::warn!("Only one GICD should be present on a system, ignoring this one");
25 | } else {
26 | gicd_opt = Some(gicd);
27 | }
28 | }
29 | _ => {}
30 | }
31 | }
32 | let Some(gicd) = gicd_opt else {
33 | log::warn!("No GICD found");
34 | return;
35 | };
36 | let mut gic_dist_if = GicDistIf::default();
37 | unsafe {
38 | let phys = PhysicalAddress::new(gicd.physical_base_address as usize);
39 | let virt = map_device_memory(phys, PAGE_SIZE);
40 | gic_dist_if.init(virt.data());
41 | };
42 | log::info!("{:#x?}", gic_dist_if);
43 | match gicd.gic_version {
44 | 1 | 2 => {
45 | for gicc in giccs {
46 | let mut gic_cpu_if = GicCpuIf::default();
47 | unsafe {
48 | let phys = PhysicalAddress::new(gicc.physical_base_address as usize);
49 | let virt = map_device_memory(phys, PAGE_SIZE);
50 | gic_cpu_if.init(virt.data())
51 | };
52 | log::info!("{:#x?}", gic_cpu_if);
53 | let gic = GenericInterruptController {
54 | gic_dist_if,
55 | gic_cpu_if,
56 | irq_range: (0, 0),
57 | };
58 | let chip = IrqChipItem {
59 | phandle: 0,
60 | parents: Vec::new(),
61 | children: Vec::new(),
62 | ic: Box::new(gic),
63 | };
64 | unsafe { IRQ_CHIP.irq_chip_list.chips.push(chip) };
65 | //TODO: support more GICCs
66 | break;
67 | }
68 | }
69 | 3 => {
70 | for gicc in giccs {
71 | let mut gic_cpu_if = GicV3CpuIf;
72 | unsafe { gic_cpu_if.init() };
73 | log::info!("{:#x?}", gic_cpu_if);
74 | let gic = GicV3 {
75 | gic_dist_if,
76 | gic_cpu_if,
77 | //TODO: get GICRs
78 | gicrs: Vec::new(),
79 | irq_range: (0, 0),
80 | };
81 | let chip = IrqChipItem {
82 | phandle: 0,
83 | parents: Vec::new(),
84 | children: Vec::new(),
85 | ic: Box::new(gic),
86 | };
87 | unsafe { IRQ_CHIP.irq_chip_list.chips.push(chip) };
88 | //TODO: support more GICCs
89 | break;
90 | }
91 | }
92 | _ => {
93 | log::warn!("unsupported GIC version {}", gicd.gic_version);
94 | }
95 | }
96 | unsafe { IRQ_CHIP.init(None) };
97 | }
98 |
--------------------------------------------------------------------------------
/src/acpi/madt/arch/other.rs:
--------------------------------------------------------------------------------
1 | use super::Madt;
2 |
3 | pub(super) fn init(madt: Madt) {
4 | for madt_entry in madt.iter() {
5 | println!(" {:#x?}", madt_entry);
6 | }
7 |
8 | log::warn!("MADT not yet handled on this platform");
9 | }
10 |
--------------------------------------------------------------------------------
/src/acpi/rsdp.rs:
--------------------------------------------------------------------------------
1 | use crate::{
2 | memory::{Frame, KernelMapper},
3 | paging::{Page, PageFlags, PhysicalAddress, VirtualAddress},
4 | };
5 |
6 | /// RSDP
7 | #[derive(Copy, Clone, Debug)]
8 | #[repr(C, packed)]
9 | pub struct RSDP {
10 | signature: [u8; 8],
11 | _checksum: u8,
12 | _oemid: [u8; 6],
13 | revision: u8,
14 | rsdt_address: u32,
15 | _length: u32,
16 | xsdt_address: u64,
17 | _extended_checksum: u8,
18 | _reserved: [u8; 3],
19 | }
20 |
21 | impl RSDP {
22 | fn get_already_supplied_rsdp(rsdp_ptr: *const u8) -> RSDP {
23 | // TODO: Validate
24 | unsafe { *(rsdp_ptr as *const RSDP) }
25 | }
26 | pub fn get_rsdp(
27 | mapper: &mut KernelMapper,
28 | already_supplied_rsdp: Option<*const u8>,
29 | ) -> Option {
30 | if let Some(rsdp_ptr) = already_supplied_rsdp {
31 | Some(Self::get_already_supplied_rsdp(rsdp_ptr))
32 | } else {
33 | Self::get_rsdp_by_searching(mapper)
34 | }
35 | }
36 | /// Search for the RSDP
37 | pub fn get_rsdp_by_searching(mapper: &mut KernelMapper) -> Option {
38 | let start_addr = 0xE_0000;
39 | let end_addr = 0xF_FFFF;
40 |
41 | // Map all of the ACPI RSDP space
42 | {
43 | let start_frame = Frame::containing(PhysicalAddress::new(start_addr));
44 | let end_frame = Frame::containing(PhysicalAddress::new(end_addr));
45 | for frame in Frame::range_inclusive(start_frame, end_frame) {
46 | let page = Page::containing_address(VirtualAddress::new(frame.base().data()));
47 | let result = unsafe {
48 | mapper
49 | .get_mut()
50 | .expect("KernelMapper locked re-entrant while locating RSDPs")
51 | .map_phys(page.start_address(), frame.base(), PageFlags::new())
52 | .expect("failed to map page while searching for RSDP")
53 | };
54 | result.flush();
55 | }
56 | }
57 |
58 | RSDP::search(start_addr, end_addr)
59 | }
60 |
61 | fn search(start_addr: usize, end_addr: usize) -> Option {
62 | for i in 0..(end_addr + 1 - start_addr) / 16 {
63 | let rsdp = unsafe { &*((start_addr + i * 16) as *const RSDP) };
64 | if &rsdp.signature == b"RSD PTR " {
65 | return Some(*rsdp);
66 | }
67 | }
68 | None
69 | }
70 |
71 | /// Get the RSDT or XSDT address
72 | pub fn sdt_address(&self) -> usize {
73 | if self.revision >= 2 {
74 | self.xsdt_address as usize
75 | } else {
76 | self.rsdt_address as usize
77 | }
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/src/acpi/rsdt.rs:
--------------------------------------------------------------------------------
1 | use alloc::boxed::Box;
2 | use core::{convert::TryFrom, mem};
3 |
4 | use super::{rxsdt::Rxsdt, sdt::Sdt};
5 |
6 | #[derive(Debug)]
7 | pub struct Rsdt(&'static Sdt);
8 |
9 | impl Rsdt {
10 | pub fn new(sdt: &'static Sdt) -> Option {
11 | if &sdt.signature == b"RSDT" {
12 | Some(Rsdt(sdt))
13 | } else {
14 | None
15 | }
16 | }
17 | pub fn as_slice(&self) -> &[u8] {
18 | let length =
19 | usize::try_from(self.0.length).expect("expected 32-bit length to fit within usize");
20 |
21 | unsafe { core::slice::from_raw_parts(self.0 as *const _ as *const u8, length) }
22 | }
23 | }
24 |
25 | impl Rxsdt for Rsdt {
26 | fn iter(&self) -> Box> {
27 | Box::new(RsdtIter { sdt: self.0, i: 0 })
28 | }
29 | }
30 |
31 | pub struct RsdtIter {
32 | sdt: &'static Sdt,
33 | i: usize,
34 | }
35 |
36 | impl Iterator for RsdtIter {
37 | type Item = usize;
38 | fn next(&mut self) -> Option {
39 | if self.i < self.sdt.data_len() / mem::size_of::() {
40 | let item = unsafe {
41 | (self.sdt.data_address() as *const u32)
42 | .add(self.i)
43 | .read_unaligned()
44 | };
45 | self.i += 1;
46 | Some(item as usize)
47 | } else {
48 | None
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/acpi/rxsdt.rs:
--------------------------------------------------------------------------------
1 | use alloc::boxed::Box;
2 |
3 | pub trait Rxsdt {
4 | fn iter(&self) -> Box>;
5 | }
6 |
--------------------------------------------------------------------------------
/src/acpi/sdt.rs:
--------------------------------------------------------------------------------
1 | use core::mem;
2 |
3 | #[derive(Copy, Clone, Debug)]
4 | #[repr(C, packed)]
5 | pub struct Sdt {
6 | pub signature: [u8; 4],
7 | pub length: u32,
8 | pub revision: u8,
9 | pub checksum: u8,
10 | pub oem_id: [u8; 6],
11 | pub oem_table_id: [u8; 8],
12 | pub oem_revision: u32,
13 | pub creator_id: u32,
14 | pub creator_revision: u32,
15 | }
16 |
17 | impl Sdt {
18 | /// Get the address of this tables data
19 | pub fn data_address(&self) -> usize {
20 | self as *const _ as usize + mem::size_of::()
21 | }
22 |
23 | /// Get the length of this tables data
24 | pub fn data_len(&self) -> usize {
25 | let total_size = self.length as usize;
26 | let header_size = mem::size_of::();
27 | if total_size >= header_size {
28 | total_size - header_size
29 | } else {
30 | 0
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/acpi/xsdt.rs:
--------------------------------------------------------------------------------
1 | use alloc::boxed::Box;
2 | use core::{convert::TryFrom, mem};
3 |
4 | use super::{rxsdt::Rxsdt, sdt::Sdt};
5 |
6 | #[derive(Debug)]
7 | pub struct Xsdt(&'static Sdt);
8 |
9 | impl Xsdt {
10 | pub fn new(sdt: &'static Sdt) -> Option {
11 | if &sdt.signature == b"XSDT" {
12 | Some(Xsdt(sdt))
13 | } else {
14 | None
15 | }
16 | }
17 | pub fn as_slice(&self) -> &[u8] {
18 | let length =
19 | usize::try_from(self.0.length).expect("expected 32-bit length to fit within usize");
20 |
21 | unsafe { core::slice::from_raw_parts(self.0 as *const _ as *const u8, length) }
22 | }
23 | }
24 |
25 | impl Rxsdt for Xsdt {
26 | fn iter(&self) -> Box> {
27 | Box::new(XsdtIter { sdt: self.0, i: 0 })
28 | }
29 | }
30 |
31 | pub struct XsdtIter {
32 | sdt: &'static Sdt,
33 | i: usize,
34 | }
35 |
36 | impl Iterator for XsdtIter {
37 | type Item = usize;
38 | fn next(&mut self) -> Option {
39 | if self.i < self.sdt.data_len() / mem::size_of::() {
40 | let item = unsafe {
41 | core::ptr::read_unaligned((self.sdt.data_address() as *const u64).add(self.i))
42 | };
43 | self.i += 1;
44 | Some(item as usize)
45 | } else {
46 | None
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/allocator/linked_list.rs:
--------------------------------------------------------------------------------
1 | use crate::memory::KernelMapper;
2 | use core::{
3 | alloc::{GlobalAlloc, Layout},
4 | ptr::{self, NonNull},
5 | };
6 | use linked_list_allocator::Heap;
7 | use spin::Mutex;
8 |
9 | static HEAP: Mutex