forked from AbleOS/ableos
Removed unused code
This commit is contained in:
parent
e33014d000
commit
8d640b6a9b
|
@ -1,14 +0,0 @@
|
|||
[build]
|
||||
# target = "riscv64gc-unknown-none-elf"
|
||||
target = "json_targets/x86_64-ableos.json"
|
||||
|
||||
[unstable]
|
||||
build-std = ["core", "compiler_builtins", "alloc"]
|
||||
build-std-features = ["compiler-builtins-mem"]
|
||||
|
||||
[target.'cfg(target_arch = "x86_64")']
|
||||
rustflags = ["-C", "target-feature=+rdrand"]
|
||||
|
||||
[target.riscv64gc-unknown-none-elf]
|
||||
rustflags = "-C link-arg=-Tableos/src/arch/riscv/virt.lds"
|
||||
# ableos/src/arch/riscv/virt.lds
|
|
@ -1,120 +0,0 @@
|
|||
[package]
|
||||
edition = "2021"
|
||||
name = "ableos"
|
||||
version = "0.1.1"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[profile.release]
|
||||
panic = "abort"
|
||||
|
||||
[package.metadata.bootimage]
|
||||
test-args = [
|
||||
"-device",
|
||||
"isa-debug-exit,iobase=0xf4,iosize=0x04",
|
||||
"-serial",
|
||||
"stdio",
|
||||
]
|
||||
|
||||
[dependencies]
|
||||
lazy_static = { version = "1.4.0", features = ["spin_no_std"] }
|
||||
qrcode = { path = "../qrcode-rust" }
|
||||
bitflags = "1.3"
|
||||
lliw = "0.2.0"
|
||||
spin = "0.9"
|
||||
pretty-hex = "0.2.1"
|
||||
unicode-width = "0.1.7"
|
||||
picorand = "0.1.0"
|
||||
watson = "0.4"
|
||||
genfs = "0.1.0"
|
||||
axel = { git = "https://git.ablecorp.us/able/aos_userland" }
|
||||
versioning = { git = "https://git.ablecorp.us/able/aos_userland" }
|
||||
# embedded-graphics = "*"
|
||||
pc-keyboard = "0.5"
|
||||
# mini-backtrace = "0.1"
|
||||
clparse = { git = "https://git.ablecorp.us/able/core_utils", default-features = false }
|
||||
seq-macro = "0.3"
|
||||
|
||||
[dependencies.linked_list_allocator]
|
||||
version = "0.9.0"
|
||||
features = ["use_spin_nightly"]
|
||||
[dependencies.log]
|
||||
version = "0.4.17"
|
||||
default-features = false
|
||||
|
||||
[dependencies.logos]
|
||||
version = "0.12"
|
||||
default-features = false
|
||||
features = ["export_derive"]
|
||||
|
||||
[dependencies.rdrand]
|
||||
version = "0.8"
|
||||
default-features = false
|
||||
|
||||
[dependencies.kernel]
|
||||
path = "../kernel"
|
||||
|
||||
[dependencies.serde]
|
||||
version = "1.0"
|
||||
default-features = false
|
||||
features = ["derive", "alloc"]
|
||||
|
||||
[dependencies.hashbrown]
|
||||
version = "0.12"
|
||||
default-features = false
|
||||
features = ["inline-more"]
|
||||
|
||||
[dependencies.rkyv]
|
||||
version = "0.7"
|
||||
default-features = false
|
||||
features = ["size_64", "alloc"]
|
||||
|
||||
# [dependencies.smoltcp]
|
||||
# version = "0.8.0"
|
||||
# default-features = false
|
||||
# features = ["log", "proto-ipv4"]
|
||||
|
||||
[dependencies.y-compositor-protocol]
|
||||
git = "https://git.ablecorp.us:443/able/y-compositor-protocol.git"
|
||||
|
||||
[dependencies.ext2]
|
||||
path = "../ext2-rs"
|
||||
|
||||
[dependencies.toml]
|
||||
git = "https://git.ablecorp.us:443/theoddgarlic/toml-rs"
|
||||
# version = "0.5.8"
|
||||
default-features = false
|
||||
|
||||
[dependencies.facepalm]
|
||||
path = "../facepalm"
|
||||
|
||||
[dependencies.ab_glyph]
|
||||
version = "*"
|
||||
default-features = false
|
||||
features = ["libm"]
|
||||
|
||||
[dependencies.wasmi]
|
||||
default-features = false
|
||||
features = ["core"]
|
||||
version = "*"
|
||||
|
||||
[dependencies.libwasm]
|
||||
git = "https://git.ablecorp.us:443/able/libwasm.git"
|
||||
default-features = false
|
||||
|
||||
[dependencies.externc-libm]
|
||||
git = "https://git.ablecorp.us:443/able/externc-libm.git"
|
||||
|
||||
[target.'cfg(target_arch = "riscv")'.dependencies]
|
||||
riscv = "*"
|
||||
|
||||
[target.'cfg(target_arch = "x86_64")'.dependencies]
|
||||
limine = "0.1"
|
||||
cpuio = { git = "https://git.ablecorp.us/ondra05/cpuio.git" }
|
||||
pic8259 = "0.10.1"
|
||||
uart_16550 = "0.2.0"
|
||||
volatile = "0.2.6"
|
||||
x86_64 = "0.14.8"
|
||||
pc-beeper = { git = "https://github.com/AbleOS/pc-beeper" }
|
||||
acpi = "4.1.0"
|
||||
vga = { git = "https://git.ablecorp.us:443/able/vga.git" }
|
||||
# vga = { path = "../../vga" }
|
|
@ -1,11 +0,0 @@
|
|||
,-""""-. OS: \0BLUE\0 AbleOS \0RESET\0
|
||||
,'\ _ _`. Host: ???
|
||||
/ \)_)-)_)-\ Kernel: AKern-{}-v{}
|
||||
: : Uptime: {}
|
||||
\ / Packages: None
|
||||
\ / Shell: BuiltinShell
|
||||
`. ,' Resolution: 640x480
|
||||
`. ,' Terminal: VGABuffer
|
||||
`.,' CPU: {}
|
||||
/\`. ,-._ GPU: VGA Compatible
|
||||
`-' Memory: {}/{}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load diff
File diff suppressed because one or more lines are too long
|
@ -1,6 +0,0 @@
|
|||
[logging]
|
||||
enabled = true
|
||||
level = "Trace"
|
||||
log_to_serial = true
|
||||
log_to_vterm = false
|
||||
filter = ["ableos::ps2_mouse", "ableos::vterm", "ableos::devices::pci"]
|
|
@ -1,17 +0,0 @@
|
|||
pub struct KeyEvent{
|
||||
lctrl 1
|
||||
rctrl 2
|
||||
lalt 3
|
||||
ralt 4
|
||||
lsup 5
|
||||
rsup 6
|
||||
lshift 7
|
||||
rshift 8
|
||||
caps 9
|
||||
|
||||
down 10
|
||||
# Keycodes
|
||||
key 11-32
|
||||
}
|
||||
|
||||
|
|
@ -1 +0,0 @@
|
|||
{"rustc_fingerprint":3542195962280373086,"outputs":{"17598535894874457435":{"success":true,"status":"","code":0,"stdout":"rustc 1.58.0-nightly (efd048394 2021-10-20)\nbinary: rustc\ncommit-hash: efd0483949496b067cd5f7569d1b28cd3d5d3c72\ncommit-date: 2021-10-20\nhost: x86_64-unknown-linux-gnu\nrelease: 1.58.0-nightly\nLLVM version: 13.0.0\n","stderr":""},"2797684049618456168":{"success":false,"status":"exit status: 1","code":1,"stdout":"","stderr":"error: `-Csplit-debuginfo` is unstable on this platform\n\n"},"15537503139010883884":{"success":true,"status":"","code":0,"stdout":"___\nlib___.rlib\nlib___.so\nlib___.so\nlib___.a\nlib___.so\n","stderr":""},"931469667778813386":{"success":true,"status":"","code":0,"stdout":"___\nlib___.rlib\nlib___.so\nlib___.so\nlib___.a\nlib___.so\n/home/elfein/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu\ndebug_assertions\npanic=\"unwind\"\nproc_macro\ntarget_abi=\"\"\ntarget_arch=\"x86_64\"\ntarget_endian=\"little\"\ntarget_env=\"gnu\"\ntarget_family=\"unix\"\ntarget_feature=\"fxsr\"\ntarget_feature=\"sse\"\ntarget_feature=\"sse2\"\ntarget_has_atomic=\"16\"\ntarget_has_atomic=\"32\"\ntarget_has_atomic=\"64\"\ntarget_has_atomic=\"8\"\ntarget_has_atomic=\"ptr\"\ntarget_has_atomic_equal_alignment=\"16\"\ntarget_has_atomic_equal_alignment=\"32\"\ntarget_has_atomic_equal_alignment=\"64\"\ntarget_has_atomic_equal_alignment=\"8\"\ntarget_has_atomic_equal_alignment=\"ptr\"\ntarget_has_atomic_load_store=\"16\"\ntarget_has_atomic_load_store=\"32\"\ntarget_has_atomic_load_store=\"64\"\ntarget_has_atomic_load_store=\"8\"\ntarget_has_atomic_load_store=\"ptr\"\ntarget_os=\"linux\"\ntarget_pointer_width=\"64\"\ntarget_thread_local\ntarget_vendor=\"unknown\"\nunix\n","stderr":""}},"successes":{}}
|
|
@ -1,15 +0,0 @@
|
|||
{
|
||||
"llvm-target": "arm-none-eabihf",
|
||||
"target-endian": "little",
|
||||
"target-pointer-width": "32",
|
||||
"target-c-int-width": "32",
|
||||
"os": "ableos",
|
||||
"env": "eabi",
|
||||
"vendor": "unknown",
|
||||
"arch": "arm",
|
||||
"linker-flavor": "gcc",
|
||||
"linker": "arm-none-eabi-gcc",
|
||||
"data-layout": "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64",
|
||||
"executables": true,
|
||||
"relocation-model": "static"
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
{
|
||||
"arch": "aarch64",
|
||||
"data-layout": "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128",
|
||||
"disable-redzone": true,
|
||||
"env": "",
|
||||
"executables": true,
|
||||
"features": "+strict-align,+neon,+fp-armv8",
|
||||
"is-builtin": false,
|
||||
"linker": "rust-lld",
|
||||
"linker-flavor": "ld.lld",
|
||||
"linker-is-gnu": true,
|
||||
"pre-link-args": {
|
||||
"ld.lld": ["-Tsrc/arch/aarch64/aarch64-qemu.ld"]
|
||||
},
|
||||
"llvm-target": "aarch64-unknown-none",
|
||||
"max-atomic-width": 128,
|
||||
"os": "none",
|
||||
"panic-strategy": "abort",
|
||||
"relocation-model": "static",
|
||||
"target-c-int-width": "32",
|
||||
"target-endian": "little",
|
||||
"target-pointer-width": "64",
|
||||
"vendor": ""
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
{
|
||||
"llvm-target": "arm-none-eabihf",
|
||||
"target-endian": "little",
|
||||
"target-pointer-width": "32",
|
||||
"target-c-int-width": "32",
|
||||
"os": "ableos",
|
||||
"env": "eabi",
|
||||
"vendor": "unknown",
|
||||
"arch": "arm",
|
||||
"linker-flavor": "gcc",
|
||||
"linker": "arm-none-eabi-gcc",
|
||||
"data-layout": "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64",
|
||||
"executables": true,
|
||||
"relocation-model": "static"
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
{
|
||||
"llvm-target": "x86_64-unknown-none",
|
||||
"data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128",
|
||||
"arch": "x86_64",
|
||||
"target-endian": "little",
|
||||
"target-pointer-width": "64",
|
||||
"target-c-int-width": "32",
|
||||
"os": "none",
|
||||
"executables": true,
|
||||
"linker-flavor": "ld.lld",
|
||||
"linker": "rust-lld",
|
||||
"panic-strategy": "abort",
|
||||
"disable-redzone": true,
|
||||
"features": "-mmx,-sse,+soft-float",
|
||||
"code-model": "kernel",
|
||||
"pre-link-args": {
|
||||
"ld.lld": [
|
||||
"--gc-sections",
|
||||
"--script=kernel/lds/x86_64.ld"
|
||||
]
|
||||
}
|
||||
}
|
|
@ -1,256 +0,0 @@
|
|||
0-
|
||||
1-
|
||||
2-
|
||||
3-
|
||||
4-
|
||||
5-
|
||||
6-
|
||||
7-
|
||||
8-
|
||||
9-
|
||||
10-
|
||||
11-
|
||||
12-
|
||||
13-
|
||||
14-
|
||||
15-
|
||||
16-
|
||||
17-
|
||||
18-
|
||||
19-
|
||||
20-
|
||||
21-
|
||||
22-
|
||||
23-
|
||||
24-
|
||||
25-
|
||||
26-
|
||||
27-
|
||||
28-
|
||||
29-
|
||||
30-
|
||||
31-
|
||||
32-
|
||||
33-
|
||||
34-
|
||||
35-
|
||||
36-
|
||||
37-
|
||||
38-
|
||||
39-
|
||||
40-
|
||||
41-
|
||||
42-
|
||||
43-
|
||||
44-
|
||||
45-
|
||||
46-
|
||||
47-
|
||||
48-
|
||||
49-
|
||||
50-
|
||||
51-
|
||||
52-
|
||||
53-
|
||||
54-
|
||||
55-
|
||||
56-
|
||||
57-
|
||||
58-
|
||||
59-
|
||||
60-
|
||||
61-
|
||||
62-
|
||||
63-
|
||||
64-
|
||||
65-
|
||||
66-
|
||||
67-
|
||||
68-
|
||||
69-
|
||||
70-
|
||||
71-
|
||||
72-
|
||||
73-
|
||||
74-
|
||||
75-
|
||||
76-
|
||||
77-
|
||||
78-
|
||||
79-
|
||||
80-
|
||||
81-
|
||||
82-
|
||||
83-
|
||||
84-
|
||||
85-
|
||||
86-
|
||||
87-
|
||||
88-
|
||||
89-
|
||||
90-
|
||||
91-
|
||||
92-
|
||||
93-
|
||||
94-
|
||||
95-
|
||||
96-
|
||||
97-
|
||||
98-
|
||||
99-
|
||||
100-
|
||||
101-
|
||||
102-
|
||||
103-
|
||||
104-
|
||||
105-
|
||||
106-
|
||||
107-
|
||||
108-
|
||||
109-
|
||||
110-
|
||||
111-
|
||||
112-
|
||||
113-
|
||||
114-
|
||||
115-
|
||||
116-
|
||||
117-
|
||||
118-
|
||||
119-
|
||||
120-
|
||||
121-
|
||||
122-
|
||||
123-
|
||||
124-
|
||||
125-
|
||||
126-
|
||||
127-
|
||||
128-
|
||||
129-
|
||||
130-
|
||||
131-
|
||||
132-
|
||||
133-
|
||||
134-
|
||||
135-
|
||||
136-
|
||||
137-
|
||||
138-
|
||||
139-
|
||||
140-
|
||||
141-
|
||||
142-
|
||||
143-
|
||||
144-
|
||||
145-
|
||||
146-
|
||||
147-
|
||||
148-
|
||||
149-
|
||||
150-
|
||||
151-
|
||||
152-
|
||||
153-
|
||||
154-
|
||||
155-
|
||||
156-
|
||||
157-
|
||||
158-
|
||||
159-
|
||||
160-
|
||||
161-
|
||||
162-
|
||||
163-
|
||||
164-
|
||||
165-
|
||||
166-
|
||||
167-
|
||||
168-
|
||||
169-
|
||||
170-
|
||||
171-
|
||||
172-
|
||||
173-
|
||||
174-
|
||||
175-
|
||||
176-
|
||||
177-
|
||||
178-
|
||||
179-
|
||||
180-
|
||||
181-
|
||||
182-
|
||||
183-
|
||||
184-
|
||||
185-
|
||||
186-
|
||||
187-
|
||||
188-
|
||||
189-
|
||||
190-
|
||||
191-
|
||||
192-
|
||||
193-
|
||||
194-
|
||||
195-
|
||||
196-
|
||||
197-
|
||||
198-
|
||||
199-
|
||||
200-
|
||||
201-
|
||||
202-
|
||||
203-
|
||||
204-
|
||||
205-
|
||||
206-
|
||||
207-
|
||||
208-
|
||||
209-
|
||||
210-
|
||||
211-
|
||||
212-
|
||||
213-
|
||||
214-
|
||||
215-
|
||||
216-
|
||||
217-
|
||||
218-
|
||||
219-
|
||||
220-
|
||||
221-
|
||||
222-
|
||||
223-
|
||||
224-
|
||||
225-
|
||||
226-
|
||||
227-
|
||||
228-
|
||||
229-
|
||||
230-
|
||||
231-
|
||||
232-
|
||||
233-
|
||||
234-
|
||||
235-
|
||||
236-
|
||||
237-
|
||||
238-
|
||||
239-
|
||||
240-
|
||||
241-
|
||||
242-
|
||||
243-
|
||||
244-
|
||||
245-
|
||||
246-
|
||||
247-
|
||||
248-
|
||||
249-
|
||||
250-
|
||||
251-
|
||||
252-
|
||||
253-
|
||||
254-
|
||||
255-
|
|
@ -1,252 +0,0 @@
|
|||
# Able doesn't have a full keyboard
|
||||
0-NONE
|
||||
1-
|
||||
2-
|
||||
3-BACKSPACE
|
||||
4-
|
||||
5-
|
||||
6-
|
||||
7-
|
||||
8-
|
||||
9-TAB
|
||||
10-
|
||||
11-
|
||||
12-
|
||||
13-ENTER
|
||||
14-
|
||||
15-
|
||||
16-SHIFT
|
||||
17-CONTROL
|
||||
18-ALT
|
||||
19-PAUSE
|
||||
20-CAPS_LOCK
|
||||
21-
|
||||
22-
|
||||
23-
|
||||
24-
|
||||
25-
|
||||
26-
|
||||
27-
|
||||
28-
|
||||
29-
|
||||
30-
|
||||
31-
|
||||
32-SPACE
|
||||
33-PAGE_UP
|
||||
34-PAGE_DOWN
|
||||
35-END
|
||||
36-HOME
|
||||
37-ARROW_LEFT
|
||||
38-ARROW_UP
|
||||
39-ARROW_RIGHT
|
||||
40-ARROW_DOWN
|
||||
41-
|
||||
42-
|
||||
43-
|
||||
44-
|
||||
45-INSERT
|
||||
46-DELETE
|
||||
47-
|
||||
48-0
|
||||
49-1
|
||||
50-2
|
||||
51-3
|
||||
52-4
|
||||
53-5
|
||||
54-6
|
||||
55-7
|
||||
56-8
|
||||
57-9
|
||||
58-
|
||||
59-SEMICOLON
|
||||
60-
|
||||
61-EQUAL
|
||||
62-
|
||||
63-
|
||||
64-
|
||||
65-a
|
||||
66-b
|
||||
67-c
|
||||
68-d
|
||||
69-e
|
||||
70-f
|
||||
71-g
|
||||
72-h
|
||||
73-i
|
||||
74-j
|
||||
75-k
|
||||
76-l
|
||||
77-m
|
||||
78-n
|
||||
79-o
|
||||
80-p
|
||||
81-q
|
||||
82-r
|
||||
83-s
|
||||
84-t
|
||||
85-u
|
||||
86-v
|
||||
87-w
|
||||
88-x
|
||||
89-y
|
||||
90-z
|
||||
91-
|
||||
92-
|
||||
93-
|
||||
94-
|
||||
95-
|
||||
96-
|
||||
97-
|
||||
98-
|
||||
99-
|
||||
100-
|
||||
101-
|
||||
102-
|
||||
103-
|
||||
106-
|
||||
107-
|
||||
108-
|
||||
109-
|
||||
110-
|
||||
111-
|
||||
112-FUNCTION_1
|
||||
113-FUNCTION_2
|
||||
114-FUNCTION_3
|
||||
115-FUNCTION_4
|
||||
116-FUNCTION_5
|
||||
117-FUNCTION_6
|
||||
118-FUNCTION_7
|
||||
119-FUNCTION_8
|
||||
120-FUNCTION_9
|
||||
121-FUNCTION_10
|
||||
122-FUNCTION_11
|
||||
123-FUNCTION_12
|
||||
124-
|
||||
125-
|
||||
126-
|
||||
127-
|
||||
128-
|
||||
129-
|
||||
130-
|
||||
131-
|
||||
132-
|
||||
134-
|
||||
135-
|
||||
136-
|
||||
137-
|
||||
138-
|
||||
139-
|
||||
140-
|
||||
141-
|
||||
142-
|
||||
143-
|
||||
145-SCROLL_LOCK
|
||||
146-
|
||||
147-
|
||||
148-
|
||||
149-
|
||||
150-
|
||||
151-
|
||||
152-
|
||||
153-
|
||||
154-
|
||||
155-
|
||||
156-
|
||||
157-
|
||||
158-
|
||||
159-
|
||||
160-
|
||||
161-
|
||||
162-
|
||||
163-
|
||||
164-
|
||||
165-
|
||||
166-
|
||||
167-
|
||||
168-
|
||||
169-
|
||||
170-
|
||||
171-
|
||||
172-
|
||||
173-MINUS
|
||||
174-
|
||||
175-
|
||||
176-
|
||||
177-
|
||||
178-
|
||||
179-
|
||||
180-
|
||||
181-
|
||||
182-
|
||||
183-
|
||||
184-
|
||||
185-
|
||||
186-
|
||||
187-
|
||||
188-COMMA
|
||||
189-
|
||||
190-PERIOD
|
||||
191-FORWARD_SLASH
|
||||
192-GRAVE
|
||||
193-
|
||||
194-
|
||||
195-
|
||||
196-
|
||||
197-
|
||||
198-
|
||||
199-
|
||||
200-
|
||||
201-
|
||||
202-
|
||||
203-
|
||||
204-
|
||||
205-
|
||||
206-
|
||||
207-
|
||||
208-
|
||||
209-
|
||||
210-
|
||||
211-
|
||||
212-
|
||||
213-
|
||||
214-
|
||||
215-
|
||||
216-
|
||||
218-
|
||||
219-BRACKET_LEFT
|
||||
220-BACK_SLASH
|
||||
221-BRACKET_RIGHT
|
||||
222-QUOTE
|
||||
223-
|
||||
224-
|
||||
225-
|
||||
226-
|
||||
227-
|
||||
228-
|
||||
229-
|
||||
230-
|
||||
231-
|
||||
232-
|
||||
233-
|
||||
234-
|
||||
235-
|
||||
236-
|
||||
237-
|
||||
238-
|
||||
239-
|
||||
240-
|
||||
241-
|
||||
242-
|
||||
243-
|
||||
244-
|
||||
245-
|
||||
246-
|
||||
247-
|
||||
248-
|
||||
249-
|
||||
250-
|
||||
251-
|
||||
252-
|
||||
253-
|
||||
254-
|
||||
255-
|
|
@ -1,73 +0,0 @@
|
|||
//! The allocator to be implemented by ableOS
|
||||
//!
|
||||
//! NOTE: All memory regions are taken from https://wiki.osdev.org/Memory_Map_(x86)
|
||||
|
||||
use alloc::alloc::{GlobalAlloc, Layout};
|
||||
use core::{fmt::Display, ptr::null_mut};
|
||||
|
||||
const HEAP_START: usize = 600_000_000;
|
||||
const BLOCK_SIZE: usize = 1024;
|
||||
const BLOCK_COUNT: usize = 512;
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct MemoryRegion {
|
||||
_start: usize,
|
||||
_end: usize,
|
||||
}
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct AAlloc {
|
||||
current_region: usize,
|
||||
memory_regions: [Option<MemoryRegion>; 512],
|
||||
}
|
||||
|
||||
impl AAlloc {
|
||||
pub fn add_region(&mut self, mem: MemoryRegion) {
|
||||
self.memory_regions[self.current_region] = Some(mem);
|
||||
self.current_region += 1;
|
||||
}
|
||||
|
||||
pub fn intialize() {
|
||||
info!("Heap Start: {}", HEAP_START);
|
||||
info!("Heap Size: {}", BLOCK_SIZE * BLOCK_COUNT);
|
||||
info!("Heap End: {}", HEAP_START + BLOCK_SIZE * BLOCK_COUNT);
|
||||
|
||||
let mut aalloc = AAlloc {
|
||||
current_region: 0,
|
||||
memory_regions: [None; 512],
|
||||
};
|
||||
|
||||
aalloc.add_region(MemoryRegion {
|
||||
_start: 0x00100000,
|
||||
_end: 0x00EFFFFF,
|
||||
});
|
||||
debug!("{}", aalloc);
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for AAlloc {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
||||
write!(f, "AAlloc {{\n\tcurrent_region: {},\n", self.current_region)?;
|
||||
|
||||
for x in 0..self.current_region {
|
||||
if let Some(region) = self.memory_regions[x] {
|
||||
write!(f, "\tRegion {}: {:?}\n", x, region)?;
|
||||
}
|
||||
}
|
||||
write!(f, "}}")?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl GlobalAlloc for AAlloc {
|
||||
unsafe fn alloc(&self, _layout: Layout) -> *mut u8 {
|
||||
println!("Allocating memory");
|
||||
|
||||
println!("{}", _layout.size());
|
||||
println!("{}", _layout.align());
|
||||
|
||||
null_mut()
|
||||
}
|
||||
|
||||
unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {
|
||||
panic!("dealloc should be never called")
|
||||
}
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
pub mod aalloc;
|
||||
pub use aalloc::*;
|
||||
|
||||
pub const HEAP_START: usize = 0x_4444_4444_0000;
|
||||
pub const HEAP_MULTIPLIER: usize = 100000;
|
||||
pub const HEAP_BASE: usize = 100;
|
||||
pub const HEAP_SIZE: usize = HEAP_BASE * HEAP_MULTIPLIER;
|
||||
|
||||
/*
|
||||
#[global_allocator]
|
||||
pub static ALLOCATOR: LockedHeap = LockedHeap::empty();
|
||||
|
||||
#[alloc_error_handler]
|
||||
fn alloc_error_handler(layout: alloc::alloc::Layout) -> ! {
|
||||
panic!("allocation error: {:?}", layout)
|
||||
}
|
||||
|
||||
|
||||
*/
|
|
@ -1,14 +0,0 @@
|
|||
ENTRY(_start)
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x40000000;
|
||||
.text.boot : { *(.text.boot) }
|
||||
.text : { *(.text) }
|
||||
.data : { *(.data) }
|
||||
.rodata : { *(.rodata) }
|
||||
.bss : { *(.bss) }
|
||||
|
||||
. = ALIGN(8);
|
||||
. = . + 0x4000;
|
||||
LD_STACK_PTR = .;
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
.globl _start
|
||||
.extern LD_STACK_PTR
|
||||
|
||||
.section ".text.boot"
|
||||
|
||||
_start:
|
||||
ldr x30, =LD_STACK_PTR
|
||||
mov sp, x30
|
||||
bl not_main
|
||||
|
||||
.equ PSCI_SYSTEM_OFF, 0x84000008
|
||||
.globl system_off
|
||||
system_off:
|
||||
ldr x0, =PSCI_SYSTEM_OFF
|
||||
hvc #0
|
|
@ -1,13 +0,0 @@
|
|||
use alloc::alloc::{GlobalAlloc, Layout};
|
||||
use core::ptr::null_mut;
|
||||
|
||||
pub struct Dummy;
|
||||
unsafe impl GlobalAlloc for Dummy {
|
||||
unsafe fn alloc(&self, _layout: Layout) -> *mut u8 {
|
||||
null_mut()
|
||||
}
|
||||
|
||||
unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {
|
||||
panic!("dealloc should be never called")
|
||||
}
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
use crate::driver_traits::graphics::{Graphics, Point, Rgb};
|
||||
|
||||
pub struct GraphicsBuffer;
|
||||
|
||||
#[allow(unused)]
|
||||
impl Graphics for GraphicsBuffer {
|
||||
fn put_line(coords_start: Point, coords_end: Point, thickness: u32, color: Rgb) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn put_rect(coords_start: Point, coords_end: Point, color: Rgb) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn put_circle(coords: Point, radius: u32) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn put_triangle(coords_1: Point, coords_2: Point, coords_3: Point, thickness: u32, color: Rgb) {
|
||||
todo!();
|
||||
}
|
||||
|
||||
fn put_pixel(coords: Point, color: Rgb) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn paint_cursor(coords: Point) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn hide_cursor() {}
|
||||
fn show_cursor() {}
|
||||
fn draw() {}
|
||||
fn clear() {
|
||||
todo!()
|
||||
}
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
pub mod allocator;
|
||||
pub mod graphics;
|
||||
pub mod nrf52;
|
||||
pub mod serial;
|
|
@ -1,70 +0,0 @@
|
|||
//! A not-very-useful abstraction of GPIOs in Rust
|
||||
#![allow(dead_code)]
|
||||
|
||||
use core::sync::atomic::{AtomicBool, Ordering::SeqCst};
|
||||
|
||||
const REG_P0_PIN_CNF_BASE: *mut u32 = 0x5000_0700 as *mut u32;
|
||||
const REG_P0_OUT_SET: *mut u32 = 0x5000_0508 as *mut u32;
|
||||
const REG_P0_OUT_CLR: *mut u32 = 0x5000_050C as *mut u32;
|
||||
|
||||
const PIN_CNF_DIR_OUTPUT: u32 = 0x0000_0001;
|
||||
const PIN_CNF_INPUT_CONNECT: u32 = 0x0000_0000;
|
||||
const PIN_CNF_PULL_DISABLED: u32 = 0x0000_0000;
|
||||
const PIN_CNF_DRIVE_S0S1: u32 = 0x0000_0000;
|
||||
const PIN_CNF_SENSE_DISABLED: u32 = 0x0000_0000;
|
||||
/// A struct that represents an nRF52 Pin
|
||||
pub struct Pin(u8);
|
||||
impl Pin {
|
||||
/// Set a pin to be a push pull output
|
||||
pub fn set_push_pull_output(&mut self, level: Level) {
|
||||
// set level
|
||||
match level {
|
||||
Level::High => self.set_high(),
|
||||
Level::Low => self.set_low(),
|
||||
}
|
||||
|
||||
let set_val = PIN_CNF_DIR_OUTPUT
|
||||
| PIN_CNF_INPUT_CONNECT
|
||||
| PIN_CNF_PULL_DISABLED
|
||||
| PIN_CNF_DRIVE_S0S1
|
||||
| PIN_CNF_SENSE_DISABLED;
|
||||
|
||||
unsafe {
|
||||
core::ptr::write_volatile(REG_P0_PIN_CNF_BASE.offset(self.0 as isize), set_val);
|
||||
}
|
||||
}
|
||||
|
||||
/// Set a pin to output level low
|
||||
pub fn set_low(&mut self) {
|
||||
unsafe { core::ptr::write_volatile(REG_P0_OUT_SET, 1 << (self.0 as u32)) }
|
||||
}
|
||||
|
||||
/// Set a pin to output level high
|
||||
pub fn set_high(&mut self) {
|
||||
unsafe { core::ptr::write_volatile(REG_P0_OUT_CLR, 1 << (self.0 as u32)) }
|
||||
}
|
||||
}
|
||||
|
||||
/// The level of a GPIO
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum Level {
|
||||
Low,
|
||||
High,
|
||||
}
|
||||
|
||||
/// A struct that represents P0 of the nRF52
|
||||
pub struct Pins {
|
||||
pub p0_31: Pin,
|
||||
}
|
||||
|
||||
impl Pins {
|
||||
/// A function to obtain a Port 0 singleton structure
|
||||
pub fn take() -> Self {
|
||||
static TAKEN: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
// Enforce this as a singleton
|
||||
assert!(!TAKEN.swap(true, SeqCst));
|
||||
|
||||
Self { p0_31: Pin(31) }
|
||||
}
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
/// Prints to the host through the serial interface.
|
||||
#[macro_export]
|
||||
macro_rules! serial_print {
|
||||
($($arg:tt)*) => {};
|
||||
}
|
||||
|
||||
/// Prints to the host through the serial interface, appending a newline.
|
||||
#[macro_export]
|
||||
macro_rules! serial_println {
|
||||
() => {};
|
||||
($fmt:expr) => {};
|
||||
($fmt:expr, $($arg:tt)*) => {};
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
pub fn init() {}
|
|
@ -1,66 +0,0 @@
|
|||
pub mod drivers;
|
||||
pub mod init;
|
||||
|
||||
use crate::arch::drivers::nrf52::{Level, Pins};
|
||||
use core::ptr;
|
||||
use core::ptr::write_volatile;
|
||||
|
||||
global_asm!(include_str!("boot.s"));
|
||||
|
||||
fn delay(ticks: usize) {
|
||||
static mut DUMMY: usize = 0;
|
||||
|
||||
// Reduce the number of iterations when in debug mode
|
||||
#[cfg(debug_assertions)]
|
||||
let ticks = ticks / 128;
|
||||
|
||||
for t in 0..ticks {
|
||||
// Prevent the optimizer from removing this loop
|
||||
unsafe {
|
||||
write_volatile(&mut DUMMY, t);
|
||||
}
|
||||
}
|
||||
}
|
||||
use crate::print;
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn not_main() {
|
||||
const UART0: *mut u8 = 0x0900_0000 as *mut u8;
|
||||
for byte in b"ableOS Arm 64" {
|
||||
unsafe {
|
||||
ptr::write_volatile(UART0, *byte);
|
||||
}
|
||||
}
|
||||
|
||||
// let gpios = Pins::take();
|
||||
// let mut led = gpios.p0_31;
|
||||
//
|
||||
// loop {
|
||||
// led.set_high();
|
||||
// delay(2_000_000);
|
||||
//
|
||||
// led.set_low();
|
||||
// delay(6_000_000);
|
||||
// }
|
||||
//
|
||||
// led.set_push_pull_output(Level::Low);
|
||||
|
||||
crate::kmain::kernel_main();
|
||||
sloop();
|
||||
}
|
||||
|
||||
pub fn sloop() -> ! {
|
||||
loop {}
|
||||
}
|
||||
|
||||
pub fn print() {
|
||||
for byte in b"ableOS Arm 64" {
|
||||
const UART0: *mut u8 = 0x0900_0000 as *mut u8;
|
||||
|
||||
unsafe {
|
||||
ptr::write_volatile(UART0, *byte);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn shutdown() {}
|
|
@ -1,4 +0,0 @@
|
|||
cargo build --target=json_targets/aarch64-ableos.json --release &&\
|
||||
qemu-system-aarch64 -machine virt -m 1024M -cpu cortex-a53 \
|
||||
-kernel target/aarch64-ableos/release/ableos -serial stdio \
|
||||
-device virtio-keyboard
|
|
@ -1,13 +0,0 @@
|
|||
use alloc::alloc::{GlobalAlloc, Layout};
|
||||
use core::ptr::null_mut;
|
||||
|
||||
pub struct Dummy;
|
||||
unsafe impl GlobalAlloc for Dummy {
|
||||
unsafe fn alloc(&self, _layout: Layout) -> *mut u8 {
|
||||
null_mut()
|
||||
}
|
||||
|
||||
unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {
|
||||
panic!("dealloc should be never called")
|
||||
}
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
use crate::driver_traits::graphics::{Graphics, Point, Rgb};
|
||||
|
||||
pub struct GraphicsBuffer;
|
||||
|
||||
#[allow(unused)]
|
||||
impl Graphics for GraphicsBuffer {
|
||||
fn put_line(coords_start: Point, coords_end: Point, thickness: u32, color: Rgb) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn put_rect(coords_start: Point, coords_end: Point, color: Rgb) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn put_circle(coords: Point, radius: u32) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn put_triangle(coords_1: Point, coords_2: Point, coords_3: Point, thickness: u32, color: Rgb) {
|
||||
todo!();
|
||||
}
|
||||
|
||||
fn put_pixel(coords: Point, color: Rgb) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn paint_cursor(coords: Point) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn hide_cursor() {}
|
||||
fn show_cursor() {}
|
||||
fn draw() {}
|
||||
fn clear() {
|
||||
todo!()
|
||||
}
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
/// # Safety
|
||||
///
|
||||
/// We label the mmio function unsafe since
|
||||
/// we will be working with raw memory. Rust cannot
|
||||
/// make any guarantees when we do this.
|
||||
#[inline(always)]
|
||||
fn mmio_write(address: usize, offset: usize, value: u8) {
|
||||
// Set the pointer based off of the address
|
||||
let reg = address as *mut u8;
|
||||
|
||||
// write_volatile is a member of the *mut raw
|
||||
// and we can use the .add() to give us another pointer
|
||||
// at an offset based on the original pointer's memory
|
||||
// address. NOTE: The add uses pointer arithmetic so it is
|
||||
// new_pointer = old_pointer + sizeof(pointer_type) * offset
|
||||
unsafe {
|
||||
reg.add(offset).write_volatile(value);
|
||||
}
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// We label the mmio function unsafe since
|
||||
/// we will be working with raw memory. Rust cannot
|
||||
/// make any guarantees when we do this.
|
||||
fn mmio_read(address: usize, offset: usize, value: u8) -> u8 {
|
||||
// Set the pointer based off of the address
|
||||
let reg = address as *mut u8;
|
||||
|
||||
// read_volatile() is much like write_volatile() except it
|
||||
// will grab 8-bits from the pointer and give that value to us.
|
||||
// We don't add a semi-colon at the end here so that the value
|
||||
// is "returned".
|
||||
unsafe { reg.add(offset).read_volatile() }
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
pub mod allocator;
|
||||
pub mod graphics;
|
||||
pub mod mmio;
|
||||
pub mod sysinfo;
|
||||
pub mod uart;
|
|
@ -1,23 +0,0 @@
|
|||
pub fn sysinfo() {}
|
||||
pub fn master() -> Option<Master> {
|
||||
Some(Master {
|
||||
brand_string: Some("riscv".to_string()),
|
||||
})
|
||||
}
|
||||
|
||||
pub struct Master {
|
||||
// TODO: Rename struct
|
||||
// version_information: Option<VersionInformation>,
|
||||
// thermal_power_management_information: Option<ThermalPowerManagementInformation>,
|
||||
// structured_extended_information: Option<StructuredExtendedInformation>,
|
||||
// extended_processor_signature: Option<ExtendedProcessorSignature>,
|
||||
pub brand_string: Option<String>,
|
||||
// cache_line: Option<CacheLine>,
|
||||
// time_stamp_counter: Option<TimeStampCounter>,
|
||||
// physical_address_size: Option<PhysicalAddressSize>,
|
||||
}
|
||||
impl Master {
|
||||
pub fn brand_string(&self) -> Option<&str> {
|
||||
self.brand_string.as_deref()
|
||||
}
|
||||
}
|
|
@ -1,129 +0,0 @@
|
|||
use core::fmt::{Error, Write};
|
||||
|
||||
/// Initialize the UART driver by setting
|
||||
/// the word length, FIFOs, and interrupts
|
||||
pub fn uart_init(base_addr: usize) {
|
||||
let ptr = base_addr as *mut u8;
|
||||
unsafe {
|
||||
// First, set the word length, which
|
||||
// are bits 0, and 1 of the line control register (LCR)
|
||||
// which is at base_address + 3
|
||||
// We can easily write the value 3 here or 0b11, but I'm
|
||||
// extending it so that it is clear we're setting two individual
|
||||
// fields
|
||||
// Word 0 Word 1
|
||||
// ~~~~~~ ~~~~~~
|
||||
let lcr = (1 << 0) | (1 << 1);
|
||||
ptr.add(3).write_volatile(lcr);
|
||||
|
||||
// Now, enable the FIFO, which is bit index 0 of the FIFO
|
||||
// control register (FCR at offset 2).
|
||||
// Again, we can just write 1 here, but when we use left shift,
|
||||
// it's easier to see that we're trying to write bit index #0.
|
||||
ptr.add(2).write_volatile(1 << 0);
|
||||
|
||||
// Enable receiver buffer interrupts, which is at bit index
|
||||
// 0 of the interrupt enable register (IER at offset 1).
|
||||
ptr.add(1).write_volatile(1 << 0);
|
||||
|
||||
// If we cared about the divisor, the code below would set the divisor
|
||||
// from a global clock rate of 22.729 MHz (22,729,000 cycles per second)
|
||||
// to a signaling rate of 2400 (BAUD). We usually have much faster signalling
|
||||
// rates nowadays, but this demonstrates what the divisor actually does.
|
||||
// The formula given in the NS16500A specification for calculating the divisor
|
||||
// is:
|
||||
// divisor = ceil( (clock_hz) / (baud_sps x 16) )
|
||||
// So, we substitute our values and get:
|
||||
// divisor = ceil( 22_729_000 / (2400 x 16) )
|
||||
// divisor = ceil( 22_729_000 / 38_400 )
|
||||
// divisor = ceil( 591.901 ) = 592
|
||||
|
||||
// The divisor register is two bytes (16 bits), so we need to split the value
|
||||
// 592 into two bytes. Typically, we would calculate this based on measuring
|
||||
// the clock rate, but again, for our purposes [qemu], this doesn't really do
|
||||
// anything.
|
||||
let divisor: u16 = 592;
|
||||
let divisor_least: u8 = (divisor & 0xff).try_into().unwrap();
|
||||
let divisor_most: u8 = (divisor >> 8).try_into().unwrap();
|
||||
|
||||
// Notice that the divisor register DLL (divisor latch least) and DLM (divisor
|
||||
// latch most) have the same base address as the receiver/transmitter and the
|
||||
// interrupt enable register. To change what the base address points to, we
|
||||
// open the "divisor latch" by writing 1 into the Divisor Latch Access Bit
|
||||
// (DLAB), which is bit index 7 of the Line Control Register (LCR) which
|
||||
// is at base_address + 3.
|
||||
ptr.add(3).write_volatile(lcr | 1 << 7);
|
||||
|
||||
// Now, base addresses 0 and 1 point to DLL and DLM, respectively.
|
||||
// Put the lower 8 bits of the divisor into DLL
|
||||
ptr.add(0).write_volatile(divisor_least);
|
||||
ptr.add(1).write_volatile(divisor_most);
|
||||
|
||||
// Now that we've written the divisor, we never have to touch this again. In
|
||||
// hardware, this will divide the global clock (22.729 MHz) into one suitable
|
||||
// for 2,400 signals per second. So, to once again get access to the
|
||||
// RBR/THR/IER registers, we need to close the DLAB bit by clearing it to 0.
|
||||
ptr.add(3).write_volatile(lcr);
|
||||
}
|
||||
}
|
||||
|
||||
fn uart_get(base_addr: usize) -> Option<u8> {
|
||||
let ptr = base_addr as *mut u8;
|
||||
unsafe {
|
||||
// Bit index #5 is the Line Control Register.
|
||||
if ptr.add(5).read_volatile() & 1 == 0 {
|
||||
// The DR bit is 0, meaning no data
|
||||
None
|
||||
} else {
|
||||
// The DR bit is 1, meaning data!
|
||||
Some(ptr.add(0).read_volatile())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn uart_put(base_addr: usize, c: u8) {
|
||||
let ptr = base_addr as *mut u8;
|
||||
unsafe {
|
||||
// If we get here, the transmitter is empty, so transmit
|
||||
// our stuff!
|
||||
ptr.add(0).write_volatile(c);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Uart {
|
||||
base_address: usize,
|
||||
}
|
||||
|
||||
impl Uart {
|
||||
pub fn new(base_address: usize) -> Self {
|
||||
Uart { base_address }
|
||||
}
|
||||
|
||||
pub fn get(&self) -> Option<u8> {
|
||||
uart_get(self.base_address)
|
||||
}
|
||||
|
||||
pub fn put(&self, c: u8) {
|
||||
uart_put(self.base_address, c);
|
||||
}
|
||||
|
||||
pub fn init(&self) {
|
||||
uart_init(self.base_address);
|
||||
}
|
||||
}
|
||||
|
||||
// This is a slightly different syntax. Write is this "trait", meaning it is much like
|
||||
// an interface where we're just guaranteeing a certain function signature. In the Write
|
||||
// trait, one is absolutely required to be implemented, which is write_str. There are other
|
||||
// functions, but they all rely on write_str(), so their default implementation is OK for now.
|
||||
impl Write for Uart {
|
||||
// The trait Write expects us to write the function write_str
|
||||
// which looks like:
|
||||
fn write_str(&mut self, s: &str) -> Result<(), Error> {
|
||||
for c in s.bytes() {
|
||||
self.put(c);
|
||||
}
|
||||
// Return that we succeeded.
|
||||
Ok(())
|
||||
}
|
||||
}
|
Binary file not shown.
|
@ -1 +0,0 @@
|
|||
pub fn init() {}
|
|
@ -1,99 +0,0 @@
|
|||
pub mod drivers;
|
||||
pub mod init;
|
||||
|
||||
use crate::print;
|
||||
use crate::println;
|
||||
use core::arch::asm;
|
||||
|
||||
#[naked]
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn _boot() -> ! {
|
||||
#[rustfmt::skip]
|
||||
asm!("
|
||||
csrw sie, zero
|
||||
csrci sstatus, 2
|
||||
|
||||
.option push
|
||||
.option norelax
|
||||
lla gp, __global_pointer$
|
||||
.option pop
|
||||
|
||||
lla sp, __tmp_stack_top
|
||||
|
||||
lla t0, __bss_start
|
||||
lla t1, __bss_end
|
||||
|
||||
1:
|
||||
beq t0, t1, 2f
|
||||
sd zero, (t0)
|
||||
addi t0, t0, 8
|
||||
j 1b
|
||||
|
||||
2:
|
||||
j {}
|
||||
",
|
||||
sym _start, options(noreturn));
|
||||
}
|
||||
|
||||
extern "C" fn _start() -> ! {
|
||||
use crate::serial_println;
|
||||
|
||||
let uart = crate::arch::drivers::uart::Uart::new(0x1000_0000);
|
||||
uart.init();
|
||||
log!("Hello, world!\r");
|
||||
|
||||
loop {
|
||||
if let Some(c) = uart.get() {
|
||||
match c {
|
||||
66 => break,
|
||||
10 | 13 => {
|
||||
uart.put('\n' as u8);
|
||||
uart.put('\r' as u8);
|
||||
}
|
||||
|
||||
/*
|
||||
91 => {
|
||||
if let Some(ch) = uart.get() {
|
||||
match ch as char {
|
||||
'A' => {
|
||||
serial_println!("That's the up arrow!");
|
||||
}
|
||||
'B' => {
|
||||
serial_println!("That's the down arrow!");
|
||||
}
|
||||
'C' => {
|
||||
serial_println!("That's the right arrow!");
|
||||
}
|
||||
'D' => {
|
||||
serial_println!("That's the left arrow!");
|
||||
}
|
||||
_ => {
|
||||
serial_println!("That's something else!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
_ => {
|
||||
uart.put(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
serial_println!("Serial connection closed.\r");
|
||||
sloop()
|
||||
}
|
||||
|
||||
pub fn sloop() -> ! {
|
||||
loop {
|
||||
unsafe {
|
||||
asm!("wfi");
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
pub fn shutdown() {}
|
||||
pub fn generate_process_pass() -> u128 {
|
||||
123
|
||||
}
|
|
@ -1,64 +0,0 @@
|
|||
OUTPUT_ARCH(riscv64gc)
|
||||
|
||||
ENTRY(_boot);
|
||||
|
||||
|
||||
SECTIONS {
|
||||
. = 0x80200000;
|
||||
.text : {
|
||||
PROVIDE(__text_start = .);
|
||||
PROVIDE(KERNEL_START = .);
|
||||
*(.init.boot)
|
||||
*(.init.rust)
|
||||
*(.text .text.*)
|
||||
. = ALIGN(4K);
|
||||
PROVIDE(__text_end = .);
|
||||
}
|
||||
|
||||
.data : {
|
||||
PROVIDE(__data_start = .);
|
||||
*(.data .data.* .rodata .rodata.*)
|
||||
. = ALIGN(8);
|
||||
PROVIDE(__tmp_stack_bottom = .);
|
||||
. += 1024 * 1024 * 4;
|
||||
PROVIDE(__tmp_stack_top = .);
|
||||
. += 4096;
|
||||
PROVIDE(__scratch_stack = .);
|
||||
. = ALIGN(8);
|
||||
}
|
||||
|
||||
. = ALIGN(8);
|
||||
|
||||
.sdata : {
|
||||
PROVIDE(__global_pointer$ = .);
|
||||
*(.sdata .sdata.*)
|
||||
. = ALIGN(4K);
|
||||
PROVIDE(__data_end = .);
|
||||
}
|
||||
|
||||
PROVIDE(__bss_start = .);
|
||||
.sbss : {
|
||||
*(.sbss .sbss.*);
|
||||
}
|
||||
|
||||
.bss : {
|
||||
*(.bss .bss.*)
|
||||
}
|
||||
. = ALIGN(4K);
|
||||
PROVIDE(__bss_end = .);
|
||||
|
||||
.tdata : {
|
||||
. = ALIGN(4K);
|
||||
PROVIDE(__tdata_start = .);
|
||||
|
||||
*(.tdata .tdata.*)
|
||||
|
||||
. = ALIGN(4K);
|
||||
PROVIDE(__tdata_end = .);
|
||||
}
|
||||
|
||||
. = ALIGN(2M);
|
||||
PROVIDE(KERNEL_END = .);
|
||||
|
||||
/DISCARD/ : { *(.eh_frame_hdr .eh_frame) }
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
use alloc::alloc::{GlobalAlloc, Layout};
|
||||
use core::ptr::null_mut;
|
||||
use kernel::allocator::{HEAP_SIZE, HEAP_START};
|
||||
use x86_64::{
|
||||
structures::paging::{
|
||||
mapper::MapToError, FrameAllocator, Mapper, Page, PageTableFlags, Size4KiB,
|
||||
},
|
||||
VirtAddr,
|
||||
};
|
||||
pub struct Dummy;
|
||||
unsafe impl GlobalAlloc for Dummy {
|
||||
unsafe fn alloc(&self, _layout: Layout) -> *mut u8 {
|
||||
null_mut()
|
||||
}
|
||||
|
||||
unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {
|
||||
panic!("dealloc should be never called")
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init_heap(
|
||||
mapper: &mut impl Mapper<Size4KiB>,
|
||||
frame_allocator: &mut impl FrameAllocator<Size4KiB>,
|
||||
) -> Result<(), MapToError<Size4KiB>> {
|
||||
let page_range = {
|
||||
let heap_start = VirtAddr::new(HEAP_START as u64);
|
||||
let heap_end = heap_start + HEAP_SIZE - 1u64;
|
||||
let heap_start_page = Page::containing_address(heap_start);
|
||||
let heap_end_page = Page::containing_address(heap_end);
|
||||
Page::range_inclusive(heap_start_page, heap_end_page)
|
||||
};
|
||||
|
||||
for page in page_range {
|
||||
let frame = frame_allocator
|
||||
.allocate_frame()
|
||||
.ok_or(MapToError::FrameAllocationFailed)?;
|
||||
let flags = PageTableFlags::PRESENT | PageTableFlags::WRITABLE;
|
||||
unsafe { mapper.map_to(page, frame, flags, frame_allocator)?.flush() };
|
||||
}
|
||||
|
||||
unsafe {
|
||||
kernel::allocator::ALLOCATOR
|
||||
.lock()
|
||||
.init(HEAP_START, HEAP_SIZE);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
use crate::driver_traits::graphics::{Graphics, Point, Rgb};
|
||||
use cpuio::outw;
|
||||
|
||||
pub struct GraphicsBuffer;
|
||||
|
||||
#[allow(unused)]
|
||||
impl Graphics for GraphicsBuffer {
|
||||
fn put_line(coords_start: Point, coords_end: Point, thickness: u32, color: Rgb) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn put_rect(coords_start: Point, coords_end: Point, color: Rgb) {}
|
||||
|
||||
fn put_circle(coords: Point, radius: u32) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn put_triangle(coords_1: Point, coords_2: Point, coords_3: Point, thickness: u32, color: Rgb) {
|
||||
todo!();
|
||||
}
|
||||
|
||||
fn put_pixel(coords: Point, color: Rgb) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn paint_cursor(coords: Point) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn hide_cursor() {
|
||||
unsafe {
|
||||
outw(0x0A, 0x3D4);
|
||||
outw(0x20, 0x3D5);
|
||||
}
|
||||
}
|
||||
|
||||
fn show_cursor() {}
|
||||
fn draw() {}
|
||||
fn clear() {
|
||||
todo!()
|
||||
}
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
pub mod allocator;
|
||||
// pub mod graphics;
|
||||
pub mod serial;
|
||||
pub mod sysinfo;
|
||||
pub mod timer;
|
||||
|
||||
#[deprecated(note = "The use of hardware specific drivers for VGA is discouraged")]
|
||||
pub mod vga;
|
|
@ -1,36 +0,0 @@
|
|||
use spin::{Lazy, Mutex};
|
||||
use uart_16550::SerialPort;
|
||||
|
||||
pub static SERIAL1: Lazy<Mutex<SerialPort>> = Lazy::new(|| {
|
||||
let mut serial_port = unsafe { SerialPort::new(0x3F8) };
|
||||
serial_port.init();
|
||||
Mutex::new(serial_port)
|
||||
});
|
||||
|
||||
#[doc(hidden)]
|
||||
pub fn _print(args: ::core::fmt::Arguments) {
|
||||
use core::fmt::Write;
|
||||
// /*
|
||||
SERIAL1
|
||||
.lock()
|
||||
.write_fmt(args)
|
||||
.expect("Printing to serial failed");
|
||||
// */
|
||||
}
|
||||
|
||||
/// Prints to the host through the serial interface.
|
||||
#[macro_export]
|
||||
macro_rules! sprint {
|
||||
($($arg:tt)*) => {
|
||||
$crate::arch::drivers::serial::_print(format_args!($($arg)*));
|
||||
};
|
||||
}
|
||||
|
||||
/// Prints to the host through the serial interface, appending a newline.
|
||||
#[macro_export]
|
||||
macro_rules! sprintln {
|
||||
() => ($crate::sprint!("\n"));
|
||||
($fmt:expr) => ($crate::sprint!(concat!($fmt, "\n")));
|
||||
($fmt:expr, $($arg:tt)*) => ($crate::sprint!(
|
||||
concat!($fmt, "\n"), $($arg)*));
|
||||
}
|
|
@ -1,954 +0,0 @@
|
|||
//! ```
|
||||
//! extern crate cupid;
|
||||
//!
|
||||
//! fn main() {
|
||||
//! let information = cupid::master();
|
||||
//! println!("{:#?}", information);
|
||||
//! if let Some(information) = information {
|
||||
//! if information.sse4_2() {
|
||||
//! println!("SSE 4.2 Available");
|
||||
//! }
|
||||
//! }
|
||||
//! }
|
||||
//! ```
|
||||
|
||||
#![cfg_attr(
|
||||
not(any(target_arch = "x86_64", target_arch = "x86")),
|
||||
allow(dead_code)
|
||||
)]
|
||||
|
||||
use core::arch::asm;
|
||||
use core::ops::Deref;
|
||||
use core::{fmt, slice, str};
|
||||
|
||||
// 3 calls of 4 registers of 4 bytes
|
||||
const BRAND_STRING_LENGTH: usize = 3 * 4 * 4;
|
||||
|
||||
macro_rules! bit {
|
||||
($reg:ident, {$($idx:expr => $name:ident),+ $(,)?}) => {
|
||||
$(pub fn $name(self) -> bool {
|
||||
((self.$reg >> $idx) & 1) != 0
|
||||
})+
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! dump {
|
||||
($me:expr, $f: expr, $sname:expr, {$($name:ident),+ $(,)?}) => {
|
||||
$f.debug_struct($sname)
|
||||
$(.field(stringify!($name), &$me.$name()))+
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! delegate_flag {
|
||||
($item:ident, {$($name:ident),+ $(,)?}) => {
|
||||
$(pub fn $name(&self) -> bool {
|
||||
self.$item.map(|i| i.$name()).unwrap_or(false)
|
||||
})+
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! master_attr_reader {
|
||||
($name:ident, $kind:ty) => {
|
||||
pub fn $name(&self) -> Option<&$kind> {
|
||||
self.$name.as_ref()
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[repr(u32)]
|
||||
pub enum RequestType {
|
||||
BasicInformation = 0x00000000,
|
||||
VersionInformation = 0x00000001,
|
||||
ThermalPowerManagementInformation = 0x00000006,
|
||||
StructuredExtendedInformation = 0x00000007,
|
||||
ExtendedFunctionInformation = 0x80000000,
|
||||
ExtendedProcessorSignature = 0x80000001,
|
||||
BrandString1 = 0x80000002,
|
||||
BrandString2 = 0x80000003,
|
||||
BrandString3 = 0x80000004,
|
||||
// reserved = 0x80000005,
|
||||
CacheLine = 0x80000006,
|
||||
TimeStampCounter = 0x80000007,
|
||||
PhysicalAddressSize = 0x80000008,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct VersionInformation {
|
||||
eax: u32,
|
||||
ebx: u32,
|
||||
ecx: u32,
|
||||
edx: u32,
|
||||
}
|
||||
|
||||
impl VersionInformation {
|
||||
pub fn new() -> VersionInformation {
|
||||
let (a, b, c, d) = cpuid(RequestType::VersionInformation);
|
||||
VersionInformation {
|
||||
eax: a,
|
||||
ebx: b,
|
||||
ecx: c,
|
||||
edx: d,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn family_id(self) -> u32 {
|
||||
let family_id = bits_of(self.eax, 8, 11);
|
||||
let extended_family_id = bits_of(self.eax, 20, 27);
|
||||
|
||||
if family_id != 0x0F {
|
||||
family_id
|
||||
} else {
|
||||
extended_family_id + family_id
|
||||
}
|
||||
}
|
||||
|
||||
pub fn model_id(self) -> u32 {
|
||||
let family_id = self.family_id();
|
||||
let model_id = bits_of(self.eax, 4, 7);
|
||||
let extended_model_id = bits_of(self.eax, 16, 19);
|
||||
|
||||
if family_id == 0x06 || family_id == 0x0F {
|
||||
(extended_model_id << 4) + model_id
|
||||
} else {
|
||||
model_id
|
||||
}
|
||||
}
|
||||
|
||||
pub fn stepping(self) -> u32 {
|
||||
bits_of(self.eax, 0, 3)
|
||||
}
|
||||
|
||||
fn processor_signature(self) -> u32 {
|
||||
self.eax
|
||||
}
|
||||
|
||||
pub fn brand_string(self) -> Option<&'static str> {
|
||||
let brand_index = bits_of(self.ebx, 0, 7);
|
||||
let processor_signature = self.processor_signature();
|
||||
|
||||
match brand_index {
|
||||
0x00 => None,
|
||||
0x01 => Some("Intel(R) Celeron(R)"),
|
||||
0x02 => Some("Intel(R) Pentium(R) III"),
|
||||
0x03 => {
|
||||
if processor_signature == 0x06B1 {
|
||||
Some("Intel(R) Celeron(R)")
|
||||
} else {
|
||||
Some("Intel(R) Pentium(R) III Xeon(R)")
|
||||
}
|
||||
}
|
||||
0x04 => Some("Intel(R) Pentium(R) III"),
|
||||
0x06 => Some("Mobile Intel(R) Pentium(R) III-M"),
|
||||
0x07 => Some("Mobile Intel(R) Celeron(R)"),
|
||||
0x08 => Some("Intel(R) Pentium(R) 4"),
|
||||
0x09 => Some("Intel(R) Pentium(R) 4"),
|
||||
0x0A => Some("Intel(R) Celeron(R)"),
|
||||
0x0B => {
|
||||
if processor_signature == 0x0F13 {
|
||||
Some("Intel(R) Xeon(R) MP")
|
||||
} else {
|
||||
Some("Intel(R) Xeon(R)")
|
||||
}
|
||||
}
|
||||
0x0C => Some("Intel(R) Xeon(R) MP"),
|
||||
0x0E => {
|
||||
if processor_signature == 0x0F13 {
|
||||
Some("Intel(R) Xeon(R)")
|
||||
} else {
|
||||
Some("Mobile Intel(R) Pentium(R) 4-M")
|
||||
}
|
||||
}
|
||||
0x0F => Some("Mobile Intel(R) Celeron(R)"),
|
||||
0x11 => Some("Mobile Genuine Intel(R)"),
|
||||
0x12 => Some("Intel(R) Celeron(R) M"),
|
||||
0x13 => Some("Mobile Intel(R) Celeron(R)"),
|
||||
0x14 => Some("Intel(R) Celeron(R)"),
|
||||
0x15 => Some("Mobile Genuine Intel(R)"),
|
||||
0x16 => Some("Intel(R) Pentium(R) M"),
|
||||
0x17 => Some("Mobile Intel(R) Celeron(R)"),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
bit!(ecx, {
|
||||
0 => sse3,
|
||||
1 => pclmulqdq,
|
||||
2 => dtes64,
|
||||
3 => monitor,
|
||||
4 => ds_cpl,
|
||||
5 => vmx,
|
||||
6 => smx,
|
||||
7 => eist,
|
||||
8 => tm2,
|
||||
9 => ssse3,
|
||||
10 => cnxt_id,
|
||||
11 => sdbg,
|
||||
12 => fma,
|
||||
13 => cmpxchg16b,
|
||||
14 => xtpr_update_control,
|
||||
15 => pdcm,
|
||||
// 16 - reserved
|
||||
17 => pcid,
|
||||
18 => dca,
|
||||
19 => sse4_1,
|
||||
20 => sse4_2,
|
||||
21 => x2apic,
|
||||
22 => movbe,
|
||||
23 => popcnt,
|
||||
24 => tsc_deadline,
|
||||
25 => aesni,
|
||||
26 => xsave,
|
||||
27 => osxsave,
|
||||
28 => avx,
|
||||
29 => f16c,
|
||||
30 => rdrand,
|
||||
// 31 - unused,
|
||||
});
|
||||
|
||||
bit!(edx, {
|
||||
0 => fpu,
|
||||
1 => vme,
|
||||
2 => de,
|
||||
3 => pse,
|
||||
4 => tsc,
|
||||
5 => msr,
|
||||
6 => pae,
|
||||
7 => mce,
|
||||
8 => cx8,
|
||||
9 => apic,
|
||||
// 10 - reserved
|
||||
11 => sep,
|
||||
12 => mtrr,
|
||||
13 => pge,
|
||||
14 => mca,
|
||||
15 => cmov,
|
||||
16 => pat,
|
||||
17 => pse_36,
|
||||
18 => psn,
|
||||
19 => clfsh,
|
||||
// 20 - reserved
|
||||
21 => ds,
|
||||
22 => acpi,
|
||||
23 => mmx,
|
||||
24 => fxsr,
|
||||
25 => sse,
|
||||
26 => sse2,
|
||||
27 => ss,
|
||||
28 => htt,
|
||||
29 => tm,
|
||||
// 30 -reserved
|
||||
31 => pbe,
|
||||
});
|
||||
}
|
||||
|
||||
impl Default for VersionInformation {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for VersionInformation {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
dump!(self, f, "VersionInformation", {
|
||||
family_id,
|
||||
model_id,
|
||||
stepping,
|
||||
brand_string,
|
||||
sse3,
|
||||
pclmulqdq,
|
||||
dtes64,
|
||||
monitor,
|
||||
ds_cpl,
|
||||
vmx,
|
||||
smx,
|
||||
eist,
|
||||
tm2,
|
||||
ssse3,
|
||||
cnxt_id,
|
||||
sdbg,
|
||||
fma,
|
||||
cmpxchg16b,
|
||||
xtpr_update_control,
|
||||
pdcm,
|
||||
pcid,
|
||||
dca,
|
||||
sse4_1,
|
||||
sse4_2,
|
||||
x2apic,
|
||||
movbe,
|
||||
popcnt,
|
||||
tsc_deadline,
|
||||
aesni,
|
||||
xsave,
|
||||
osxsave,
|
||||
avx,
|
||||
f16c,
|
||||
rdrand,
|
||||
fpu,
|
||||
vme,
|
||||
de,
|
||||
pse,
|
||||
tsc,
|
||||
msr,
|
||||
pae,
|
||||
mce,
|
||||
cx8,
|
||||
apic,
|
||||
sep,
|
||||
mtrr,
|
||||
pge,
|
||||
mca,
|
||||
cmov,
|
||||
pat,
|
||||
pse_36,
|
||||
psn,
|
||||
clfsh,
|
||||
ds,
|
||||
acpi,
|
||||
mmx,
|
||||
fxsr,
|
||||
sse,
|
||||
sse2,
|
||||
ss,
|
||||
htt,
|
||||
tm,
|
||||
pbe,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct ExtendedProcessorSignature {
|
||||
ecx: u32,
|
||||
edx: u32,
|
||||
}
|
||||
|
||||
impl ExtendedProcessorSignature {
|
||||
fn new() -> ExtendedProcessorSignature {
|
||||
let (_, _, c, d) = cpuid(RequestType::ExtendedProcessorSignature);
|
||||
ExtendedProcessorSignature { ecx: c, edx: d }
|
||||
}
|
||||
|
||||
bit!(ecx, {
|
||||
0 => lahf_sahf_in_64_bit,
|
||||
// 1-4 reserved
|
||||
5 => lzcnt,
|
||||
// 6-7 reserved
|
||||
8 => prefetchw,
|
||||
// 9-31 reserved
|
||||
});
|
||||
|
||||
bit!(edx, {
|
||||
// 0-10 reserved
|
||||
11 => syscall_sysret_in_64_bit,
|
||||
// 12-19 reserved
|
||||
20 => execute_disable,
|
||||
// 21-25 reserved
|
||||
26 => gigabyte_pages,
|
||||
27 => rdtscp_and_ia32_tsc_aux,
|
||||
// 28 reserved
|
||||
29 => intel_64_bit_architecture,
|
||||
// 30-31 reserved
|
||||
});
|
||||
}
|
||||
|
||||
impl fmt::Debug for ExtendedProcessorSignature {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
dump!(self, f, "ThermalPowerManagementInformation", {
|
||||
lahf_sahf_in_64_bit,
|
||||
lzcnt,
|
||||
prefetchw,
|
||||
syscall_sysret_in_64_bit,
|
||||
execute_disable,
|
||||
gigabyte_pages,
|
||||
rdtscp_and_ia32_tsc_aux,
|
||||
intel_64_bit_architecture,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub struct BrandString {
|
||||
bytes: [u8; BRAND_STRING_LENGTH],
|
||||
}
|
||||
|
||||
impl BrandString {
|
||||
fn new() -> BrandString {
|
||||
fn append_bytes(a: RequestType, bytes: &mut [u8]) {
|
||||
let (a, b, c, d) = cpuid(a);
|
||||
|
||||
let result_bytes = as_bytes(&a)
|
||||
.iter()
|
||||
.chain(as_bytes(&b).iter())
|
||||
.chain(as_bytes(&c).iter())
|
||||
.chain(as_bytes(&d).iter());
|
||||
|
||||
for (output, input) in bytes.iter_mut().zip(result_bytes) {
|
||||
*output = *input
|
||||
}
|
||||
}
|
||||
|
||||
let mut brand_string = BrandString {
|
||||
bytes: [0; BRAND_STRING_LENGTH],
|
||||
};
|
||||
append_bytes(RequestType::BrandString1, &mut brand_string.bytes[0..]);
|
||||
append_bytes(RequestType::BrandString2, &mut brand_string.bytes[16..]);
|
||||
append_bytes(RequestType::BrandString3, &mut brand_string.bytes[32..]);
|
||||
brand_string
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for BrandString {
|
||||
fn clone(&self) -> Self {
|
||||
let mut bytes = [0; BRAND_STRING_LENGTH];
|
||||
for (d, s) in bytes.iter_mut().zip(self.bytes.iter()) {
|
||||
*d = *s;
|
||||
}
|
||||
BrandString { bytes }
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for BrandString {
|
||||
type Target = str;
|
||||
|
||||
fn deref(&self) -> &str {
|
||||
let nul_terminator = self.bytes.iter().position(|&b| b == 0).unwrap_or(0);
|
||||
let usable_bytes = &self.bytes[..nul_terminator];
|
||||
unsafe { str::from_utf8_unchecked(usable_bytes) }.trim()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for BrandString {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
(self as &str).fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for BrandString {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
(self as &str).fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct ThermalPowerManagementInformation {
|
||||
eax: u32,
|
||||
ebx: u32,
|
||||
ecx: u32,
|
||||
}
|
||||
|
||||
impl ThermalPowerManagementInformation {
|
||||
fn new() -> ThermalPowerManagementInformation {
|
||||
let (a, b, c, _) = cpuid(RequestType::ThermalPowerManagementInformation);
|
||||
ThermalPowerManagementInformation {
|
||||
eax: a,
|
||||
ebx: b,
|
||||
ecx: c,
|
||||
}
|
||||
}
|
||||
|
||||
bit!(eax, {
|
||||
0 => digital_temperature_sensor,
|
||||
1 => intel_turbo_boost,
|
||||
2 => arat,
|
||||
// 3 - reserved
|
||||
4 => pln,
|
||||
5 => ecmd,
|
||||
6 => ptm,
|
||||
7 => hwp,
|
||||
8 => hwp_notification,
|
||||
9 => hwp_activity_window,
|
||||
10 => hwp_energy_performance_preference,
|
||||
// 12 - reserved
|
||||
13 => hdc,
|
||||
});
|
||||
|
||||
pub fn number_of_interrupt_thresholds(self) -> u32 {
|
||||
bits_of(self.ebx, 0, 3)
|
||||
}
|
||||
|
||||
bit!(ecx, {
|
||||
0 => hardware_coordination_feedback,
|
||||
// 1-2 - reserved
|
||||
3 => performance_energy_bias
|
||||
});
|
||||
}
|
||||
|
||||
impl fmt::Debug for ThermalPowerManagementInformation {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
dump!(self, f, "ThermalPowerManagementInformation", {
|
||||
digital_temperature_sensor,
|
||||
intel_turbo_boost,
|
||||
arat,
|
||||
pln,
|
||||
ecmd,
|
||||
ptm,
|
||||
hwp,
|
||||
hwp_notification,
|
||||
hwp_activity_window,
|
||||
hwp_energy_performance_preference,
|
||||
hdc,
|
||||
number_of_interrupt_thresholds,
|
||||
hardware_coordination_feedback,
|
||||
performance_energy_bias
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct StructuredExtendedInformation {
|
||||
ebx: u32,
|
||||
ecx: u32,
|
||||
}
|
||||
|
||||
impl StructuredExtendedInformation {
|
||||
fn new() -> StructuredExtendedInformation {
|
||||
let (_, b, c, _) = cpuid(RequestType::StructuredExtendedInformation);
|
||||
StructuredExtendedInformation { ebx: b, ecx: c }
|
||||
}
|
||||
|
||||
bit!(ebx, {
|
||||
0 => fsgsbase,
|
||||
1 => ia32_tsc_adjust_msr,
|
||||
// 2 - reserved
|
||||
3 => bmi1,
|
||||
4 => hle,
|
||||
5 => avx2,
|
||||
// 6 - reserved
|
||||
7 => smep,
|
||||
8 => bmi2,
|
||||
9 => enhanced_rep_movsb_stosb,
|
||||
10 => invpcid,
|
||||
11 => rtm,
|
||||
12 => pqm,
|
||||
13 => deprecates_fpu_cs_ds,
|
||||
// 14 - reserved
|
||||
15 => pqe,
|
||||
// 16-17 - reserved
|
||||
18 => rdseed,
|
||||
19 => adx,
|
||||
20 => smap,
|
||||
// 21-24 - reserved
|
||||
25 => intel_processor_trace,
|
||||
// 26-31 - reserved
|
||||
});
|
||||
|
||||
bit!(ecx, {
|
||||
0 => prefetchwt1
|
||||
});
|
||||
}
|
||||
|
||||
impl fmt::Debug for StructuredExtendedInformation {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
dump!(self, f, "StructuredExtendedInformation", {
|
||||
fsgsbase,
|
||||
ia32_tsc_adjust_msr,
|
||||
bmi1,
|
||||
hle,
|
||||
avx2,
|
||||
smep,
|
||||
bmi2,
|
||||
enhanced_rep_movsb_stosb,
|
||||
invpcid,
|
||||
rtm,
|
||||
pqm,
|
||||
deprecates_fpu_cs_ds,
|
||||
pqe,
|
||||
rdseed,
|
||||
adx,
|
||||
smap,
|
||||
intel_processor_trace,
|
||||
prefetchwt1,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub enum CacheLineAssociativity {
|
||||
Disabled,
|
||||
DirectMapped,
|
||||
TwoWay,
|
||||
FourWay,
|
||||
EightWay,
|
||||
SixteenWay,
|
||||
Full,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct CacheLine(u32);
|
||||
impl CacheLine {
|
||||
fn new() -> CacheLine {
|
||||
let (_, _, c, _) = cpuid(RequestType::CacheLine);
|
||||
CacheLine(c)
|
||||
}
|
||||
|
||||
pub fn cache_line_size(self) -> u32 {
|
||||
bits_of(self.0, 0, 7)
|
||||
}
|
||||
|
||||
pub fn l2_associativity(self) -> Option<CacheLineAssociativity> {
|
||||
match bits_of(self.0, 12, 15) {
|
||||
0x00 => Some(CacheLineAssociativity::Disabled),
|
||||
0x01 => Some(CacheLineAssociativity::DirectMapped),
|
||||
0x02 => Some(CacheLineAssociativity::TwoWay),
|
||||
0x04 => Some(CacheLineAssociativity::FourWay),
|
||||
0x06 => Some(CacheLineAssociativity::EightWay),
|
||||
0x08 => Some(CacheLineAssociativity::SixteenWay),
|
||||
0x0F => Some(CacheLineAssociativity::Full),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cache_size(self) -> u32 {
|
||||
bits_of(self.0, 16, 31)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for CacheLine {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
dump!(self, f, "CacheLine", {
|
||||
cache_line_size,
|
||||
l2_associativity,
|
||||
cache_size
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct TimeStampCounter {
|
||||
edx: u32,
|
||||
}
|
||||
|
||||
impl TimeStampCounter {
|
||||
fn new() -> TimeStampCounter {
|
||||
let (_, _, _, d) = cpuid(RequestType::TimeStampCounter);
|
||||
TimeStampCounter { edx: d }
|
||||
}
|
||||
|
||||
bit!(edx, {
|
||||
// 0-7 - reserved
|
||||
8 => invariant_tsc
|
||||
// 9-31 - reserved
|
||||
});
|
||||
}
|
||||
|
||||
impl fmt::Debug for TimeStampCounter {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
dump!(self, f, "TimeStampCounter", { invariant_tsc })
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct PhysicalAddressSize(u32);
|
||||
impl PhysicalAddressSize {
|
||||
fn new() -> PhysicalAddressSize {
|
||||
let (a, _, _, _) = cpuid(RequestType::PhysicalAddressSize);
|
||||
PhysicalAddressSize(a)
|
||||
}
|
||||
|
||||
pub fn physical_address_bits(self) -> u32 {
|
||||
bits_of(self.0, 0, 7)
|
||||
}
|
||||
|
||||
pub fn linear_address_bits(self) -> u32 {
|
||||
bits_of(self.0, 8, 15)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for PhysicalAddressSize {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
dump!(self, f, "PhysicalAddressSize", {
|
||||
physical_address_bits,
|
||||
linear_address_bits
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Information about the currently running processor
|
||||
///
|
||||
/// Feature flags match the feature mnemonic listed in the Intel
|
||||
/// Instruction Set Reference. This struct provides a facade for flags
|
||||
/// so the consumer doesn't need to worry about which particular CPUID
|
||||
/// leaf provides the information.
|
||||
///
|
||||
/// For data beyond simple feature flags, you will need to retrieve
|
||||
/// the nested struct and call the appropriate methods on it.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Master {
|
||||
// TODO: Rename struct
|
||||
version_information: Option<VersionInformation>,
|
||||
thermal_power_management_information: Option<ThermalPowerManagementInformation>,
|
||||
structured_extended_information: Option<StructuredExtendedInformation>,
|
||||
extended_processor_signature: Option<ExtendedProcessorSignature>,
|
||||
brand_string: Option<BrandString>,
|
||||
cache_line: Option<CacheLine>,
|
||||
time_stamp_counter: Option<TimeStampCounter>,
|
||||
physical_address_size: Option<PhysicalAddressSize>,
|
||||
}
|
||||
|
||||
impl Master {
|
||||
pub fn new() -> Master {
|
||||
fn when_supported<F, T>(max: u32, kind: RequestType, then: F) -> Option<T>
|
||||
where
|
||||
F: FnOnce() -> T,
|
||||
{
|
||||
if max >= kind as u32 {
|
||||
Some(then())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
let (max_value, _, _, _) = cpuid(RequestType::BasicInformation);
|
||||
|
||||
let vi = when_supported(max_value, RequestType::VersionInformation, || {
|
||||
VersionInformation::new()
|
||||
});
|
||||
let tpm = when_supported(
|
||||
max_value,
|
||||
RequestType::ThermalPowerManagementInformation,
|
||||
ThermalPowerManagementInformation::new,
|
||||
);
|
||||
let sei = when_supported(
|
||||
max_value,
|
||||
RequestType::StructuredExtendedInformation,
|
||||
StructuredExtendedInformation::new,
|
||||
);
|
||||
|
||||
// Extended information
|
||||
|
||||
let (max_value, _, _, _) = cpuid(RequestType::ExtendedFunctionInformation);
|
||||
|
||||
let eps = when_supported(max_value, RequestType::ExtendedProcessorSignature, || {
|
||||
ExtendedProcessorSignature::new()
|
||||
});
|
||||
let brand_string = when_supported(max_value, RequestType::BrandString3, BrandString::new);
|
||||
let cache_line = when_supported(max_value, RequestType::CacheLine, CacheLine::new);
|
||||
let tsc = when_supported(max_value, RequestType::TimeStampCounter, || {
|
||||
TimeStampCounter::new()
|
||||
});
|
||||
let pas = when_supported(max_value, RequestType::PhysicalAddressSize, || {
|
||||
PhysicalAddressSize::new()
|
||||
});
|
||||
|
||||
Master {
|
||||
version_information: vi,
|
||||
thermal_power_management_information: tpm,
|
||||
structured_extended_information: sei,
|
||||
extended_processor_signature: eps,
|
||||
brand_string,
|
||||
cache_line,
|
||||
time_stamp_counter: tsc,
|
||||
physical_address_size: pas,
|
||||
}
|
||||
}
|
||||
|
||||
master_attr_reader!(version_information, VersionInformation);
|
||||
master_attr_reader!(
|
||||
thermal_power_management_information,
|
||||
ThermalPowerManagementInformation
|
||||
);
|
||||
master_attr_reader!(
|
||||
structured_extended_information,
|
||||
StructuredExtendedInformation
|
||||
);
|
||||
master_attr_reader!(extended_processor_signature, ExtendedProcessorSignature);
|
||||
master_attr_reader!(cache_line, CacheLine);
|
||||
master_attr_reader!(time_stamp_counter, TimeStampCounter);
|
||||
master_attr_reader!(physical_address_size, PhysicalAddressSize);
|
||||
|
||||
pub fn brand_string(&self) -> Option<&str> {
|
||||
self.brand_string
|
||||
.as_ref()
|
||||
.map(|bs| bs as &str)
|
||||
.or_else(|| self.version_information.and_then(|vi| vi.brand_string()))
|
||||
}
|
||||
|
||||
delegate_flag!(version_information, {
|
||||
sse3,
|
||||
pclmulqdq,
|
||||
dtes64,
|
||||
monitor,
|
||||
ds_cpl,
|
||||
vmx,
|
||||
smx,
|
||||
eist,
|
||||
tm2,
|
||||
ssse3,
|
||||
cnxt_id,
|
||||
sdbg,
|
||||
fma,
|
||||
cmpxchg16b,
|
||||
xtpr_update_control,
|
||||
pdcm,
|
||||
pcid,
|
||||
dca,
|
||||
sse4_1,
|
||||
sse4_2,
|
||||
x2apic,
|
||||
movbe,
|
||||
popcnt,
|
||||
tsc_deadline,
|
||||
aesni,
|
||||
xsave,
|
||||
osxsave,
|
||||
avx,
|
||||
f16c,
|
||||
rdrand,
|
||||
fpu,
|
||||
vme,
|
||||
de,
|
||||
pse,
|
||||
tsc,
|
||||
msr,
|
||||
pae,
|
||||
mce,
|
||||
cx8,
|
||||
apic,
|
||||
sep,
|
||||
mtrr,
|
||||
pge,
|
||||
mca,
|
||||
cmov,
|
||||
pat,
|
||||
pse_36,
|
||||
psn,
|
||||
clfsh,
|
||||
ds,
|
||||
acpi,
|
||||
mmx,
|
||||
fxsr,
|
||||
sse,
|
||||
sse2,
|
||||
ss,
|
||||
htt,
|
||||
tm,
|
||||
pbe,
|
||||
});
|
||||
|
||||
delegate_flag!(thermal_power_management_information, {
|
||||
digital_temperature_sensor,
|
||||
intel_turbo_boost,
|
||||
arat,
|
||||
pln,
|
||||
ecmd,
|
||||
ptm,
|
||||
hwp,
|
||||
hwp_notification,
|
||||
hwp_activity_window,
|
||||
hwp_energy_performance_preference,
|
||||
hdc,
|
||||
hardware_coordination_feedback,
|
||||
performance_energy_bias,
|
||||
});
|
||||
|
||||
delegate_flag!(structured_extended_information, {
|
||||
fsgsbase,
|
||||
ia32_tsc_adjust_msr,
|
||||
bmi1,
|
||||
hle,
|
||||
avx2,
|
||||
smep,
|
||||
bmi2,
|
||||
enhanced_rep_movsb_stosb,
|
||||
invpcid,
|
||||
rtm,
|
||||
pqm,
|
||||
deprecates_fpu_cs_ds,
|
||||
pqe,
|
||||
rdseed,
|
||||
adx,
|
||||
smap,
|
||||
intel_processor_trace,
|
||||
prefetchwt1
|
||||
});
|
||||
|
||||
delegate_flag!(extended_processor_signature, {
|
||||
lahf_sahf_in_64_bit,
|
||||
lzcnt,
|
||||
prefetchw,
|
||||
syscall_sysret_in_64_bit,
|
||||
execute_disable,
|
||||
gigabyte_pages,
|
||||
rdtscp_and_ia32_tsc_aux,
|
||||
intel_64_bit_architecture,
|
||||
});
|
||||
|
||||
delegate_flag!(time_stamp_counter, { invariant_tsc });
|
||||
}
|
||||
|
||||
impl Default for Master {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
/// The main entrypoint to the CPU information
|
||||
#[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
|
||||
pub fn master() -> Option<Master> {
|
||||
Some(Master::new())
|
||||
}
|
||||
|
||||
pub fn sysinfo() {}
|
||||
|
||||
pub fn as_bytes(v: &u32) -> &[u8] {
|
||||
let start = v as *const u32 as *const u8;
|
||||
// TODO: use u32::BYTES
|
||||
unsafe { slice::from_raw_parts(start, 4) }
|
||||
}
|
||||
|
||||
pub fn cpuid(code: RequestType) -> (u32, u32, u32, u32) {
|
||||
let eax;
|
||||
let ebx;
|
||||
let ecx;
|
||||
let edx;
|
||||
|
||||
unsafe {
|
||||
asm!(
|
||||
"movq %rbx, {0:r}",
|
||||
"cpuid",
|
||||
"xchgq %rbx, {0:r}",
|
||||
lateout(reg) ebx,
|
||||
inlateout("eax") code as u32 => eax,
|
||||
inlateout("ecx") 0 => ecx,
|
||||
lateout("edx") edx,
|
||||
options(nostack, preserves_flags, att_syntax),
|
||||
);
|
||||
}
|
||||
|
||||
(eax, ebx, ecx, edx)
|
||||
}
|
||||
|
||||
// This matches the Intel Architecture guide, with bits 31 -> 0.
|
||||
// The bit positions are inclusive.
|
||||
fn bits_of(val: u32, start_bit: u8, end_bit: u8) -> u32 {
|
||||
let mut silly = 0;
|
||||
for _ in start_bit..end_bit + 1 {
|
||||
silly <<= 1;
|
||||
silly |= 1;
|
||||
}
|
||||
|
||||
(val >> start_bit) & silly
|
||||
}
|
||||
|
||||
/*
|
||||
cfg_if! {
|
||||
if #[cfg(any(target_arch = "x86_64", target_arch = "x86"))] {
|
||||
|
||||
#[test]
|
||||
fn basic_genuine_intel() {
|
||||
let (_, b, c, d) = cpuid(RequestType::BasicInformation);
|
||||
|
||||
assert_eq!(b"Genu", as_bytes(&b));
|
||||
assert_eq!(b"ntel", as_bytes(&c));
|
||||
assert_eq!(b"ineI", as_bytes(&d));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn brand_string_contains_intel() {
|
||||
assert!(master().unwrap().brand_string().unwrap().contains("Intel(R)"))
|
||||
}
|
||||
|
||||
} else {}
|
||||
}
|
||||
*/
|
|
@ -1,2 +0,0 @@
|
|||
/// This magic value is the herts of the timer interupts normalized
|
||||
pub const TIMER_INTERRUPT_HERTZ: f64 = 1193182.0;
|
|
@ -1 +0,0 @@
|
|||
|
|
@ -1,48 +0,0 @@
|
|||
use spin::Lazy;
|
||||
use x86_64::structures::gdt::{Descriptor, GlobalDescriptorTable, SegmentSelector};
|
||||
use x86_64::structures::tss::TaskStateSegment;
|
||||
use x86_64::VirtAddr;
|
||||
|
||||
pub const DOUBLE_FAULT_IST_INDEX: u16 = 0;
|
||||
|
||||
struct Selectors {
|
||||
code_selector: SegmentSelector,
|
||||
tss_selector: SegmentSelector,
|
||||
}
|
||||
|
||||
static TSS: Lazy<TaskStateSegment> = Lazy::new(|| {
|
||||
let mut tss = TaskStateSegment::new();
|
||||
tss.interrupt_stack_table[DOUBLE_FAULT_IST_INDEX as usize] = {
|
||||
const STACK_SIZE: usize = 4096 * 5;
|
||||
static mut STACK: [u8; STACK_SIZE] = [0; STACK_SIZE];
|
||||
|
||||
let stack_start = VirtAddr::from_ptr(unsafe { &STACK });
|
||||
stack_start + STACK_SIZE
|
||||
};
|
||||
tss
|
||||
});
|
||||
|
||||
static GDT: Lazy<(GlobalDescriptorTable, Selectors)> = Lazy::new(|| {
|
||||
let mut gdt = GlobalDescriptorTable::new();
|
||||
let code_selector = gdt.add_entry(Descriptor::kernel_code_segment());
|
||||
let tss_selector = gdt.add_entry(Descriptor::tss_segment(&TSS));
|
||||
(
|
||||
gdt,
|
||||
Selectors {
|
||||
code_selector,
|
||||
tss_selector,
|
||||
},
|
||||
)
|
||||
});
|
||||
|
||||
pub fn init() {
|
||||
use x86_64::instructions::segmentation::{Segment, CS};
|
||||
use x86_64::instructions::tables::load_tss;
|
||||
|
||||
log::debug!("Initialising GDT");
|
||||
GDT.0.load();
|
||||
unsafe {
|
||||
CS::set_reg(GDT.1.code_selector);
|
||||
load_tss(GDT.1.tss_selector);
|
||||
}
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
// #![allow(clippy::print_literal)]
|
||||
use super::{gdt, interrupts};
|
||||
// use crate::{logger, serial_println, TERM};
|
||||
use crate::{logger, serial_println};
|
||||
|
||||
/// x86_64 initialization
|
||||
pub fn init() {
|
||||
// use crate::{network::socket::SimpleSock, relib::network::socket::Socket};
|
||||
|
||||
// let mut log_socket_id = SimpleSock::new();
|
||||
// log_socket_id.register_protocol("Logger".to_string());
|
||||
|
||||
let result = logger::init();
|
||||
match result {
|
||||
Ok(_) => {
|
||||
info!("Logger initialized");
|
||||
}
|
||||
Err(err) => serial_println!("{}", err),
|
||||
}
|
||||
|
||||
trace!("gdt");
|
||||
gdt::init();
|
||||
|
||||
trace!("idt");
|
||||
interrupts::init_idt();
|
||||
unsafe { interrupts::PICS.lock().initialize() };
|
||||
|
||||
// trace!("term");
|
||||
// let term = &*TERM;
|
||||
// trace!("term.lock()");
|
||||
// let mut term = term.lock();
|
||||
// term.initialize();
|
||||
// term.set_dirty(true);
|
||||
// term.draw_term();
|
||||
// drop(term);
|
||||
|
||||
x86_64::instructions::interrupts::enable();
|
||||
}
|
|
@ -1,285 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2022, able <abl3theabove@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
use core::panic::PanicInfo;
|
||||
|
||||
use crate::{arch::gdt, println, rhai_shell::KEYBUFF};
|
||||
use cpuio::outb;
|
||||
use pic8259::ChainedPics;
|
||||
use qrcode::QrCode;
|
||||
use seq_macro::seq;
|
||||
use spin::Lazy;
|
||||
use x86_64::{
|
||||
registers::control::Cr2,
|
||||
structures::idt::{InterruptDescriptorTable, InterruptStackFrame, PageFaultErrorCode},
|
||||
};
|
||||
|
||||
use super::sloop;
|
||||
|
||||
pub const PIC_1_OFFSET: u8 = 32;
|
||||
pub const PIC_2_OFFSET: u8 = PIC_1_OFFSET + 8;
|
||||
|
||||
pub static PICS: spin::Mutex<ChainedPics> =
|
||||
spin::Mutex::new(unsafe { ChainedPics::new(PIC_1_OFFSET, PIC_2_OFFSET) });
|
||||
|
||||
/// Interrupt offsets.
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[repr(u8)]
|
||||
pub enum InterruptIndex {
|
||||
Timer = PIC_1_OFFSET,
|
||||
Keyboard,
|
||||
/// Mouse offset
|
||||
Mouse = 44,
|
||||
|
||||
/// Disk offset
|
||||
Disk = 46,
|
||||
|
||||
// SecondInterrupt = PIC_2_OFFSET,
|
||||
Cmos = 0x70,
|
||||
}
|
||||
|
||||
impl InterruptIndex {
|
||||
fn as_u8(self) -> u8 {
|
||||
self as u8
|
||||
}
|
||||
fn as_usize(self) -> usize {
|
||||
usize::from(self.as_u8())
|
||||
}
|
||||
}
|
||||
|
||||
static IDT: Lazy<InterruptDescriptorTable> = Lazy::new(|| {
|
||||
reset_pit_for_cpu();
|
||||
let mut idt = InterruptDescriptorTable::new();
|
||||
|
||||
seq!(N in 32..=255 {
|
||||
idt[N].set_handler_fn(undefined_handler_~N);
|
||||
});
|
||||
|
||||
idt.breakpoint.set_handler_fn(breakpoint_handler);
|
||||
idt.page_fault.set_handler_fn(page_fault_handler);
|
||||
unsafe {
|
||||
idt.double_fault
|
||||
.set_handler_fn(double_fault_handler)
|
||||
.set_stack_index(gdt::DOUBLE_FAULT_IST_INDEX);
|
||||
}
|
||||
|
||||
idt[InterruptIndex::Timer.as_usize()].set_handler_fn(timer_interrupt_handler);
|
||||
idt[InterruptIndex::Keyboard.as_usize()].set_handler_fn(keyboard_interrupt_handler);
|
||||
idt[InterruptIndex::Mouse.as_usize()].set_handler_fn(crate::hardware::mouse_interrupt_handler);
|
||||
|
||||
// run `a + b + l + e + o + s print;` in ablescript and its 54 thats why this seemingly arbitrary number was chosen
|
||||
idt[54].set_handler_fn(software_int_handler);
|
||||
|
||||
idt
|
||||
});
|
||||
|
||||
seq!(N in 32..=255 {
|
||||
extern "x86-interrupt" fn undefined_handler_~N(stack_frame: InterruptStackFrame) {
|
||||
error!("INT {}: {:?}", N, stack_frame);
|
||||
unsafe {
|
||||
PICS.lock()
|
||||
.notify_end_of_interrupt(N);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
extern "x86-interrupt" fn software_int_handler(stack_frame: InterruptStackFrame) {
|
||||
trace!("EXCEPTION: SOFTWARE INT\n{:#?}", stack_frame);
|
||||
unsafe {
|
||||
PICS.lock().notify_end_of_interrupt(54);
|
||||
}
|
||||
}
|
||||
|
||||
extern "x86-interrupt" fn breakpoint_handler(stack_frame: InterruptStackFrame) {
|
||||
trace!("EXCEPTION: BREAKPOINT\n{:#?}", stack_frame);
|
||||
}
|
||||
|
||||
extern "x86-interrupt" fn page_fault_handler(
|
||||
stack_frame: InterruptStackFrame,
|
||||
error_code: PageFaultErrorCode,
|
||||
) {
|
||||
error!("EXCEPTION: PAGE FAULT {error_code:?}\n{:#?}", stack_frame);
|
||||
trace!("CR2: {:x}", Cr2::read_raw());
|
||||
trace!("SCREE");
|
||||
loop {}
|
||||
}
|
||||
|
||||
extern "x86-interrupt" fn double_fault_handler(
|
||||
stack_frame: InterruptStackFrame,
|
||||
// NOTE(able): ignore this always is 0
|
||||
_error_code: u64,
|
||||
) -> ! {
|
||||
// bsod(BSODSource::DoubleFault(&stack_frame));
|
||||
panic!("EXCEPTION: DOUBLE FAULT\n{:#?}", stack_frame);
|
||||
}
|
||||
|
||||
/* SAFETY
|
||||
* DO NOT TOUCH
|
||||
* The `#[naked]` macro removes various error/bounds checks that
|
||||
* the Rust compiler would normally add.
|
||||
* *Early return* and *enabling interrupts* in this function are
|
||||
* undefined behavior.
|
||||
* As long as nothing in this function does something that would
|
||||
* normally trigger an error, this function is relatively safe.
|
||||
*/
|
||||
extern "x86-interrupt" fn timer_interrupt_handler(_stack_frame: InterruptStackFrame) {
|
||||
crate::kmain::tick();
|
||||
unsafe {
|
||||
PICS.lock()
|
||||
.notify_end_of_interrupt(InterruptIndex::Timer.as_u8());
|
||||
}
|
||||
}
|
||||
|
||||
extern "x86-interrupt" fn keyboard_interrupt_handler(_stack_frame: InterruptStackFrame) {
|
||||
use pc_keyboard::{
|
||||
layouts::Us104Key, DecodedKey, HandleControl, KeyCode, Keyboard, ScancodeSet1,
|
||||
};
|
||||
use spin::Mutex;
|
||||
use x86_64::instructions::port::Port;
|
||||
|
||||
static KEYBOARD: Lazy<Mutex<Keyboard<Us104Key, ScancodeSet1>>> =
|
||||
Lazy::new(|| Mutex::new(Keyboard::new(Us104Key, ScancodeSet1, HandleControl::Ignore)));
|
||||
|
||||
let mut keyboard = KEYBOARD.lock();
|
||||
if let Ok(Some(key)) = keyboard
|
||||
.add_byte(unsafe { Port::new(0x60).read() })
|
||||
.map(|x| x.and_then(|ev| keyboard.process_keyevent(ev)))
|
||||
{
|
||||
// trace!("{key:?}");
|
||||
match key {
|
||||
DecodedKey::Unicode(chr) => match chr {
|
||||
'\n' => {
|
||||
KEYBUFF.lock().push('\n');
|
||||
}
|
||||
// Backspace
|
||||
'\u{8}' => {
|
||||
// TODO: Fix this and apply to new term
|
||||
|
||||
KEYBUFF.lock().push(8.into());
|
||||
// trace!("8");
|
||||
// print!("\u{8}");
|
||||
}
|
||||
// '^' => KERNEL_STATE.lock().shutdown(),
|
||||
chr => {
|
||||
KEYBUFF.lock().push(chr);
|
||||
// trace!("{chr}");
|
||||
// print!("{chr}");
|
||||
}
|
||||
},
|
||||
DecodedKey::RawKey(key) => {
|
||||
use KeyCode::*;
|
||||
match KeyCode::from(key) {
|
||||
AltLeft | AltRight => (),
|
||||
ArrowDown | ArrowRight | ArrowLeft | ArrowUp => {
|
||||
// warn!("ArrowKeys are unsupported currently");
|
||||
}
|
||||
|
||||
_kc => {
|
||||
// trace!("Unprintable key: {kc:?}"),
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe {
|
||||
PICS.lock()
|
||||
.notify_end_of_interrupt(InterruptIndex::Keyboard.as_u8());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init_idt() {
|
||||
IDT.load();
|
||||
}
|
||||
|
||||
/// https://wiki.osdev.org/Pit
|
||||
///
|
||||
const PIT_MAX_FREQ: u32 = 1193182;
|
||||
|
||||
pub fn set_pit_frequency(pit: u16, freq: u32) {
|
||||
// Dividing the maximum frequency by the desired frequency
|
||||
// gives roughly what the maximum value for the timer
|
||||
// counter should be to run at the desired frequency.
|
||||
let ret = (PIT_MAX_FREQ / freq).try_into();
|
||||
|
||||
// Type-bounded counter maximum.
|
||||
let divisor: u16 = match ret {
|
||||
Ok(div) => div,
|
||||
Err(err) => {
|
||||
error!("{}", err);
|
||||
|
||||
warn!("Defaulting to 1000 on PIT{}", pit);
|
||||
1000
|
||||
}
|
||||
};
|
||||
|
||||
unsafe {
|
||||
outb(0x36, 0x43);
|
||||
|
||||
outb((divisor & 0xFF) as u8, 0x39 + pit);
|
||||
outb((divisor >> 8) as u8, 0x40 + pit);
|
||||
}
|
||||
}
|
||||
pub fn set_pit_1(freq: u32) {
|
||||
set_pit_frequency(1, freq);
|
||||
}
|
||||
pub fn set_pit_2(freq: u32) {
|
||||
set_pit_frequency(2, freq);
|
||||
}
|
||||
|
||||
pub fn set_pit_3(freq: u32) {
|
||||
set_pit_frequency(3, freq);
|
||||
}
|
||||
|
||||
pub fn reset_pit_for_cpu() {
|
||||
set_pit_1(1000);
|
||||
set_pit_2(1000);
|
||||
set_pit_3(1000);
|
||||
}
|
||||
pub fn bsod(src: BSODSource) -> ! {
|
||||
let src1 = match src {
|
||||
BSODSource::DoubleFault(_) => "DoubleFault".to_string(),
|
||||
BSODSource::Panic(panic_info) => {
|
||||
let strr = format!("PANIC: {}", panic_info);
|
||||
strr
|
||||
}
|
||||
};
|
||||
|
||||
let st = format!(
|
||||
"We fucked up ඞ : \n{}\nThe following qr code will link you to the wiki which hopefully solves your problems",
|
||||
src1
|
||||
);
|
||||
|
||||
println!("\n{}", st);
|
||||
|
||||
// let sf = format!("https://git.ablecorp.us/able/ableos/wiki/Double-Faults");
|
||||
|
||||
let sd = match src {
|
||||
BSODSource::DoubleFault(_) => "https://git.ablecorp.us/able/ableos/wiki/Double-Faults",
|
||||
BSODSource::Panic(_) => {
|
||||
trace!("panic");
|
||||
"https://git.ablecorp.us/able/ableos/wiki/Panic"
|
||||
}
|
||||
};
|
||||
|
||||
let code = QrCode::new(sd).unwrap();
|
||||
|
||||
let image = code
|
||||
.render::<char>()
|
||||
.quiet_zone(false)
|
||||
.module_dimensions(2, 1)
|
||||
.build();
|
||||
|
||||
println!("{}", image);
|
||||
|
||||
sloop();
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum BSODSource<'a> {
|
||||
DoubleFault(&'a InterruptStackFrame),
|
||||
Panic(&'a PanicInfo<'a>),
|
||||
}
|
|
@ -1,62 +0,0 @@
|
|||
use limine::{LimineMemmapResponse, LimineMemoryMapEntryType};
|
||||
use x86_64::{
|
||||
structures::paging::{
|
||||
FrameAllocator, FrameDeallocator, OffsetPageTable, PageTable, PhysFrame,
|
||||
Size4KiB,
|
||||
},
|
||||
PhysAddr, VirtAddr,
|
||||
};
|
||||
|
||||
pub unsafe fn init(physical_memory_offset: VirtAddr) -> OffsetPageTable<'static> {
|
||||
let level_4_table = active_level_4_table(physical_memory_offset);
|
||||
OffsetPageTable::new(level_4_table, physical_memory_offset)
|
||||
}
|
||||
|
||||
unsafe fn active_level_4_table(physical_memory_offset: VirtAddr) -> &'static mut PageTable {
|
||||
use x86_64::registers::control::Cr3;
|
||||
|
||||
let (level_4_table_frame, _) = Cr3::read();
|
||||
|
||||
let phys = level_4_table_frame.start_address();
|
||||
let virt = physical_memory_offset + phys.as_u64();
|
||||
let page_table_ptr: *mut PageTable = virt.as_mut_ptr();
|
||||
|
||||
// THIS IS UNSAFE
|
||||
&mut *page_table_ptr
|
||||
}
|
||||
|
||||
pub struct BootInfoFrameAllocator {
|
||||
memory_map: &'static LimineMemmapResponse,
|
||||
next: usize,
|
||||
}
|
||||
|
||||
impl BootInfoFrameAllocator {
|
||||
pub unsafe fn init(memory_map: &'static LimineMemmapResponse) -> Self {
|
||||
Self {
|
||||
memory_map,
|
||||
next: 0,
|
||||
}
|
||||
}
|
||||
|
||||
fn usable_frames(&self) -> impl Iterator<Item = PhysFrame> {
|
||||
self.memory_map.mmap().unwrap().iter()
|
||||
.filter(|r| r.typ == LimineMemoryMapEntryType::Usable)
|
||||
.map(|r| r.base..r.base + r.len)
|
||||
.flat_map(|r| r.step_by(4096))
|
||||
.map(|addr| PhysFrame::containing_address(PhysAddr::new(addr)))
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl FrameAllocator<Size4KiB> for BootInfoFrameAllocator {
|
||||
fn allocate_frame(&mut self) -> Option<PhysFrame<Size4KiB>> {
|
||||
let frame = self.usable_frames().nth(self.next);
|
||||
self.next += 1;
|
||||
frame
|
||||
}
|
||||
}
|
||||
|
||||
impl FrameDeallocator<Size4KiB> for BootInfoFrameAllocator {
|
||||
unsafe fn deallocate_frame(&mut self, _frame: PhysFrame<Size4KiB>) {
|
||||
// TODO
|
||||
}
|
||||
}
|
|
@ -1,60 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2022, able <abl3theabove@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
pub mod drivers;
|
||||
pub mod gdt;
|
||||
pub mod init;
|
||||
pub mod interrupts;
|
||||
pub mod memory;
|
||||
|
||||
use limine::*;
|
||||
use x86_64::{instructions::hlt, VirtAddr};
|
||||
|
||||
use crate::serial_println;
|
||||
|
||||
use self::drivers::allocator;
|
||||
|
||||
static HHDM: LimineHhdmRequest = LimineHhdmRequest::new(0);
|
||||
static MMAP: LimineMmapRequest = LimineMmapRequest::new(0);
|
||||
|
||||
#[no_mangle]
|
||||
pub fn x86_64_start() -> ! {
|
||||
let hhdm = HHDM.get_response().get().unwrap();
|
||||
let mmap = MMAP.get_response().get().unwrap();
|
||||
let phys_mem_offset = VirtAddr::new(hhdm.offset);
|
||||
|
||||
let mut mapper = unsafe { memory::init(phys_mem_offset) };
|
||||
let mut frame_allocator = unsafe { memory::BootInfoFrameAllocator::init(mmap) };
|
||||
|
||||
allocator::init_heap(&mut mapper, &mut frame_allocator).expect("heap initialization failed");
|
||||
|
||||
crate::kmain::kernel_main(mapper, frame_allocator);
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn shutdown() -> ! {
|
||||
info!("Shutting down");
|
||||
unsafe {
|
||||
cpuio::outw(0x2000, 0x604);
|
||||
}
|
||||
|
||||
sloop();
|
||||
}
|
||||
|
||||
pub fn sloop() -> ! {
|
||||
loop {
|
||||
hlt();
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Split up into the randomness and the password generation
|
||||
pub fn generate_process_pass() -> u128 {
|
||||
// TODO: Move this into entropy_pool module
|
||||
use rdrand::RdRand;
|
||||
let gen = RdRand::new().unwrap();
|
||||
|
||||
(gen.try_next_u64().unwrap() as u128) << 64 | (gen.try_next_u64().unwrap() as u128)
|
||||
}
|
|
@ -1,72 +0,0 @@
|
|||
use log::LevelFilter;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize, Debug, Deserialize)]
|
||||
pub enum LogLevel {
|
||||
/// A level lower than all log levels.
|
||||
Off,
|
||||
/// Corresponds to the `Error` log level.
|
||||
Error,
|
||||
/// Corresponds to the `Warn` log level.
|
||||
Warn,
|
||||
/// Corresponds to the `Info` log level.
|
||||
Info,
|
||||
/// Corresponds to the `Debug` log level.
|
||||
Debug,
|
||||
/// Corresponds to the `Trace` log level.
|
||||
Trace,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Debug, Deserialize)]
|
||||
pub struct KernelConfig {
|
||||
pub logging: LoggingConfig,
|
||||
}
|
||||
|
||||
impl KernelConfig {
|
||||
pub fn new() -> Self {
|
||||
KernelConfig::default()
|
||||
}
|
||||
pub fn load_from_string(toml_string: &str) -> Self {
|
||||
match toml::from_str(toml_string) {
|
||||
Ok(kernel_conf) => kernel_conf,
|
||||
Err(err) => {
|
||||
error!("Error {}", err);
|
||||
KernelConfig::new()
|
||||
}
|
||||
}
|
||||
}
|
||||
pub fn log_level(&self) -> LevelFilter {
|
||||
use LevelFilter::*;
|
||||
match self.logging.level {
|
||||
LogLevel::Off => Off,
|
||||
LogLevel::Error => Error,
|
||||
LogLevel::Warn => Warn,
|
||||
LogLevel::Info => Info,
|
||||
LogLevel::Debug => Debug,
|
||||
LogLevel::Trace => Trace,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for KernelConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
logging: LoggingConfig {
|
||||
enabled: true,
|
||||
log_to_serial: true,
|
||||
log_to_vterm: false,
|
||||
level: LogLevel::Trace,
|
||||
filter: Vec::new(),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Debug, Deserialize)]
|
||||
pub struct LoggingConfig {
|
||||
pub enabled: bool,
|
||||
pub log_to_serial: bool,
|
||||
pub log_to_vterm: bool,
|
||||
pub level: LogLevel,
|
||||
pub filter: Vec<String>,
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
//! Block device interface
|
||||
|
||||
/// Block device interface
|
||||
pub trait BlockDevice {
|
||||
// TODO
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
//!
|
||||
|
||||
/// Character device interface.
|
||||
pub trait CharacterDevice {
|
||||
/// Returns true if the device can be read from.
|
||||
fn can_read(&self) -> bool;
|
||||
|
||||
/// Returns true if the device can be written to
|
||||
fn can_write(&self) -> bool;
|
||||
|
||||
/// Reads a single character from the device
|
||||
fn read_char(&mut self) -> Option<char>;
|
||||
|
||||
/// Writes a single character to the device and returns true if the write was successful
|
||||
fn write_char(&mut self, c: char) -> bool;
|
||||
|
||||
/// Reset the device to its initial state
|
||||
fn reset(&mut self);
|
||||
|
||||
/// initializes the device, returns true if successful
|
||||
fn initialize(&mut self) -> bool;
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
//! Platform Agnostic Device
|
||||
|
||||
mod block;
|
||||
mod character;
|
||||
|
||||
pub use block::BlockDevice;
|
||||
pub use character::CharacterDevice;
|
|
@ -1,29 +0,0 @@
|
|||
use crate::device_interface::CharacterDevice;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct DevNull;
|
||||
impl CharacterDevice for DevNull {
|
||||
fn can_read(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn can_write(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn read_char(&mut self) -> Option<char> {
|
||||
Some(0x00 as char)
|
||||
}
|
||||
|
||||
fn write_char(&mut self, _: char) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn reset(&mut self) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn initialize(&mut self) -> bool {
|
||||
todo!()
|
||||
}
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
use crate::device_interface::CharacterDevice;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct DevUnicode {
|
||||
pub next_write_char: char,
|
||||
pub next_read_char: char,
|
||||
}
|
||||
|
||||
impl CharacterDevice for DevUnicode {
|
||||
fn can_read(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn can_write(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn read_char(&mut self) -> Option<char> {
|
||||
let c = self.next_read_char;
|
||||
self.next_read_char = add1_char(c);
|
||||
|
||||
Some(c)
|
||||
}
|
||||
|
||||
fn write_char(&mut self, c: char) -> bool {
|
||||
if self.next_write_char != c {
|
||||
return false;
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
fn reset(&mut self) {
|
||||
self.next_write_char = 0x00 as char;
|
||||
self.next_read_char = 0x00 as char;
|
||||
}
|
||||
|
||||
fn initialize(&mut self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
fn add1_char(c: char) -> char {
|
||||
if c == char::MAX {
|
||||
return 0x00 as char;
|
||||
}
|
||||
|
||||
char::from_u32(c as u32 + 1).unwrap()
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
use crate::device_interface::CharacterDevice;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct DevZero;
|
||||
impl CharacterDevice for DevZero {
|
||||
fn can_read(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn can_write(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn read_char(&mut self) -> Option<char> {
|
||||
Some(0 as char)
|
||||
}
|
||||
|
||||
fn write_char(&mut self, _: char) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn reset(&mut self) {}
|
||||
|
||||
fn initialize(&mut self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
pub mod dev_null;
|
||||
pub mod dev_unicode;
|
||||
pub mod dev_zero;
|
||||
|
||||
pub use crate::device_interface::CharacterDevice;
|
|
@ -1,265 +0,0 @@
|
|||
// ! A virtual terminal device.
|
||||
|
||||
use crate::device_interface::CharacterDevice;
|
||||
use core::ops::Not;
|
||||
use core::sync::atomic::AtomicU32;
|
||||
use core::sync::atomic::Ordering;
|
||||
|
||||
use crate::pixel_format::Rgba64;
|
||||
|
||||
pub const VTERM_HEIGHT: u32 = 40;
|
||||
pub const VTERM_WIDTH: u32 = 100;
|
||||
|
||||
pub static VIRTUAL_TERMINAL_COUNT: AtomicU32 = AtomicU32::new(0);
|
||||
|
||||
/// Fg and bg colors for vterm
|
||||
pub type ColorCharacter = (Rgba64, Rgba64);
|
||||
|
||||
/// A vterm representation of a character
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct VtermCharacter {
|
||||
pub character: char,
|
||||
//
|
||||
pub style: Style,
|
||||
//
|
||||
pub char_color: ColorCharacter,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, Copy)]
|
||||
|
||||
pub struct Style(pub u8);
|
||||
impl Style {
|
||||
pub fn bold(&self) -> bool {
|
||||
(self.0 & 0x01) > 0
|
||||
}
|
||||
|
||||
pub fn underlined(&self) -> bool {
|
||||
(self.0 & 0x02) > 0
|
||||
}
|
||||
|
||||
pub fn italic(&self) -> bool {
|
||||
(self.0 & 0x04) > 0
|
||||
}
|
||||
|
||||
pub fn blinking(&self) -> bool {
|
||||
(self.0 & 0x08) > 0
|
||||
}
|
||||
|
||||
pub fn reversed(&self) -> bool {
|
||||
(self.0 & 0x10) > 0
|
||||
}
|
||||
|
||||
pub fn struck(&self) -> bool {
|
||||
(self.0 & 0x20) > 0
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn set_bold(mut self, v: bool) -> Self {
|
||||
if v {
|
||||
self.0 |= 0x01;
|
||||
} else {
|
||||
self.0 &= 0x01u8.not();
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn set_underlined(mut self, v: bool) -> Self {
|
||||
if v {
|
||||
self.0 |= 0x02;
|
||||
} else {
|
||||
self.0 &= 0x02u8.not();
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn set_italic(mut self, v: bool) -> Self {
|
||||
if v {
|
||||
self.0 |= 0x04;
|
||||
} else {
|
||||
self.0 &= 0x04u8.not();
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn set_blinking(mut self, v: bool) -> Self {
|
||||
if v {
|
||||
self.0 |= 0x08;
|
||||
} else {
|
||||
self.0 &= 0x08u8.not();
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn set_reversed(mut self, v: bool) -> Self {
|
||||
if v {
|
||||
self.0 |= 0x10;
|
||||
} else {
|
||||
self.0 &= 0x10u8.not();
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn set_struck(mut self, v: bool) -> Self {
|
||||
if v {
|
||||
self.0 |= 0x20;
|
||||
} else {
|
||||
self.0 &= 0x20u8.not();
|
||||
}
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct VTerm {
|
||||
pub characters: [[VtermCharacter; VTERM_WIDTH as usize]; VTERM_HEIGHT as usize],
|
||||
pub cursor_visible: bool,
|
||||
|
||||
/// Internal ID of the vterm
|
||||
iid: u32,
|
||||
|
||||
/// The internal representation of the vterm
|
||||
style: Style,
|
||||
|
||||
/// The cursor position in layout x,y
|
||||
cursor_position: (u32, u32),
|
||||
key_buff: Vec<char>,
|
||||
}
|
||||
|
||||
impl Default for VTerm {
|
||||
fn default() -> Self {
|
||||
VTerm {
|
||||
iid: 0,
|
||||
characters: [[VtermCharacter {
|
||||
character: 0x00 as char,
|
||||
char_color: (0xff_ff_ff_ff, 0x00_00_00_00),
|
||||
style: Style::default(),
|
||||
}; VTERM_WIDTH as usize]; VTERM_HEIGHT as usize],
|
||||
cursor_position: (0, 0),
|
||||
cursor_visible: true,
|
||||
style: Style::default(),
|
||||
key_buff: vec![],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The primitive interface for a vterm
|
||||
impl VTerm {
|
||||
pub fn new() -> Self {
|
||||
let mut vterm = VTerm::default();
|
||||
let mut vtc = VIRTUAL_TERMINAL_COUNT.load(Ordering::Relaxed);
|
||||
vterm.iid = vtc;
|
||||
vtc += 1;
|
||||
VIRTUAL_TERMINAL_COUNT.store(vtc, Ordering::Relaxed);
|
||||
|
||||
vterm
|
||||
}
|
||||
/// Set the vterm cursor to the given position
|
||||
pub fn set_cursor_position(&mut self, x: u32, y: u32) {
|
||||
if x > VTERM_WIDTH {
|
||||
self.cursor_position.0 = VTERM_WIDTH;
|
||||
error!("Cursor x position out of bounds");
|
||||
} else {
|
||||
self.cursor_position.0 = x;
|
||||
}
|
||||
if y > VTERM_HEIGHT {
|
||||
error!("Cursor y position out of bounds");
|
||||
self.cursor_position.1 = VTERM_HEIGHT;
|
||||
} else {
|
||||
self.cursor_position.1 = y;
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the vterm style
|
||||
pub fn set_vterm_style(&mut self, style: Style) {
|
||||
self.style = style;
|
||||
}
|
||||
}
|
||||
|
||||
impl CharacterDevice for VTerm {
|
||||
fn can_read(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn can_write(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn read_char(&mut self) -> Option<char> {
|
||||
if let Some(c) = self.key_buff.pop() {
|
||||
return Some(c);
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn write_char(&mut self, c: char) -> bool {
|
||||
match c {
|
||||
'\n' => {
|
||||
self.cursor_position.1 += 1;
|
||||
self.cursor_position.0 = 0;
|
||||
true
|
||||
}
|
||||
'\r' => {
|
||||
self.cursor_position.0 = 0;
|
||||
true
|
||||
}
|
||||
'\t' => {
|
||||
self.cursor_position.0 += 4;
|
||||
true
|
||||
}
|
||||
'\x08' => {
|
||||
self.cursor_position.0 -= 1;
|
||||
self.characters[self.cursor_position.1 as usize][self.cursor_position.0 as usize]
|
||||
.character = ' ';
|
||||
true
|
||||
}
|
||||
// This is a form feed, which is used to clear the screen
|
||||
'\x0c' => {
|
||||
self.characters = [[VtermCharacter {
|
||||
character: ' ',
|
||||
char_color: (0xff_ff_ff_ff, 0x00_00_00_00),
|
||||
style: Style::default(),
|
||||
}; VTERM_WIDTH as usize]; VTERM_HEIGHT as usize];
|
||||
true
|
||||
}
|
||||
|
||||
_ => {
|
||||
self.characters[self.cursor_position.1 as usize][self.cursor_position.0 as usize]
|
||||
.character = c;
|
||||
self.characters[self.cursor_position.1 as usize][self.cursor_position.0 as usize]
|
||||
.char_color = (0xff_ff_ff_ff, 0x00_00_00_00);
|
||||
self.characters[self.cursor_position.1 as usize][self.cursor_position.0 as usize]
|
||||
.style = self.style;
|
||||
|
||||
if self.cursor_position.0 < VTERM_WIDTH {
|
||||
self.cursor_position.0 += 1;
|
||||
true
|
||||
} else {
|
||||
self.cursor_position.0 = 0;
|
||||
self.cursor_position.1 += 1;
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn reset(&mut self) {
|
||||
self.characters = [[VtermCharacter {
|
||||
character: ' ',
|
||||
char_color: (0xff_ff_ff_ff, 0x00_00_00_00),
|
||||
style: Style::default(),
|
||||
}; VTERM_WIDTH as usize]; VTERM_HEIGHT as usize];
|
||||
|
||||
self.cursor_position = (0, 0);
|
||||
self.cursor_visible = true;
|
||||
self.style = Style::default();
|
||||
}
|
||||
|
||||
fn initialize(&mut self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
#[derive(Debug)]
|
||||
pub enum Vendor {
|
||||
Unknown = 0,
|
||||
Ati = 1002,
|
||||
}
|
||||
|
||||
pub fn match_vendor(id: u16) -> Vendor {
|
||||
use Vendor::*;
|
||||
|
||||
match id {
|
||||
1002 => Ati,
|
||||
_ => Unknown,
|
||||
}
|
||||
}
|
|
@ -1,59 +0,0 @@
|
|||
pub mod character_devs;
|
||||
mod dev_vterm;
|
||||
|
||||
pub mod id;
|
||||
pub mod pci;
|
||||
|
||||
pub use self::Device::*;
|
||||
|
||||
use crate::device_interface::{BlockDevice, CharacterDevice};
|
||||
use crate::devices::dev_vterm::VTerm;
|
||||
use character_devs::{dev_null::DevNull, dev_unicode::DevUnicode, dev_zero::DevZero};
|
||||
use hashbrown::HashMap;
|
||||
use spin::Lazy;
|
||||
|
||||
pub static DEVICE_TABLE: Lazy<spin::Mutex<DeviceTable>> =
|
||||
Lazy::new(|| spin::Mutex::new(DeviceTable::new()));
|
||||
|
||||
// FIXME: This is a hack to hold a device.
|
||||
// #[derive(Debug)]
|
||||
pub enum Device {
|
||||
Block(Box<dyn BlockDevice>),
|
||||
Character(Box<dyn CharacterDevice>),
|
||||
Vterm(Box<VTerm>),
|
||||
}
|
||||
|
||||
unsafe impl Sync for Device {}
|
||||
unsafe impl Send for Device {}
|
||||
|
||||
pub struct DeviceTable {
|
||||
pub devices: HashMap<String, Device>,
|
||||
}
|
||||
|
||||
impl DeviceTable {
|
||||
pub fn new() -> Self {
|
||||
DeviceTable {
|
||||
devices: [
|
||||
("null", Character(Box::new(DevNull))),
|
||||
("zero", Character(Box::new(DevZero))),
|
||||
(
|
||||
"unicode",
|
||||
Character(Box::new(DevUnicode {
|
||||
next_write_char: 0x00 as char,
|
||||
next_read_char: 0x00 as char,
|
||||
})),
|
||||
),
|
||||
("kvterm", Vterm(Box::new(VTerm::new()))),
|
||||
]
|
||||
.into_iter()
|
||||
.map(|(k, v)| (k.to_string(), v))
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for DeviceTable {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
|
@ -1,240 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2022, able <abl3theabove@gmail.com>
|
||||
* Copyright (c) 2022, Umut İnan Erdoğan <umutinanerdogan@pm.me>
|
||||
*
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
use core::fmt::Display;
|
||||
|
||||
#[allow(non_camel_case_types, dead_code)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
#[repr(C)]
|
||||
/// Class specification for a PCI device
|
||||
pub enum PciClass {
|
||||
Unclassified = 0x00,
|
||||
MassStorage = 0x01,
|
||||
Network = 0x02,
|
||||
Display = 0x03,
|
||||
Multimedia = 0x04,
|
||||
Memory = 0x05,
|
||||
Bridge = 0x06,
|
||||
Unknown = 0xFF,
|
||||
}
|
||||
|
||||
impl From<u8> for PciClass {
|
||||
/// Convert a u8 into the corresponding PciClass
|
||||
fn from(n: u8) -> Self {
|
||||
use PciClass::*;
|
||||
match n {
|
||||
0x00 => Unclassified,
|
||||
0x01 => MassStorage,
|
||||
0x02 => Network,
|
||||
0x03 => Display,
|
||||
0x04 => Multimedia,
|
||||
0x05 => Memory,
|
||||
0x06 => Bridge,
|
||||
_ => Unknown,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types, dead_code)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
#[repr(C)]
|
||||
/// Full class specification (type and subtype) for a PCI device.
|
||||
///
|
||||
/// Uses non-camel-case types for readability.
|
||||
pub enum PciFullClass {
|
||||
Unclassified_NonVgaCompatible = 0x0000,
|
||||
Unclassified_VgaCompatible = 0x0001,
|
||||
|
||||
MassStorage_ScsiBus = 0x0100,
|
||||
MassStorage_IDE = 0x0101,
|
||||
MassStorage_Floppy = 0x0102,
|
||||
MassStorage_IpiBus = 0x0103,
|
||||
MassStorage_RAID = 0x0104,
|
||||
MassStorage_ATA = 0x0105,
|
||||
MassStorage_SATA = 0x0106,
|
||||
MassStorage_SerialSCSI = 0x0107,
|
||||
MassStorage_NVM = 0x0108,
|
||||
MassStorage_Other = 0x0180,
|
||||
|
||||
Network_Ethernet = 0x0200,
|
||||
Network_TokenRing = 0x0201,
|
||||
Network_FDDI = 0x0202,
|
||||
Network_ATM = 0x0203,
|
||||
Network_ISDN = 0x0204,
|
||||
Network_WorldFlip = 0x0205,
|
||||
Network_PICMG = 0x0206,
|
||||
Network_Infiniband = 0x0207,
|
||||
Network_Fabric = 0x0208,
|
||||
Network_Other = 0x0280,
|
||||
|
||||
Display_VGA = 0x0300,
|
||||
Display_XGA = 0x0301,
|
||||
Display_3D = 0x0302,
|
||||
Display_Other = 0x0380,
|
||||
|
||||
Multimedia_Video = 0x0400,
|
||||
Multimedia_AudioController = 0x0401,
|
||||
Multimedia_Telephony = 0x0402,
|
||||
Multimedia_AudioDevice = 0x0403,
|
||||
Multimedia_Other = 0x0480,
|
||||
|
||||
Memory_RAM = 0x0500,
|
||||
Memory_Flash = 0x0501,
|
||||
Memory_Other = 0x0580,
|
||||
|
||||
Bridge_Host = 0x0600,
|
||||
Bridge_ISA = 0x0601,
|
||||
Bridge_EISA = 0x0602,
|
||||
Bridge_MCA = 0x0603,
|
||||
Bridge_PciToPci = 0x0604,
|
||||
Bridge_PCMCIA = 0x0605,
|
||||
Bridge_NuBus = 0x0606,
|
||||
Bridge_CardBus = 0x0607,
|
||||
Bridge_RACEway = 0x0608,
|
||||
Bridge_PciToPciSemiTransparent = 0x0609,
|
||||
Bridge_InfinibandToPci = 0x060A,
|
||||
Bridge_Other = 0x0680,
|
||||
|
||||
Unknown = 0xFFFF,
|
||||
}
|
||||
|
||||
impl PciFullClass {
|
||||
// listen, i know this sucks, but i didn't want to include
|
||||
// `num`, `num-traits` and `num-derive` as dependencies for
|
||||
// this crate just for a convenience function
|
||||
/// Convert a u16 into the corresponding PciFullClass
|
||||
pub fn from_u16(n: u16) -> PciFullClass {
|
||||
match n {
|
||||
0x0000 => PciFullClass::Unclassified_NonVgaCompatible,
|
||||
0x0001 => PciFullClass::Unclassified_VgaCompatible,
|
||||
|
||||
0x0100 => PciFullClass::MassStorage_ScsiBus,
|
||||
0x0101 => PciFullClass::MassStorage_IDE,
|
||||
0x0102 => PciFullClass::MassStorage_Floppy,
|
||||
0x0103 => PciFullClass::MassStorage_IpiBus,
|
||||
0x0104 => PciFullClass::MassStorage_RAID,
|
||||
0x0105 => PciFullClass::MassStorage_ATA,
|
||||
0x0106 => PciFullClass::MassStorage_SATA,
|
||||
0x0107 => PciFullClass::MassStorage_SerialSCSI,
|
||||
0x0108 => PciFullClass::MassStorage_NVM,
|
||||
0x0180 => PciFullClass::MassStorage_Other,
|
||||
|
||||
0x0200 => PciFullClass::Network_Ethernet,
|
||||
0x0201 => PciFullClass::Network_TokenRing,
|
||||
0x0202 => PciFullClass::Network_FDDI,
|
||||
0x0203 => PciFullClass::Network_ATM,
|
||||
0x0204 => PciFullClass::Network_ISDN,
|
||||
0x0205 => PciFullClass::Network_WorldFlip,
|
||||
0x0206 => PciFullClass::Network_PICMG,
|
||||
0x0207 => PciFullClass::Network_Infiniband,
|
||||
0x0208 => PciFullClass::Network_Fabric,
|
||||
0x0280 => PciFullClass::Network_Other,
|
||||
|
||||
0x0300 => PciFullClass::Display_VGA,
|
||||
0x0301 => PciFullClass::Display_XGA,
|
||||
0x0302 => PciFullClass::Display_3D,
|
||||
0x0380 => PciFullClass::Display_Other,
|
||||
|
||||
0x0400 => PciFullClass::Multimedia_Video,
|
||||
0x0401 => PciFullClass::Multimedia_AudioController,
|
||||
0x0402 => PciFullClass::Multimedia_Telephony,
|
||||
0x0403 => PciFullClass::Multimedia_AudioDevice,
|
||||
0x0480 => PciFullClass::Multimedia_Other,
|
||||
|
||||
0x0500 => PciFullClass::Memory_RAM,
|
||||
0x0501 => PciFullClass::Memory_Flash,
|
||||
0x0580 => PciFullClass::Memory_Other,
|
||||
|
||||
0x0600 => PciFullClass::Bridge_Host,
|
||||
0x0601 => PciFullClass::Bridge_ISA,
|
||||
0x0602 => PciFullClass::Bridge_EISA,
|
||||
0x0603 => PciFullClass::Bridge_MCA,
|
||||
0x0604 => PciFullClass::Bridge_PciToPci,
|
||||
0x0605 => PciFullClass::Bridge_PCMCIA,
|
||||
0x0606 => PciFullClass::Bridge_NuBus,
|
||||
0x0607 => PciFullClass::Bridge_CardBus,
|
||||
0x0608 => PciFullClass::Bridge_RACEway,
|
||||
0x0609 => PciFullClass::Bridge_PciToPciSemiTransparent,
|
||||
0x060A => PciFullClass::Bridge_InfinibandToPci,
|
||||
0x0680 => PciFullClass::Bridge_Other,
|
||||
|
||||
_ => PciFullClass::Unknown,
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert a PciFullClass to its u16 representation
|
||||
pub fn as_u16(&self) -> u16 {
|
||||
*self as u16
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u16> for PciFullClass {
|
||||
/// Convert a u16 into the corresponding PciFullClass
|
||||
fn from(n: u16) -> Self {
|
||||
Self::from_u16(n)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for PciFullClass {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
write!(f, " Class: ")?;
|
||||
|
||||
match self {
|
||||
PciFullClass::Unclassified_NonVgaCompatible => write!(f, "\0LIGHTBLUE\0")?,
|
||||
PciFullClass::Unclassified_VgaCompatible => write!(f, "\0LIGHTBLUE\0")?,
|
||||
PciFullClass::MassStorage_ScsiBus => write!(f, "\0CYAN\0")?,
|
||||
PciFullClass::MassStorage_IDE => write!(f, "\0CYAN\0")?,
|
||||
PciFullClass::MassStorage_Floppy => write!(f, "\0CYAN\0")?,
|
||||
PciFullClass::MassStorage_IpiBus => write!(f, "\0CYAN\0")?,
|
||||
PciFullClass::MassStorage_RAID => write!(f, "\0CYAN\0")?,
|
||||
PciFullClass::MassStorage_ATA => write!(f, "\0CYAN\0")?,
|
||||
PciFullClass::MassStorage_SATA => write!(f, "\0CYAN\0")?,
|
||||
PciFullClass::MassStorage_SerialSCSI => write!(f, "\0CYAN\0")?,
|
||||
PciFullClass::MassStorage_NVM => write!(f, "\0CYAN\0")?,
|
||||
PciFullClass::MassStorage_Other => write!(f, "\0CYAN\0")?,
|
||||
PciFullClass::Network_Ethernet => write!(f, "\0MAGENTA\0")?,
|
||||
PciFullClass::Network_TokenRing => write!(f, "\0MAGENTA\0")?,
|
||||
PciFullClass::Network_FDDI => write!(f, "\0MAGENTA\0")?,
|
||||
PciFullClass::Network_ATM => write!(f, "\0MAGENTA\0")?,
|
||||
PciFullClass::Network_ISDN => write!(f, "\0MAGENTA\0")?,
|
||||
PciFullClass::Network_WorldFlip => write!(f, "\0MAGENTA\0")?,
|
||||
PciFullClass::Network_PICMG => write!(f, "\0MAGENTA\0")?,
|
||||
PciFullClass::Network_Infiniband => write!(f, "\0MAGENTA\0")?,
|
||||
PciFullClass::Network_Fabric => write!(f, "\0MAGENTA\0")?,
|
||||
PciFullClass::Network_Other => write!(f, "\0MAGENTA\0")?,
|
||||
PciFullClass::Display_VGA => write!(f, "\0YELLOW\0")?,
|
||||
PciFullClass::Display_XGA => write!(f, "\0YELLOW\0")?,
|
||||
PciFullClass::Display_3D => write!(f, "\0YELLOW\0")?,
|
||||
PciFullClass::Display_Other => write!(f, "\0YELLOW\0")?,
|
||||
PciFullClass::Multimedia_Video => write!(f, "\0LIGHTBLUE\0")?,
|
||||
PciFullClass::Multimedia_AudioController => write!(f, "\0LIGHTBLUE\0")?,
|
||||
PciFullClass::Multimedia_Telephony => write!(f, "\0LIGHTBLUE\0")?,
|
||||
PciFullClass::Multimedia_AudioDevice => write!(f, "\0LIGHTBLUE\0")?,
|
||||
PciFullClass::Multimedia_Other => write!(f, "\0LIGHTBLUE\0")?,
|
||||
PciFullClass::Memory_RAM => write!(f, "\0BLUE\0")?,
|
||||
PciFullClass::Memory_Flash => write!(f, "\0WHITE\0")?,
|
||||
PciFullClass::Memory_Other => write!(f, "\0LIGHTGREY\0")?,
|
||||
PciFullClass::Bridge_Host => write!(f, "\0GREEN\0")?,
|
||||
PciFullClass::Bridge_ISA => write!(f, "\0GREEN\0")?,
|
||||
PciFullClass::Bridge_EISA => write!(f, "\0GREEN\0")?,
|
||||
PciFullClass::Bridge_MCA => write!(f, "\0GREEN\0")?,
|
||||
PciFullClass::Bridge_PciToPci => write!(f, "\0GREEN\0")?,
|
||||
PciFullClass::Bridge_PCMCIA => write!(f, "\0GREEN\0")?,
|
||||
PciFullClass::Bridge_NuBus => write!(f, "\0GREEN\0")?,
|
||||
PciFullClass::Bridge_CardBus => write!(f, "\0GREEN\0")?,
|
||||
PciFullClass::Bridge_RACEway => write!(f, "\0GREEN\0")?,
|
||||
PciFullClass::Bridge_PciToPciSemiTransparent => write!(f, "\0GREEN\0")?,
|
||||
PciFullClass::Bridge_InfinibandToPci => write!(f, "\0GREEN\0")?,
|
||||
PciFullClass::Bridge_Other => write!(f, "\0GREEN\0")?,
|
||||
PciFullClass::Unknown => write!(f, "\0RED\0")?,
|
||||
}
|
||||
|
||||
write!(f, "{:?} ({:#06X})\0RESET\0", self, self.as_u16())?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
|
@ -1,194 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2022, able <abl3theabove@gmail.com>
|
||||
* Copyright (c) 2022, Umut İnan Erdoğan <umutinanerdogan@pm.me>
|
||||
*
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
use core::fmt;
|
||||
|
||||
use x86_64::instructions::port::Port;
|
||||
|
||||
use super::{
|
||||
vendors::Vendor::{self, *},
|
||||
PciClass, PciFullClass,
|
||||
};
|
||||
|
||||
// FIXME: Unknown class
|
||||
pub const S3_TRIO64V2: DeviceID = DeviceID::new(S3Inc, 0x8900);
|
||||
|
||||
// MassStorage_IDE (0x0101)
|
||||
pub const INTEL_PIIX3_IDE: DeviceID = DeviceID::new(IntelCorp, 0x7010);
|
||||
pub const INTEL_PIIX4_IDE: DeviceID = DeviceID::new(IntelCorp, 0x7111);
|
||||
|
||||
// Display_VGA (0x0300)
|
||||
pub const VMWARE_SVGA2: DeviceID = DeviceID::new(VMWareInc, 0x0405);
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
/// A struct containing info about a PCI device.
|
||||
pub struct PciDeviceInfo {
|
||||
pub header_type: u8,
|
||||
pub device: u8,
|
||||
pub bus: u8,
|
||||
pub device_id: DeviceID,
|
||||
pub full_class: PciFullClass,
|
||||
pub rev_id: u8,
|
||||
}
|
||||
|
||||
impl PciDeviceInfo {
|
||||
/// Get the class of the PCI device as a PciClass
|
||||
pub fn class(&self) -> PciClass {
|
||||
(((self.full_class.as_u16() >> 8) & 0xFF) as u8).into()
|
||||
}
|
||||
|
||||
/// Get the bar, 0-indexed
|
||||
pub fn bar(&self, bar: u8) -> u32 {
|
||||
assert!(bar < 6);
|
||||
unsafe { self.read(0, 0x10 + bar * 4) }
|
||||
}
|
||||
|
||||
/// Get the interrupt pin
|
||||
pub fn interrupt_pin(&self) -> u8 {
|
||||
let last_row = unsafe { self.read(0, 0x3C) };
|
||||
((last_row >> 8) & 0xFF) as u8
|
||||
}
|
||||
|
||||
/// Enable bus mastering. This allows the PCI device to do DMA
|
||||
pub fn enable_bus_mastering(&self) {
|
||||
let command = unsafe { self.read(0, 4) } | 1 << 2;
|
||||
unsafe { self.write(0, 4, command) }
|
||||
}
|
||||
|
||||
/// Read from configuration space
|
||||
pub unsafe fn read(&self, func: u8, offset: u8) -> u32 {
|
||||
pci_config_read(self.bus, self.device, func, offset)
|
||||
}
|
||||
|
||||
/// Write to IO space
|
||||
pub unsafe fn write(&self, func: u8, offset: u8, value: u32) {
|
||||
pci_config_write(self.bus, self.device, func, offset, value)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for PciDeviceInfo {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
||||
let vendor_name = &self.device_id.vendor;
|
||||
let device_id = &self.device_id.id;
|
||||
writeln!(
|
||||
f,
|
||||
"Device: {} | Bus: 0x{:X} | Vendor: {} | Device ID: 0x{:X}",
|
||||
self.device, self.bus, vendor_name, device_id,
|
||||
)?;
|
||||
writeln!(f, "{}", self.full_class)?;
|
||||
writeln!(f, " Header type: 0x{:X}", self.header_type)?;
|
||||
writeln!(f, " Revision ID: {}", self.rev_id)?;
|
||||
// write!(f, " Supported functions: 0")?;
|
||||
// for (i, b) in self.supported_fns.iter().enumerate().skip(1) {
|
||||
// if *b {
|
||||
// write!(f, ", {}", i)?;
|
||||
// }
|
||||
// }
|
||||
// writeln!(f)?;
|
||||
// write!(f, " BARs: [ ")?;
|
||||
// for i in self.bars.iter() {
|
||||
// if *i == 0 {
|
||||
// write!(f, "0x0 ")?;
|
||||
// } else {
|
||||
// write!(f, "{:#010X} ", i)?;
|
||||
// }
|
||||
// }
|
||||
// writeln!(f, "]")?;
|
||||
// writeln!(
|
||||
// f,
|
||||
// " Interrupt line / pin: {} / {}",
|
||||
// self.interrupt_line, self.interrupt_pin
|
||||
// )?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub struct DeviceID {
|
||||
pub vendor: Vendor,
|
||||
pub id: u16,
|
||||
}
|
||||
|
||||
impl DeviceID {
|
||||
pub const fn new(vendor: Vendor, id: u16) -> Self {
|
||||
Self { vendor, id }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn check_device(bus: u8, device: u8) -> Option<PciDeviceInfo> {
|
||||
assert!(device < 32);
|
||||
let (device_id, vendor_id) = get_ids(bus, device, 0);
|
||||
if vendor_id == 0xFFFF {
|
||||
// Device doesn't exist
|
||||
return None;
|
||||
}
|
||||
|
||||
let reg2 = unsafe { pci_config_read(bus, device, 0, 0x8) };
|
||||
let class = ((reg2 >> 16) & 0x0000FFFF) as u16;
|
||||
let pci_class = PciFullClass::from_u16(class);
|
||||
let header_type = get_header_type(bus, device, 0);
|
||||
|
||||
Some(PciDeviceInfo {
|
||||
header_type,
|
||||
device,
|
||||
bus,
|
||||
device_id: DeviceID {
|
||||
vendor: vendor_id.into(),
|
||||
id: device_id,
|
||||
},
|
||||
full_class: pci_class,
|
||||
rev_id: (reg2 & 0x000000FF) as u8,
|
||||
})
|
||||
}
|
||||
|
||||
unsafe fn pci_config_read(bus: u8, device: u8, func: u8, offset: u8) -> u32 {
|
||||
let bus = bus as u32;
|
||||
let device = device as u32;
|
||||
let func = func as u32;
|
||||
let offset = offset as u32;
|
||||
// construct address param
|
||||
let address =
|
||||
((bus << 16) | (device << 11) | (func << 8) | (offset & 0xfc) | 0x80000000) as u32;
|
||||
|
||||
// write address
|
||||
Port::new(0xCF8).write(address);
|
||||
|
||||
// read data
|
||||
Port::new(0xCFC).read()
|
||||
}
|
||||
|
||||
unsafe fn pci_config_write(bus: u8, device: u8, func: u8, offset: u8, value: u32) {
|
||||
let bus = bus as u32;
|
||||
let device = device as u32;
|
||||
let func = func as u32;
|
||||
let offset = offset as u32;
|
||||
// construct address param
|
||||
let address =
|
||||
((bus << 16) | (device << 11) | (func << 8) | (offset & 0xfc) | 0x80000000) as u32;
|
||||
|
||||
// write address
|
||||
Port::new(0xCF8).write(address);
|
||||
|
||||
// write data
|
||||
Port::new(0xCFC).write(value);
|
||||
}
|
||||
|
||||
fn get_header_type(bus: u8, device: u8, function: u8) -> u8 {
|
||||
assert!(device < 32);
|
||||
assert!(function < 8);
|
||||
let res = unsafe { pci_config_read(bus, device, function, 0x0C) };
|
||||
((res >> 16) & 0xFF) as u8
|
||||
}
|
||||
|
||||
fn get_ids(bus: u8, device: u8, function: u8) -> (u16, u16) {
|
||||
assert!(device < 32);
|
||||
assert!(function < 8);
|
||||
let res = unsafe { pci_config_read(bus, device, function, 0) };
|
||||
let dev_id = ((res >> 16) & 0xFFFF) as u16;
|
||||
let vnd_id = (res & 0xFFFF) as u16;
|
||||
(dev_id, vnd_id)
|
||||
}
|
|
@ -1,674 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2022, Umut İnan Erdoğan <umutinanerdogan@pm.me>
|
||||
*
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
use core::num::TryFromIntError;
|
||||
|
||||
// FIXME: platform agnostic-ify these
|
||||
use x86_64::instructions::{interrupts, port::Port};
|
||||
use x86_64::structures::paging::{mapper::MapToError, Mapper, Page, PhysFrame, Size4KiB};
|
||||
use x86_64::structures::paging::{FrameAllocator, FrameDeallocator};
|
||||
use x86_64::VirtAddr;
|
||||
|
||||
use crate::arch::memory::BootInfoFrameAllocator;
|
||||
use crate::devices::pci::check_device;
|
||||
|
||||
use super::PciDeviceInfo;
|
||||
|
||||
// FIXME: un-hardcode these
|
||||
const PRDT_START: u64 = 0xffff_ffff_0000_0000;
|
||||
const BUFFER_START: u64 = 0xffff_ffff_0000_1000;
|
||||
|
||||
/// ATA logical sector size, in bytes
|
||||
const SECTOR_SIZE: u16 = 512;
|
||||
|
||||
/// Bus Master IDE Command
|
||||
const BMIC_OFFSET: u16 = 0;
|
||||
/// Bus Master IDE Status
|
||||
const BMIS_OFFSET: u16 = 2;
|
||||
/// Bus Master IDE Descriptor Table Pointer
|
||||
const BMIDTP_OFFSET: u16 = 4;
|
||||
|
||||
/// Bus Master IDE Secondary Offset
|
||||
const BMI_SECONDARY: u16 = 8;
|
||||
|
||||
/// Primary command block offset
|
||||
const PRIMARY_COMMAND: u16 = 0x01F0;
|
||||
|
||||
/// Secondary command block offset
|
||||
const SECONDARY_COMMAND: u16 = 0x0170;
|
||||
|
||||
/// Data register offset
|
||||
const DATA_OFFSET: u16 = 0;
|
||||
|
||||
/// Sector count register offset
|
||||
const SECCOUNT_OFFSET: u16 = 2;
|
||||
|
||||
/// LBA0 register offset
|
||||
const LBA0_OFFSET: u16 = 3;
|
||||
|
||||
/// LBA1 register offset
|
||||
const LBA1_OFFSET: u16 = 4;
|
||||
|
||||
/// LBA2 register offset
|
||||
const LBA2_OFFSET: u16 = 5;
|
||||
|
||||
/// Drive/Head register offset
|
||||
const DRIVE_HEAD_OFFSET: u16 = 6;
|
||||
|
||||
/// Command/status register offset
|
||||
const COMMAND_STATUS_OFFSET: u16 = 7;
|
||||
|
||||
/// Secondary control block offset
|
||||
const SECONDARY_CONTROL: u16 = 0x0374;
|
||||
|
||||
/// Primary control block offset
|
||||
const PRIMARY_CONTROL: u16 = 0x03F4;
|
||||
|
||||
/// Alternative status offset
|
||||
const ALT_STATUS_OFFSET: u16 = 2;
|
||||
|
||||
/// ATA identification command
|
||||
const CMD_IDENTIFY: u8 = 0xEC;
|
||||
|
||||
/// ATA read using LBA28 DMA command
|
||||
const CMD_READ_DMA: u8 = 0xC8;
|
||||
|
||||
/// ATA write using LBA28 DMA command
|
||||
const CMD_WRITE_DMA: u8 = 0xCA;
|
||||
|
||||
/// ATA read using LBA48 DMA command
|
||||
const CMD_READ_DMA_EXT: u8 = 0x25;
|
||||
|
||||
/// ATA write using LBA48 DMA command
|
||||
const CMD_WRITE_DMA_EXT: u8 = 0x35;
|
||||
|
||||
pub struct PciIde {
|
||||
device_info: PciDeviceInfo,
|
||||
ide_devices: Vec<IdeDevice>,
|
||||
prdt_frame: Option<PhysFrame>,
|
||||
buffer_frames: Option<Vec<PhysFrame>>,
|
||||
bmiba: u16,
|
||||
}
|
||||
|
||||
impl PciIde {
|
||||
// FIXME: make this return a Result
|
||||
pub fn new(bus: u8, device: u8) -> Option<Self> {
|
||||
let device_info = check_device(bus, device)?;
|
||||
device_info.enable_bus_mastering();
|
||||
let idetim = unsafe { device_info.read(0, 0x40) };
|
||||
trace!("idetim: {idetim:b}");
|
||||
// FIXME: enable the right bits in idetim (and sidetim) to use fast timings
|
||||
|
||||
let mut ide_devices = Vec::with_capacity(4);
|
||||
for ch in 0..2 {
|
||||
let channel = if ch == 0 {
|
||||
Channel::Primary
|
||||
} else {
|
||||
Channel::Secondary
|
||||
};
|
||||
'drive: for dr in 0..2 {
|
||||
let drive = if dr == 0 { Drive::Master } else { Drive::Slave };
|
||||
|
||||
unsafe {
|
||||
select_drive(drive, channel);
|
||||
// FIXME: clear sector count and lba0, lba1, lba2 registers
|
||||
let status = ata_send_command(CMD_IDENTIFY, channel);
|
||||
if status == 0 {
|
||||
continue; // If status = 0, no device
|
||||
}
|
||||
|
||||
loop {
|
||||
let status = {
|
||||
let addr = if channel.secondary() {
|
||||
SECONDARY_COMMAND
|
||||
} else {
|
||||
PRIMARY_COMMAND
|
||||
} + COMMAND_STATUS_OFFSET;
|
||||
Port::<u8>::new(addr).read()
|
||||
};
|
||||
|
||||
if status & 1 == 1 {
|
||||
// if error (bit 0), device is not ATA
|
||||
// FIXME: ATAPI devices
|
||||
continue 'drive;
|
||||
}
|
||||
if !((status >> 7) & 1 == 1) && (status >> 3) & 1 == 1 {
|
||||
// BSY cleared, DRQ set, everything is right
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Read identification space of device
|
||||
let addr = if channel.secondary() {
|
||||
SECONDARY_COMMAND
|
||||
} else {
|
||||
PRIMARY_COMMAND
|
||||
} + DATA_OFFSET;
|
||||
let mut buffer = [0_u8; 512];
|
||||
read_dword_buffer(addr, buffer.as_mut_ptr() as *mut _, 128);
|
||||
// for (i, byte) in buffer.iter().enumerate() {
|
||||
// if byte.is_ascii() {
|
||||
// trace!("byte {i}: {byte:b}, ascii: {}", *byte as char);
|
||||
// } else {
|
||||
// trace!("byte {i}: {byte:b}");
|
||||
// }
|
||||
// }
|
||||
|
||||
if buffer[99] & 1 != 1 {
|
||||
// FIXME: PIO mode support
|
||||
error!("IDE drive {channel:?}/{drive:?} does not support DMA");
|
||||
continue;
|
||||
}
|
||||
|
||||
// FIXME: CHS support
|
||||
let lba48 = (buffer[167] >> 2) & 1 == 1;
|
||||
|
||||
let size = buffer[200] as u64
|
||||
| (buffer[201] as u64) << 8
|
||||
| (buffer[202] as u64) << 16
|
||||
| (buffer[203] as u64) << 24
|
||||
| (buffer[204] as u64) << 32
|
||||
| (buffer[205] as u64) << 40
|
||||
| (buffer[206] as u64) << 48
|
||||
| (buffer[207] as u64) << 54;
|
||||
trace!("IDE drive {channel:?}/{drive:?} has {size} sectors");
|
||||
|
||||
ide_devices.push(IdeDevice {
|
||||
channel,
|
||||
drive,
|
||||
size,
|
||||
lba48_support: lba48,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let bmiba = device_info.bar(4) & 0xFFFFFFFC;
|
||||
|
||||
Some(Self {
|
||||
device_info,
|
||||
ide_devices,
|
||||
prdt_frame: None,
|
||||
buffer_frames: None,
|
||||
bmiba: bmiba.try_into().ok()?,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn allocate_dma_frame(
|
||||
&mut self,
|
||||
mapper: &mut impl Mapper<Size4KiB>,
|
||||
frame_allocator: &mut BootInfoFrameAllocator,
|
||||
) -> Result<(), MapToError<Size4KiB>> {
|
||||
use x86_64::structures::paging::PageTableFlags as Flags;
|
||||
|
||||
let prdt_frame = frame_allocator
|
||||
.allocate_frame()
|
||||
.ok_or(MapToError::FrameAllocationFailed)?;
|
||||
|
||||
let buffer_frames = {
|
||||
let mut frame = frame_allocator
|
||||
.allocate_frame()
|
||||
.ok_or(MapToError::FrameAllocationFailed)?;
|
||||
while !frame.start_address().is_aligned(0x10000u64) {
|
||||
unsafe {
|
||||
frame_allocator.deallocate_frame(frame);
|
||||
}
|
||||
|
||||
frame = frame_allocator
|
||||
.allocate_frame()
|
||||
.ok_or(MapToError::FrameAllocationFailed)?;
|
||||
}
|
||||
|
||||
let mut frames = Vec::with_capacity(16);
|
||||
frames.push(frame);
|
||||
for _ in 0..15 {
|
||||
let frame = frame_allocator
|
||||
.allocate_frame()
|
||||
.ok_or(MapToError::FrameAllocationFailed)?;
|
||||
frames.push(frame);
|
||||
}
|
||||
|
||||
frames
|
||||
};
|
||||
let flags = Flags::NO_CACHE | Flags::PRESENT | Flags::WRITABLE;
|
||||
|
||||
unsafe {
|
||||
mapper
|
||||
.map_to(
|
||||
Page::containing_address(VirtAddr::new(PRDT_START)),
|
||||
prdt_frame,
|
||||
flags,
|
||||
frame_allocator,
|
||||
)?
|
||||
.flush();
|
||||
|
||||
for (i, frame) in buffer_frames.iter().enumerate() {
|
||||
mapper
|
||||
.map_to(
|
||||
Page::containing_address(VirtAddr::new(BUFFER_START + i as u64 * 0x1000)),
|
||||
*frame,
|
||||
flags,
|
||||
frame_allocator,
|
||||
)?
|
||||
.flush()
|
||||
}
|
||||
}
|
||||
|
||||
self.prdt_frame = Some(prdt_frame);
|
||||
self.buffer_frames = Some(buffer_frames);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn read(
|
||||
&mut self,
|
||||
channel: Channel,
|
||||
drive: Drive,
|
||||
lba: u64,
|
||||
sector_count: u16,
|
||||
buffer: &mut Vec<u8>,
|
||||
) -> Result<(), TryFromIntError> {
|
||||
let lba48_support = self
|
||||
.ide_devices
|
||||
.iter()
|
||||
.find(|d| d.channel == channel && d.drive == drive)
|
||||
.map(|d| d.lba48_support)
|
||||
.unwrap(); // FIXME: make this an error
|
||||
let lba48 = lba > 0xFFFFFFF && lba48_support;
|
||||
|
||||
// FIXME: make this an error
|
||||
assert!((lba48 && lba > 0xFFFFFFF) || (!lba48 && lba <= 0xFFFFFFF));
|
||||
|
||||
let byte_count = sector_count * SECTOR_SIZE;
|
||||
|
||||
// prepare PRD table
|
||||
let prd = PRDT_START as *mut PhysRegionDescriptor;
|
||||
unsafe {
|
||||
(*prd).data_buffer = self.buffer_frames.as_ref().unwrap()[0]
|
||||
.start_address()
|
||||
.as_u64()
|
||||
.try_into()?;
|
||||
(*prd).byte_count = byte_count;
|
||||
// this is the end of table
|
||||
(*prd).eot = 1 << 7;
|
||||
// this byte is reserved, we should probably set it to 0
|
||||
(*prd)._0 = 0;
|
||||
}
|
||||
|
||||
unsafe {
|
||||
self.load_prdt(channel);
|
||||
self.stop(channel);
|
||||
self.set_read(channel);
|
||||
self.clear_bmi_status(channel);
|
||||
select_drive(drive, channel);
|
||||
set_lba(channel, lba, sector_count, lba48);
|
||||
|
||||
if lba48 {
|
||||
ata_send_command(CMD_READ_DMA_EXT, channel);
|
||||
} else {
|
||||
ata_send_command(CMD_READ_DMA, channel);
|
||||
}
|
||||
|
||||
self.start(channel);
|
||||
}
|
||||
|
||||
loop {
|
||||
let status = unsafe { self.bmi_status(channel) };
|
||||
|
||||
// FIXME: error handling
|
||||
|
||||
// Bit 2 (INT) set?
|
||||
if (status >> 2) & 1 == 1 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
unsafe {
|
||||
// Stop DMA
|
||||
self.stop(channel);
|
||||
|
||||
// Clear the interrupt bit
|
||||
self.clear_bmi_status(channel);
|
||||
}
|
||||
|
||||
for i in 0..byte_count as u64 {
|
||||
let addr = (BUFFER_START + i) as *mut u8;
|
||||
buffer.push(unsafe { *addr });
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn write(
|
||||
&mut self,
|
||||
channel: Channel,
|
||||
drive: Drive,
|
||||
lba: u64,
|
||||
data: &[u8],
|
||||
) -> Result<(), TryFromIntError> {
|
||||
// FIXME: make this an error
|
||||
assert!(data.len() % SECTOR_SIZE as usize == 0);
|
||||
|
||||
let lba48_support = self
|
||||
.ide_devices
|
||||
.iter()
|
||||
.find(|d| d.channel == channel && d.drive == drive)
|
||||
.map(|d| d.lba48_support)
|
||||
.unwrap(); // FIXME: make this an error
|
||||
let lba48 = lba > 0xFFFFFFF && lba48_support;
|
||||
|
||||
// FIXME: make this an error
|
||||
assert!((lba48 && lba > 0xFFFFFFF) || (!lba48 && lba <= 0xFFFFFFF));
|
||||
|
||||
let byte_count = data.len() as u16;
|
||||
let sector_count = byte_count / SECTOR_SIZE;
|
||||
|
||||
// prepare PRD table
|
||||
let prd = PRDT_START as *mut PhysRegionDescriptor;
|
||||
unsafe {
|
||||
(*prd).data_buffer = self.buffer_frames.as_ref().unwrap()[0]
|
||||
.start_address()
|
||||
.as_u64()
|
||||
.try_into()?;
|
||||
(*prd).byte_count = byte_count;
|
||||
// this is the end of table
|
||||
(*prd).eot = 1 << 7;
|
||||
// this byte is reserved, we should probably set it to 0
|
||||
(*prd)._0 = 0;
|
||||
}
|
||||
|
||||
// copy the data over to the DMA buffer
|
||||
for i in 0..byte_count {
|
||||
let addr = (BUFFER_START + i as u64) as *mut u8;
|
||||
unsafe {
|
||||
*addr = *data.get(i as usize).unwrap_or(&0);
|
||||
}
|
||||
}
|
||||
|
||||
unsafe {
|
||||
self.load_prdt(channel);
|
||||
self.stop(channel);
|
||||
self.set_write(channel);
|
||||
self.clear_bmi_status(channel);
|
||||
select_drive(drive, channel);
|
||||
set_lba(channel, lba, sector_count, lba48);
|
||||
|
||||
if lba48 {
|
||||
ata_send_command(CMD_WRITE_DMA_EXT, channel);
|
||||
} else {
|
||||
ata_send_command(CMD_WRITE_DMA, channel);
|
||||
}
|
||||
|
||||
self.start(channel);
|
||||
}
|
||||
|
||||
loop {
|
||||
let status = unsafe { self.bmi_status(channel) };
|
||||
|
||||
// FIXME: error handling
|
||||
|
||||
// Bit 2 (INT) set?
|
||||
if (status >> 2) & 1 == 1 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
unsafe {
|
||||
// Stop DMA
|
||||
self.stop(channel);
|
||||
|
||||
// Clear the interrupt bit
|
||||
self.clear_bmi_status(channel);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn device_info(&self) -> PciDeviceInfo {
|
||||
self.device_info
|
||||
}
|
||||
|
||||
unsafe fn load_prdt(&self, channel: Channel) {
|
||||
let addr = if channel.secondary() {
|
||||
BMI_SECONDARY
|
||||
} else {
|
||||
0
|
||||
} + self.bmiba
|
||||
+ BMIDTP_OFFSET;
|
||||
Port::<u32>::new(addr).write(
|
||||
self.prdt_frame
|
||||
.unwrap()
|
||||
.start_address()
|
||||
.as_u64()
|
||||
.try_into()
|
||||
.unwrap(),
|
||||
);
|
||||
}
|
||||
|
||||
unsafe fn start(&self, channel: Channel) {
|
||||
let addr = if channel.secondary() {
|
||||
BMI_SECONDARY
|
||||
} else {
|
||||
0
|
||||
} + self.bmiba
|
||||
+ BMIC_OFFSET;
|
||||
let mut port: Port<u8> = Port::new(addr);
|
||||
let mut bmic = port.read();
|
||||
// start transfer
|
||||
bmic |= 1;
|
||||
// write the new bmic
|
||||
port.write(bmic);
|
||||
}
|
||||
|
||||
unsafe fn stop(&self, channel: Channel) {
|
||||
let addr = if channel.secondary() {
|
||||
BMI_SECONDARY
|
||||
} else {
|
||||
0
|
||||
} + self.bmiba
|
||||
+ BMIC_OFFSET;
|
||||
let mut port: Port<u8> = Port::new(addr);
|
||||
let mut bmic = port.read();
|
||||
// stop ongoing transfer
|
||||
bmic &= !1;
|
||||
// write the new bmic
|
||||
port.write(bmic);
|
||||
}
|
||||
|
||||
unsafe fn set_read(&self, channel: Channel) {
|
||||
let addr = if channel.secondary() {
|
||||
BMI_SECONDARY
|
||||
} else {
|
||||
0
|
||||
} + self.bmiba
|
||||
+ BMIC_OFFSET;
|
||||
let mut port: Port<u8> = Port::new(addr);
|
||||
let mut bmic = port.read();
|
||||
// mark bit 3 as 0 (read)
|
||||
bmic &= !(1 << 3);
|
||||
// write the new bmic
|
||||
port.write(bmic);
|
||||
}
|
||||
|
||||
unsafe fn set_write(&self, channel: Channel) {
|
||||
let addr = if channel.secondary() {
|
||||
BMI_SECONDARY
|
||||
} else {
|
||||
0
|
||||
} + self.bmiba
|
||||
+ BMIC_OFFSET;
|
||||
let mut port: Port<u8> = Port::new(addr);
|
||||
let mut bmic = port.read();
|
||||
// mark bit 3 as 1 (write)
|
||||
bmic |= 1 << 3;
|
||||
// write the new bmic
|
||||
port.write(bmic);
|
||||
}
|
||||
|
||||
unsafe fn bmi_status(&self, channel: Channel) -> u8 {
|
||||
let addr = if channel.secondary() {
|
||||
BMI_SECONDARY
|
||||
} else {
|
||||
0
|
||||
} + self.bmiba
|
||||
+ BMIS_OFFSET;
|
||||
let mut port = Port::new(addr);
|
||||
port.read()
|
||||
}
|
||||
|
||||
unsafe fn clear_bmi_status(&self, channel: Channel) {
|
||||
let addr = if channel.secondary() {
|
||||
BMI_SECONDARY
|
||||
} else {
|
||||
0
|
||||
} + self.bmiba
|
||||
+ BMIS_OFFSET;
|
||||
let mut port: Port<u8> = Port::new(addr);
|
||||
let mut bmis = port.read();
|
||||
// write 1 to bits 1 (DMA error) and 2 (int status) which clears them
|
||||
bmis |= 1 << 1 | 1 << 2;
|
||||
// write the new bmis
|
||||
port.write(bmis);
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn select_drive(drive: Drive, channel: Channel) {
|
||||
let addr = if channel.secondary() {
|
||||
SECONDARY_COMMAND
|
||||
} else {
|
||||
PRIMARY_COMMAND
|
||||
} + DRIVE_HEAD_OFFSET;
|
||||
let mut port: Port<u8> = Port::new(addr);
|
||||
// FIXME: CHS support
|
||||
let drive_command = if drive.slave() {
|
||||
// slave & LBA
|
||||
0b11110000
|
||||
} else {
|
||||
// master & LBA
|
||||
0b11100000
|
||||
};
|
||||
|
||||
// write the new drive/head register
|
||||
port.write(drive_command);
|
||||
ata_delay(channel);
|
||||
}
|
||||
|
||||
/// Send ATA command and read status afterwards
|
||||
unsafe fn ata_send_command(command: u8, channel: Channel) -> u8 {
|
||||
let addr = if channel.secondary() {
|
||||
SECONDARY_COMMAND
|
||||
} else {
|
||||
PRIMARY_COMMAND
|
||||
} + COMMAND_STATUS_OFFSET;
|
||||
let mut port = Port::new(addr);
|
||||
port.write(command);
|
||||
ata_delay(channel);
|
||||
port.read()
|
||||
}
|
||||
|
||||
/// Read the alternate status register 14 times to create a ~420ns delay
|
||||
unsafe fn ata_delay(channel: Channel) {
|
||||
let addr = if channel.secondary() {
|
||||
SECONDARY_CONTROL
|
||||
} else {
|
||||
PRIMARY_CONTROL
|
||||
} + ALT_STATUS_OFFSET;
|
||||
let mut port: Port<u8> = Port::new(addr);
|
||||
for _ in 0..14 {
|
||||
port.read();
|
||||
}
|
||||
}
|
||||
|
||||
/// Set LBA and sector count registers. sector_count of 0 means 65536 sectors
|
||||
unsafe fn set_lba(channel: Channel, lba: u64, sector_count: u16, lba48: bool) {
|
||||
let command_block = if channel.secondary() {
|
||||
SECONDARY_COMMAND
|
||||
} else {
|
||||
PRIMARY_COMMAND
|
||||
};
|
||||
|
||||
let mut seccount = Port::new(command_block + SECCOUNT_OFFSET);
|
||||
let mut lba0 = Port::new(command_block + LBA0_OFFSET);
|
||||
let mut lba1 = Port::new(command_block + LBA1_OFFSET);
|
||||
let mut lba2 = Port::new(command_block + LBA2_OFFSET);
|
||||
let mut head = Port::new(command_block + DRIVE_HEAD_OFFSET);
|
||||
let head_value: u8 = head.read();
|
||||
|
||||
let lba_bytes = lba.to_le_bytes();
|
||||
let sector_count_bytes = sector_count.to_le_bytes();
|
||||
|
||||
// write the new LBA & sector count registers
|
||||
// FIXME: CHS support
|
||||
if lba48 {
|
||||
seccount.write(sector_count_bytes[1]);
|
||||
lba0.write(lba_bytes[3]);
|
||||
lba1.write(lba_bytes[4]);
|
||||
lba2.write(lba_bytes[5]);
|
||||
} else {
|
||||
head.write(head_value | (lba_bytes[3] & 0x0F));
|
||||
}
|
||||
seccount.write(sector_count_bytes[0]);
|
||||
lba0.write(lba_bytes[0]);
|
||||
lba1.write(lba_bytes[1]);
|
||||
lba2.write(lba_bytes[2]);
|
||||
}
|
||||
|
||||
unsafe fn read_dword_buffer(port: u16, buffer: *mut u32, mut count: u32) {
|
||||
// FIXME: this assumes x86-64
|
||||
interrupts::without_interrupts(|| {
|
||||
asm!("
|
||||
cld
|
||||
repne
|
||||
insd",
|
||||
in("di") buffer,
|
||||
in("dx") port,
|
||||
inout("cx") count,
|
||||
)
|
||||
});
|
||||
}
|
||||
|
||||
struct IdeDevice {
|
||||
pub channel: Channel,
|
||||
pub drive: Drive,
|
||||
pub size: u64, // in sectors
|
||||
pub lba48_support: bool,
|
||||
// FIXME: model
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub enum Channel {
|
||||
Primary,
|
||||
Secondary,
|
||||
}
|
||||
|
||||
impl Channel {
|
||||
fn secondary(&self) -> bool {
|
||||
matches!(self, Self::Secondary)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub enum Drive {
|
||||
Master,
|
||||
Slave,
|
||||
}
|
||||
|
||||
impl Drive {
|
||||
fn slave(&self) -> bool {
|
||||
matches!(self, Self::Slave)
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C, packed)]
|
||||
struct PhysRegionDescriptor {
|
||||
/// Pointer to the data buffer
|
||||
pub data_buffer: u32,
|
||||
/// Byte count, 64K maximum per PRD transfer. 0 means 64K
|
||||
pub byte_count: u16,
|
||||
/// Reserved byte
|
||||
pub _0: u8,
|
||||
/// MSB marks end of transfer
|
||||
pub eot: u8,
|
||||
}
|
|
@ -1,71 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2022, Umut İnan Erdoğan <umutinanerdogan@pm.me>
|
||||
*
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
pub mod class;
|
||||
pub mod device;
|
||||
pub mod vendors;
|
||||
|
||||
// MassStorage_IDE (0x0101)
|
||||
pub mod ide;
|
||||
|
||||
use alloc::sync::Arc;
|
||||
pub use class::*;
|
||||
pub use device::*;
|
||||
use lazy_static::lazy_static;
|
||||
use spin::Mutex;
|
||||
use x86_64::structures::paging::{Mapper, Size4KiB};
|
||||
|
||||
use crate::arch::memory::BootInfoFrameAllocator;
|
||||
|
||||
// MassStorage_IDE (0x0101)
|
||||
use self::ide::PciIde;
|
||||
|
||||
lazy_static! {
|
||||
pub static ref PCI_DEVICES: Mutex<Vec<Arc<Mutex<PciDevice>>>> = Default::default();
|
||||
}
|
||||
|
||||
#[non_exhaustive]
|
||||
pub enum PciDevice {
|
||||
Ide(PciIde),
|
||||
// Variant so that we aren't about irrefutable if-let patterns
|
||||
// FIXME: remove as soon as we have other variants
|
||||
_0,
|
||||
}
|
||||
|
||||
/// Enumerate PCI devices and run initialisation routines on ones we support
|
||||
pub fn init(mapper: &mut impl Mapper<Size4KiB>, frame_allocator: &mut BootInfoFrameAllocator) {
|
||||
for bus in 0..=255 {
|
||||
for device in 0..32 {
|
||||
if let Some(device_info) = device::check_device(bus, device) {
|
||||
trace!("{device_info}");
|
||||
match device_info.device_id {
|
||||
// FIXME: Unknown class
|
||||
S3_TRIO64V2 => {}
|
||||
|
||||
// MassStorage_IDE (0x0101)
|
||||
ide_controller if device_info.full_class == PciFullClass::MassStorage_IDE => {
|
||||
if !matches!(ide_controller, INTEL_PIIX3_IDE | INTEL_PIIX4_IDE) {
|
||||
// not one of our tested IDE controllers, but
|
||||
// we shouldn't have any problems
|
||||
warn!("Unsupported PCI IDE controller device {device} on bus {bus}")
|
||||
}
|
||||
|
||||
let mut ide = PciIde::new(bus, device).unwrap();
|
||||
ide.allocate_dma_frame(mapper, frame_allocator).unwrap();
|
||||
let mut devices = PCI_DEVICES.lock();
|
||||
devices.push(Arc::new(Mutex::new(PciDevice::Ide(ide))));
|
||||
}
|
||||
|
||||
// Display_VGA (0x0300)
|
||||
VMWARE_SVGA2 => {}
|
||||
_ => {
|
||||
trace!("Unknown PCI device {device} on bus {bus}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,180 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2022, able <abl3theabove@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
use core::fmt::Display;
|
||||
|
||||
#[derive(PartialEq, Debug, Copy, Clone, Eq)]
|
||||
#[repr(u16)]
|
||||
pub enum Vendor {
|
||||
ThreeDfxInteractiveInc = 0x121a,
|
||||
ThreeDLabs = 0x3d3d,
|
||||
AllianceSemiconductorCorp = 0x1142,
|
||||
ARKLogicInc = 0xedd8,
|
||||
ATITechnologiesInc = 0x1002,
|
||||
AvanceLogicIncALI = 0x1005,
|
||||
ChipsandTechnologies = 0x102c,
|
||||
CirrusLogic = 0x1013,
|
||||
Compaq = 0x0e11,
|
||||
CyrixCorp = 0x1078,
|
||||
DiamondMultimediaSystems = 0x1092,
|
||||
DigitalEquipmentCorp = 0x1011,
|
||||
Iit = 0x1061,
|
||||
IntegratedMicroSolutionsInc = 0x10e0,
|
||||
IntelCorp = 0x8086,
|
||||
IntergraphicsSystems = 0x10ea,
|
||||
MacronixInc = 0x10d9,
|
||||
MatroxGraphicsInc = 0x102b,
|
||||
MiroComputersProductsAG = 0x1031,
|
||||
NationalSemiconductorCorp = 0x100b,
|
||||
NeoMagicCorp = 0x10c8,
|
||||
Number9ComputerCompany = 0x105d,
|
||||
NVidiaCorporation = 0x10de,
|
||||
NVidiaSgsthomson = 0x12d2,
|
||||
OakTechnologyInc = 0x104e,
|
||||
Qemu = 0x1234,
|
||||
QuantumDesignsHKLtd = 0x1098,
|
||||
Real3D = 0x003d,
|
||||
Rendition = 0x1163,
|
||||
S3Inc = 0x5333,
|
||||
SierraSemiconductor = 0x10a8,
|
||||
SiliconIntegratedSystemsSiS = 0x1039,
|
||||
SiliconMotionInc = 0x126f,
|
||||
STBSystemsInc = 0x10b4,
|
||||
TexasInstruments = 0x104c,
|
||||
ToshibaAmericaInfoSystems = 0x1179,
|
||||
TridentMicrosystems = 0x1023,
|
||||
TsengLabsInc = 0x100c,
|
||||
TundraSemiconductorCorp = 0x10e3,
|
||||
VIATechnologiesInc = 0x1106,
|
||||
VirtIO = 0x1AF4,
|
||||
VMWareInc = 0x15ad,
|
||||
Weitek = 0x100e,
|
||||
Unknown(u16),
|
||||
}
|
||||
|
||||
impl From<u16> for Vendor {
|
||||
fn from(vendor_id: u16) -> Self {
|
||||
use Vendor::*;
|
||||
match vendor_id {
|
||||
0x121a => ThreeDfxInteractiveInc,
|
||||
0x3d3d => ThreeDLabs,
|
||||
0x1142 => AllianceSemiconductorCorp,
|
||||
0xedd8 => ARKLogicInc,
|
||||
0x1002 => ATITechnologiesInc,
|
||||
0x1005 => AvanceLogicIncALI,
|
||||
0x102c => ChipsandTechnologies,
|
||||
0x1013 => CirrusLogic,
|
||||
0x0e11 => Compaq,
|
||||
0x1078 => CyrixCorp,
|
||||
0x1092 => DiamondMultimediaSystems,
|
||||
0x1011 => DigitalEquipmentCorp,
|
||||
0x1061 => Iit,
|
||||
0x10e0 => IntegratedMicroSolutionsInc,
|
||||
0x8086 => IntelCorp,
|
||||
0x10ea => IntergraphicsSystems,
|
||||
0x10d9 => MacronixInc,
|
||||
0x102b => MatroxGraphicsInc,
|
||||
0x1031 => MiroComputersProductsAG,
|
||||
0x100b => NationalSemiconductorCorp,
|
||||
0x10c8 => NeoMagicCorp,
|
||||
0x105d => Number9ComputerCompany,
|
||||
0x10de => NVidiaCorporation,
|
||||
0x12d2 => NVidiaSgsthomson,
|
||||
0x104e => OakTechnologyInc,
|
||||
0x1234 => Qemu,
|
||||
0x1098 => QuantumDesignsHKLtd,
|
||||
0x003d => Real3D,
|
||||
0x1163 => Rendition,
|
||||
0x5333 => S3Inc,
|
||||
0x10a8 => SierraSemiconductor,
|
||||
0x1039 => SiliconIntegratedSystemsSiS,
|
||||
0x126f => SiliconMotionInc,
|
||||
0x10b4 => STBSystemsInc,
|
||||
0x104c => TexasInstruments,
|
||||
0x1179 => ToshibaAmericaInfoSystems,
|
||||
0x1023 => TridentMicrosystems,
|
||||
0x100c => TsengLabsInc,
|
||||
0x10e3 => TundraSemiconductorCorp,
|
||||
0x1106 => VIATechnologiesInc,
|
||||
0x1AF4 => VirtIO,
|
||||
0x15ad => VMWareInc,
|
||||
0x100e => Weitek,
|
||||
id => Unknown(id),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<u16> for Vendor {
|
||||
fn into(self) -> u16 {
|
||||
use Vendor::*;
|
||||
match self {
|
||||
ThreeDfxInteractiveInc => 0x121a,
|
||||
ThreeDLabs => 0x3d3d,
|
||||
AllianceSemiconductorCorp => 0x1142,
|
||||
ARKLogicInc => 0xedd8,
|
||||
ATITechnologiesInc => 0x1002,
|
||||
AvanceLogicIncALI => 0x1005,
|
||||
ChipsandTechnologies => 0x102c,
|
||||
CirrusLogic => 0x1013,
|
||||
Compaq => 0x0e11,
|
||||
CyrixCorp => 0x1078,
|
||||
DiamondMultimediaSystems => 0x1092,
|
||||
DigitalEquipmentCorp => 0x1011,
|
||||
Iit => 0x1061,
|
||||
IntegratedMicroSolutionsInc => 0x10e0,
|
||||
IntelCorp => 0x8086,
|
||||
IntergraphicsSystems => 0x10ea,
|
||||
MacronixInc => 0x10d9,
|
||||
MatroxGraphicsInc => 0x102b,
|
||||
MiroComputersProductsAG => 0x1031,
|
||||
NationalSemiconductorCorp => 0x100b,
|
||||
NeoMagicCorp => 0x10c8,
|
||||
Number9ComputerCompany => 0x105d,
|
||||
NVidiaCorporation => 0x10de,
|
||||
NVidiaSgsthomson => 0x12d2,
|
||||
OakTechnologyInc => 0x104e,
|
||||
Qemu => 0x1234,
|
||||
QuantumDesignsHKLtd => 0x1098,
|
||||
Real3D => 0x003d,
|
||||
Rendition => 0x1163,
|
||||
S3Inc => 0x5333,
|
||||
SierraSemiconductor => 0x10a8,
|
||||
SiliconIntegratedSystemsSiS => 0x1039,
|
||||
SiliconMotionInc => 0x126f,
|
||||
STBSystemsInc => 0x10b4,
|
||||
TexasInstruments => 0x104c,
|
||||
ToshibaAmericaInfoSystems => 0x1179,
|
||||
TridentMicrosystems => 0x1023,
|
||||
TsengLabsInc => 0x100c,
|
||||
TundraSemiconductorCorp => 0x10e3,
|
||||
VIATechnologiesInc => 0x1106,
|
||||
VirtIO => 0x1AF4,
|
||||
VMWareInc => 0x15ad,
|
||||
Weitek => 0x100e,
|
||||
Unknown(id) => id,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Vendor {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
use Vendor::*;
|
||||
|
||||
match self {
|
||||
Qemu => write!(f, "{}", "\0PINK\0QEMU (0x1234)"),
|
||||
VirtIO => write!(f, "{}", "\0PINK\0VirtIO (0x1AF4)"),
|
||||
VMWareInc => write!(f, "{}", "\0PINK\0VMWARE (0x15AD)"),
|
||||
S3Inc => write!(f, "{}", "\0YELLOW\0S3 Incorporated (0x5333)"),
|
||||
IntelCorp => write!(f, "{}", "\0BLUE\0Intel Corp. (0x8086)"),
|
||||
ATITechnologiesInc => write!(f, "{}", "\0RED\0ATI (0x1002)"),
|
||||
Unknown(id) => write!(f, "\0RED\0Unknown ({:#6})", id),
|
||||
other => write!(f, "{other:?}"),
|
||||
}?;
|
||||
|
||||
write!(f, "\0RESET\0")?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
#![allow(unused)]
|
||||
|
||||
pub const REFRESH_RATE: u8 = 60;
|
||||
|
||||
pub type RefreshRate = u8;
|
||||
pub type Resolution = (usize, usize);
|
||||
pub type Point = (GCoord, GCoord);
|
||||
pub type GCoord = usize;
|
||||
|
||||
pub enum GModes {
|
||||
Vga800x600,
|
||||
Custom(u16, u16),
|
||||
}
|
||||
|
||||
// TODO remap to a bitmasked u32
|
||||
// REASON: More effecient memory wise so less overhead on the wasm memory
|
||||
// Current: u32+u32+u32
|
||||
// Proposed: u32 with bitmaps
|
||||
pub struct Rgb {
|
||||
pub r: u32,
|
||||
pub g: u32,
|
||||
pub b: u32,
|
||||
}
|
||||
|
||||
impl Rgb {
|
||||
fn to_vga_color() {
|
||||
todo!();
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FrameBuffer;
|
||||
pub trait Graphics {
|
||||
fn put_line(coords_start: Point, coords_end: Point, thickness: u32, color: Rgb);
|
||||
fn put_rect(coords_start: Point, coords_end: Point, color: Rgb);
|
||||
fn put_circle(coords: Point, radius: u32);
|
||||
fn put_pixel(coords: Point, color: Rgb);
|
||||
fn put_triangle(coords_1: Point, coords_2: Point, coords_3: Point, thickness: u32, color: Rgb);
|
||||
fn paint_cursor(coords: Point);
|
||||
fn hide_cursor();
|
||||
fn show_cursor();
|
||||
/// Actually move the double buffer to the single buffer and "update" the screen
|
||||
fn draw();
|
||||
fn clear();
|
||||
}
|
|
@ -1,2 +0,0 @@
|
|||
pub mod graphics;
|
||||
pub mod serial;
|
|
@ -1,16 +0,0 @@
|
|||
// TODO: Bitmasking
|
||||
pub enum Mouse {
|
||||
Button1,
|
||||
Button2,
|
||||
Button3,
|
||||
Button4,
|
||||
Button5,
|
||||
X(i8),
|
||||
Y(i8),
|
||||
Wheel(i8),
|
||||
}
|
||||
|
||||
pub trait PS2Mouse {
|
||||
fn movement();
|
||||
fn button();
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
use crate::device_interface::CharacterDevice;
|
||||
|
||||
pub struct Serial {
|
||||
pub base: usize,
|
||||
}
|
||||
|
||||
impl CharacterDevice for Serial {
|
||||
fn can_read(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn can_write(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn read_char(&mut self) -> Option<char> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn write_char(&mut self, _c: char) -> bool {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn reset(&mut self) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn initialize(&mut self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_serial_test() {
|
||||
let mut serial = Serial { base: 0x3F8 };
|
||||
serial.initialize();
|
||||
serial.write_char('a');
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
Anything in experiments is heavily unstable and likely to change
|
|
@ -1,107 +0,0 @@
|
|||
use logos::{Lexer, Logos};
|
||||
|
||||
// TODO improve tokenizer/parser
|
||||
pub fn colorify(eval: &str) {
|
||||
let y = eval.split('$');
|
||||
for z in y {
|
||||
match z {
|
||||
"BLACK" => {
|
||||
// set_vga_color(Color::Black, Color::Black);
|
||||
}
|
||||
"RED" => {
|
||||
// set_vga_color(Color::Red, Color::Black);
|
||||
}
|
||||
"GREEN" => {
|
||||
// set_vga_color(Color::Green, Color::Black);
|
||||
}
|
||||
"BLUE" => {
|
||||
// set_vga_color(Color::Blue, Color::Black);
|
||||
}
|
||||
"CYAN" => {
|
||||
// set_vga_color(Color::Cyan, Color::Black);
|
||||
}
|
||||
"MAGENTA" => {
|
||||
// set_vga_color(Color::Magenta, Color::Black);
|
||||
}
|
||||
"BROWN" => {
|
||||
// set_vga_color(Color::Brown, Color::Black);
|
||||
}
|
||||
"LIGHTGRAY" => {
|
||||
// set_vga_color(Color::LightGray, Color::Black);
|
||||
}
|
||||
"DARKGRAY" => {
|
||||
// set_vga_color(Color::DarkGray, Color::Black);
|
||||
}
|
||||
"LIGHTBLUE" => {
|
||||
// set_vga_color(Color::LightBlue, Color::Black);
|
||||
}
|
||||
"LIGHTGREEN" => {
|
||||
// set_vga_color(Color::LightGreen, Color::Black);
|
||||
}
|
||||
"LIGHTCYAN" => {
|
||||
// set_vga_color(Color::LightCyan, Color::Black);
|
||||
}
|
||||
"LIGHTRED" => {
|
||||
// set_vga_color(Color::LightRed, Color::Black);
|
||||
}
|
||||
"PINK" => {
|
||||
// set_vga_color(Color::Pink, Color::Black);
|
||||
}
|
||||
"YELLOW" => {
|
||||
// set_vga_color(Color::Yellow, Color::Black);
|
||||
}
|
||||
"WHITE" => {
|
||||
// set_vga_color(Color::White, Color::Black);
|
||||
}
|
||||
"RESET" => {
|
||||
// set_vga_color(Color::White, Color::Black);
|
||||
}
|
||||
_elk => {
|
||||
// kprint!("{}", elk);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Logos, Debug, PartialEq)]
|
||||
pub enum Token {
|
||||
// Hex(u32),
|
||||
#[regex(r"\$RED\$")]
|
||||
Red,
|
||||
|
||||
#[regex(r"\$RESET\$")]
|
||||
Reset,
|
||||
|
||||
#[regex("[a-zA-Z!@#$%^&*\">()\n ]+", parse_text, priority = 2)]
|
||||
Text(String),
|
||||
|
||||
#[error]
|
||||
#[regex(r"[ \t\n\f]+", logos::skip)]
|
||||
Error,
|
||||
}
|
||||
|
||||
pub fn colorify_2(eval: &str) {
|
||||
let lexer = Token::lexer(eval);
|
||||
for token in lexer {
|
||||
use Token::*;
|
||||
match token {
|
||||
Red => {
|
||||
// set_vga_color(Color::Red, Color::Black);
|
||||
}
|
||||
Reset => {
|
||||
// set_vga_color(Color::White, Color::Black);
|
||||
}
|
||||
Text(_text) => {
|
||||
// kprint!("{}", text);
|
||||
}
|
||||
err => {
|
||||
error!("Error parsing {:?}", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_text(lex: &mut Lexer<Token>) -> Option<String> {
|
||||
let slice = lex.slice();
|
||||
Some(String::from(slice))
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
##### #####
|
||||
## ##### # ###### ## ## # #
|
||||
# # # # # # # # #
|
||||
# # ##### # ##### # # #####
|
||||
###### # # # # # # #
|
||||
# # # # # # ## ## # #
|
||||
# # ##### ###### ###### ##### #####
|
|
@ -1,53 +0,0 @@
|
|||
use alloc::{string::String, vec, vec::Vec};
|
||||
|
||||
pub static CLIPBOARD: spin::Mutex<Clipboard> = spin::Mutex::new(Clipboard::new());
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Mime {
|
||||
None,
|
||||
Text(String),
|
||||
}
|
||||
|
||||
// ctrl+v paste but not pop and pastes
|
||||
// ctrl+shift+v pops from the stack and pastes
|
||||
// ctrl+c pushes to the stack
|
||||
// ctrl+shift+< move stack pointer left
|
||||
// ctrl+shift+> move stack pointer right
|
||||
|
||||
pub struct Clipboard {
|
||||
pub index: usize,
|
||||
pub pages: Vec<Mime>,
|
||||
}
|
||||
|
||||
impl Clipboard {
|
||||
pub const fn new() -> Clipboard {
|
||||
Clipboard {
|
||||
index: 0,
|
||||
pages: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clear(&mut self) {
|
||||
self.pages = vec![];
|
||||
}
|
||||
|
||||
pub fn set_index(&mut self, index_new: usize) {
|
||||
self.index = index_new;
|
||||
}
|
||||
|
||||
pub fn clip_end(&mut self) {
|
||||
self.index = 0;
|
||||
}
|
||||
|
||||
pub fn clip_home(&mut self) {
|
||||
self.index = self.pages.len();
|
||||
}
|
||||
|
||||
pub fn copy(&mut self, copy_mime: Mime) {
|
||||
self.pages.push(copy_mime);
|
||||
}
|
||||
|
||||
pub fn paste(&mut self) -> &Mime {
|
||||
&self.pages[self.index] as _
|
||||
}
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
struct Permissions {
|
||||
write_files: bool,
|
||||
read_files: bool,
|
||||
execute_files: bool,
|
||||
// Every other user is part of global
|
||||
global_write_files: bool,
|
||||
global_read_files: bool,
|
||||
global_execute_files: bool,
|
||||
}
|
||||
|
||||
pub struct File {
|
||||
owner: u8,
|
||||
permissions: Permissions,
|
||||
data: Vec<u8>,
|
||||
}
|
||||
|
||||
pub struct Folder {
|
||||
owner: u8,
|
||||
permissions: Permissions,
|
||||
folders: Vec<Folder>,
|
||||
files: Vec<File>,
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
<user>/home/app1
|
||||
<user>/conf/app1
|
||||
<user>/apps/app1
|
||||
|
||||
file:app1
|
||||
conf:app1
|
||||
apps:app1
|
||||
// Discouraged
|
||||
raw:
|
||||
|
||||
/<user>/<protocol>/app1
|
||||
protocol.toml
|
||||
|
||||
|
||||
hi = ""
|
|
@ -1,57 +0,0 @@
|
|||
use core::time::Duration;
|
||||
|
||||
pub struct AtomicU32(u32);
|
||||
impl AtomicU32 {
|
||||
//if v != current value
|
||||
pub fn wait(&self, _v: u32) {
|
||||
todo!();
|
||||
}
|
||||
|
||||
pub fn wait_timeout(&self, _v: u32, _timeout: Duration) -> bool {
|
||||
todo!();
|
||||
}
|
||||
pub fn wake_single(&self) {
|
||||
todo!();
|
||||
}
|
||||
pub fn wake_all(&self) {
|
||||
todo!();
|
||||
}
|
||||
}
|
||||
/*
|
||||
// SUPER HANDWAVEY
|
||||
// YOU WILL NEED LOCKING THAT I DIDNT WRITE OUT (you == zuurr#9735)
|
||||
|
||||
// all the red is by design
|
||||
pub fn futex_wait(atom: &AtomicU32, value: usize, current_thread: ThreadID) {
|
||||
let address = atomic as *const _ as usize;
|
||||
let waiters = waiters_for(address); // Hold lock
|
||||
waiters.add(current_thread);
|
||||
if self.load() == value {
|
||||
current_thread.sleep();
|
||||
} else {
|
||||
waiters.remove(current_thread);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn futex_wake(atom: &AtomicU32, threads_to_wake: usize) {
|
||||
let address = atomic as *const _ as usize;
|
||||
let waiters = waiters_for(address);
|
||||
for waiting_thread in waiters.into_iter().take(threads_to_wake) {
|
||||
waiting_thread.wake()
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
struct FutexWaitlist {
|
||||
address: u8,
|
||||
// data: Vec<ThreadID>,
|
||||
}
|
||||
|
||||
impl FutexWaitlist {
|
||||
pub fn remove(&mut self) {
|
||||
todo!();
|
||||
}
|
||||
pub fn add(&mut self) {
|
||||
todo!();
|
||||
}
|
||||
}
|
|
@ -1,75 +0,0 @@
|
|||
use super::systeminfo::SystemMemory;
|
||||
use crate::arch::drivers::sysinfo::master;
|
||||
use core::fmt::Display;
|
||||
use kernel::allocator::ALLOCATOR;
|
||||
use versioning::Version;
|
||||
use x86_64::instructions::interrupts::{disable, enable};
|
||||
|
||||
pub enum CpuType {
|
||||
RiscV(String),
|
||||
X86_64(String),
|
||||
}
|
||||
impl Display for CpuType {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"{}",
|
||||
match self {
|
||||
CpuType::RiscV(s) => s,
|
||||
CpuType::X86_64(s) => s,
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// simple info you would want to know in a neofetch like program
|
||||
pub struct KernelInfo {
|
||||
// os: String,
|
||||
// host: String,
|
||||
pub kernel_version: Version,
|
||||
pub cpu: CpuType,
|
||||
// gpu: String,
|
||||
pub memory: SystemMemory,
|
||||
}
|
||||
|
||||
impl KernelInfo {
|
||||
pub fn get() -> KernelInfo {
|
||||
disable();
|
||||
let allocator = ALLOCATOR.lock();
|
||||
let total = allocator.size();
|
||||
let used = allocator.used();
|
||||
enable();
|
||||
|
||||
let cpu = CpuType::X86_64(master().unwrap().brand_string().unwrap().to_string());
|
||||
KernelInfo {
|
||||
kernel_version: Version {
|
||||
major: 0,
|
||||
minor: 0,
|
||||
patch: 0,
|
||||
},
|
||||
cpu,
|
||||
memory: SystemMemory { total, used },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for KernelInfo {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"
|
||||
OS: AbleOS
|
||||
Host: {{}}
|
||||
Kernel: {}.{}.{}
|
||||
CPU: {}
|
||||
Memory: {}/{}
|
||||
",
|
||||
self.kernel_version.major,
|
||||
self.kernel_version.minor,
|
||||
self.kernel_version.patch,
|
||||
self.cpu,
|
||||
self.memory.used,
|
||||
self.memory.total
|
||||
)
|
||||
}
|
||||
}
|
|
@ -1,113 +0,0 @@
|
|||
#![allow(dead_code)]
|
||||
// TODO: Evaluate variable sized mailboxes
|
||||
|
||||
pub struct MailBoxes {
|
||||
flags: u8,
|
||||
mailboxes: [u64; 4],
|
||||
}
|
||||
|
||||
impl MailBoxes {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
flags: 0b0000_0000,
|
||||
mailboxes: [0; 4],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reset(&mut self) {
|
||||
self.flags = 0b0000_0000;
|
||||
self.mailboxes = [0; 4];
|
||||
}
|
||||
|
||||
pub fn set_mailbox(&mut self, mailbox_num: u8, mailbox_data: u64) {
|
||||
if let 0..=3 = mailbox_num {
|
||||
self.mailboxes[mailbox_num as usize] = mailbox_data
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_flag(&mut self, flag_num: u8) {
|
||||
match flag_num {
|
||||
0 => {
|
||||
self.flags |= 0b0000_0001;
|
||||
}
|
||||
1 => {
|
||||
self.flags |= 0b0000_0010;
|
||||
}
|
||||
2 => {
|
||||
self.flags |= 0b0000_0100;
|
||||
}
|
||||
3 => {
|
||||
self.flags |= 0b0000_1000;
|
||||
}
|
||||
4 => {
|
||||
self.flags |= 0b0001_0000;
|
||||
}
|
||||
5 => {
|
||||
self.flags |= 0b0010_0000;
|
||||
}
|
||||
6 => {
|
||||
self.flags |= 0b0100_0000;
|
||||
}
|
||||
7 => {
|
||||
self.flags |= 0b1000_0000;
|
||||
}
|
||||
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
pub fn dump_flags(&self) {
|
||||
trace!(
|
||||
"Flag 0: {:08b} | {}",
|
||||
self.flags & 0b0000_0001,
|
||||
self.flags & 0b0000_0001
|
||||
);
|
||||
|
||||
trace!(
|
||||
"Flag 1: {:08b} | {}",
|
||||
self.flags & 0b0000_0010,
|
||||
self.flags >> 1 & 0b0000_0001
|
||||
);
|
||||
|
||||
trace!(
|
||||
"Flag 2: {:08b} | {}",
|
||||
self.flags & 0b0000_0100,
|
||||
self.flags >> 2 & 0b0000_0001
|
||||
);
|
||||
|
||||
trace!(
|
||||
"Flag 3: {:08b} | {}",
|
||||
self.flags & 0b0000_1000,
|
||||
self.flags >> 3 & 0b0000_0001
|
||||
);
|
||||
|
||||
trace!(
|
||||
"Flag 4: {:08b} | {}",
|
||||
self.flags & 0b0001_0000,
|
||||
self.flags >> 4 & 0b0000_0001
|
||||
);
|
||||
|
||||
trace!(
|
||||
"Flag 5: {:08b} | {}",
|
||||
self.flags & 0b0010_0000,
|
||||
self.flags >> 5 & 0b0000_0001
|
||||
);
|
||||
|
||||
trace!(
|
||||
"Flag 6: {:08b} | {}",
|
||||
self.flags & 0b0100_0000,
|
||||
self.flags >> 6 & 0b0000_0001
|
||||
);
|
||||
|
||||
trace!(
|
||||
"Flag 7: {:08b} | {}",
|
||||
self.flags & 0b1000_0000,
|
||||
self.flags >> 7 & 0b0000_0001
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for MailBoxes {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
#![allow(dead_code)]
|
||||
|
||||
pub mod absi;
|
||||
pub mod clip;
|
||||
pub mod futex;
|
||||
pub mod kinfo;
|
||||
pub mod mail;
|
||||
pub mod server;
|
||||
pub mod systeminfo;
|
||||
pub mod virtual_memory;
|
||||
pub mod y_compositor;
|
||||
|
||||
pub const BANNER: &str = include_str!("banner.txt");
|
|
@ -1,7 +0,0 @@
|
|||
pub type thumbnail = u8;
|
||||
|
||||
pub struct Notification {
|
||||
thumbnail: thumbnail,
|
||||
text_body: String,
|
||||
time: u64,
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
use crate::experiments::kinfo::SemanticVersion;
|
||||
|
||||
// Scuffed
|
||||
pub type Hash = u8;
|
||||
pub type PackageName = String;
|
||||
|
||||
pub struct MetaPackage {
|
||||
pub name: u8,
|
||||
pub version: SemanticVersion,
|
||||
pub authors: [u8; 8],
|
||||
pub support_email: u8,
|
||||
pub hash: Hash,
|
||||
}
|
||||
|
||||
impl MetaPackage {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
name: 0,
|
||||
version: SemanticVersion {
|
||||
major: 0,
|
||||
minor: 0,
|
||||
patch: 0,
|
||||
},
|
||||
authors: [0; 8],
|
||||
support_email: 8,
|
||||
hash: 0,
|
||||
}
|
||||
}
|
||||
|
||||
fn validate_hash(&self) {}
|
||||
}
|
||||
|
||||
impl core::fmt::Display {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"Packname: {}
|
||||
Version: {}
|
||||
Authors: {:?}
|
||||
Support Email: {}
|
||||
Hash: {}",
|
||||
self.name, self.version, self.authors, self.support_email, self.hash
|
||||
)
|
||||
}
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
pub trait Server {
|
||||
/// Initialize the server and return a number
|
||||
fn initialize() -> u32;
|
||||
|
||||
/// kill the server
|
||||
fn kill() -> bool;
|
||||
|
||||
// put data in the servers outbox
|
||||
fn send();
|
||||
|
||||
// put data in the servers inbox and notify it
|
||||
fn recieve();
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
|
||||
| low \\ high | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F |
|
||||
| ----------- | ------------------- | ------------------------ | ------------------------------------------------------------------------------------------ | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- |
|
||||
| 0 | **kill** | <sub>reserved</sub> | **sleep** | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> |
|
||||
| 1 | **stdout_reset** | <sub>reserved</sub> | **sleep_until** | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> |
|
||||
| 2 | **stdin** | <sub>reserved</sub> | [**nanosleep**](https://www.reddit.com/r/anime/comments/e7sg7g/nichijou_trouble_sleeping/) | **aes_encrypt** | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> |
|
||||
| 3 | **stdout** | <sub>reserved</sub> | **nanosleep_until** | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> |
|
||||
| 4 | **stdin_get_title** | <sub>reserved</sub> | **get_time** | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> |
|
||||
| 5 | **stdin_set_title** | <sub>reserved</sub> | **set_time** | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> |
|
||||
| 6 | **get_pid** | **make_directory** | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> |
|
||||
| 7 | **pinfo** | **delete_directory** | **socket_bind** | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> |
|
||||
| 8 | <sub>reserved</sub> | **rename_directory** | **socket_connect** | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> |
|
||||
| 9 | <sub>reserved</sub> | **set_directory_access** | **socket_disconnect** | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> |
|
||||
| A | **set_priority** | **make_file** | **socket_send** | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> |
|
||||
| B | **get_priority** | **delete_file** | **socket_receive** | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> |
|
||||
| C | **get_hostname** | **rename_file** | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> |
|
||||
| D | **set_hostname** | **set_file_access** | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> |
|
||||
| E | <sub>reserved</sub> | **file_read** | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> |
|
||||
| F | <sub>reserved</sub> | **file_write** | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> |
|
||||
|
||||
| low \\ high | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 1A | 1B | 1C | 1D | 1E | 1F |
|
||||
| ----------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- |
|
||||
| 0 | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> |
|
||||
| 1 | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> |
|
||||
| 2 | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> |
|
||||
| 3 | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> |
|
||||
| 4 | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> |
|
||||
| 5 | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> |
|
||||
| 6 | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> |
|
||||
| 7 | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> |
|
||||
| 8 | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> |
|
||||
| 9 | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> |
|
||||
| A | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> |
|
||||
| B | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> |
|
||||
| C | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> |
|
||||
| D | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> |
|
||||
| E | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> |
|
||||
| F | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> | <sub>reserved</sub> |
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
// Can be standardized
|
||||
// NOTE: move the file to the src/ dir
|
||||
|
||||
pub const KERNEL_VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||
#[cfg(debug_assertions)]
|
||||
/// A constant to check if the kernel is in debug mode
|
||||
pub const RELEASE_TYPE: &str = "debug";
|
||||
#[cfg(not(debug_assertions))]
|
||||
/// A constant to check if the kernel is in release mode
|
||||
pub const RELEASE_TYPE: &str = "release";
|
||||
|
||||
pub struct SystemMemory {
|
||||
pub used: usize,
|
||||
pub total: usize,
|
||||
}
|
||||
|
||||
impl core::fmt::Display for SystemMemory {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
||||
write!(f, "{} Bytes / {} Bytes", self.used, self.total)
|
||||
}
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
pub struct User {
|
||||
id: u8,
|
||||
clipboard: Clipboard,
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
#![allow(dead_code)]
|
||||
|
||||
pub struct Scheduler {
|
||||
executables: usize,
|
||||
}
|
||||
|
||||
pub struct RunQueue;
|
|
@ -1,12 +0,0 @@
|
|||
pub struct Compositor;
|
||||
impl Compositor {
|
||||
pub fn new() -> Self {
|
||||
Self
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Compositor {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
//!
|
||||
pub mod compositor;
|
||||
pub mod window;
|
|
@ -1,37 +0,0 @@
|
|||
// use crate::driver_traits::graphics::Point;
|
||||
|
||||
pub type MenuBar = Vec<MenuOption>;
|
||||
|
||||
pub struct MenuOption {
|
||||
symbol: char,
|
||||
}
|
||||
|
||||
pub struct Window {
|
||||
title: String,
|
||||
// position: Point,
|
||||
fullscreen: bool,
|
||||
}
|
||||
|
||||
// all of these should return a result
|
||||
impl Window {
|
||||
pub fn new(title: String, /*position: Point,*/ fullscreen: bool) -> Self {
|
||||
Self {
|
||||
title,
|
||||
// position,
|
||||
fullscreen,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fullscreen(&mut self) {
|
||||
self.fullscreen = true;
|
||||
}
|
||||
pub fn revert_fullscreen(&mut self) {
|
||||
self.fullscreen = false;
|
||||
}
|
||||
pub fn set_title(&mut self) {
|
||||
todo!();
|
||||
}
|
||||
pub fn set_position(&mut self /*pos: Point*/) {
|
||||
// self.position = pos;
|
||||
}
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2022, Umut İnan Erdoğan <umutinanerdogan@pm.me>
|
||||
*
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum FsError {
|
||||
EndOfFile,
|
||||
InodeNotFound,
|
||||
InvalidDevice,
|
||||
InvalidPath,
|
||||
IsDirectory,
|
||||
NotAbsolute,
|
||||
NotADirectory,
|
||||
NotFound,
|
||||
Recursion,
|
||||
UnsupportedOperation,
|
||||
}
|
||||
|
||||
impl Into<FsError> for ext2::error::Error {
|
||||
fn into(self) -> FsError {
|
||||
match self {
|
||||
ext2::error::Error::Other(_) => todo!(),
|
||||
ext2::error::Error::BadMagic { magic: _ } => todo!(),
|
||||
ext2::error::Error::OutOfBounds { index: _ } => todo!(),
|
||||
ext2::error::Error::AddressOutOfBounds {
|
||||
sector: _,
|
||||
offset: _,
|
||||
size: _,
|
||||
} => todo!(),
|
||||
ext2::error::Error::BadBlockGroupCount {
|
||||
by_blocks: _,
|
||||
by_inodes: _,
|
||||
} => todo!(),
|
||||
ext2::error::Error::InodeNotFound { inode: _ } => FsError::InodeNotFound,
|
||||
ext2::error::Error::NotADirectory { inode: _, name: _ } => FsError::NotADirectory,
|
||||
ext2::error::Error::NotAbsolute { name: _ } => todo!(),
|
||||
ext2::error::Error::NotFound { name: _ } => FsError::NotFound,
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,177 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2022, Umut İnan Erdoğan <umutinanerdogan@pm.me>
|
||||
*
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
use alloc::sync::{Arc, Weak};
|
||||
use ext2::fs::{sync::Synced, Ext2};
|
||||
use ext2::sector::SectorSize;
|
||||
use ext2::sys::inode::TypePerm;
|
||||
use ext2::volume::Volume;
|
||||
|
||||
use crate::handle::{Handle, HandleResource};
|
||||
|
||||
use super::errors::FsError;
|
||||
use super::vfs::{DirectoryEntry, FsFlags, VirtualFileSystem, VFS};
|
||||
use super::{FsNode, FsResult as Result, StorageDevice};
|
||||
|
||||
pub struct Ext2StorageDevice<S, V>
|
||||
where
|
||||
S: SectorSize,
|
||||
V: Volume<u8, S>,
|
||||
{
|
||||
fs: Synced<Ext2<S, V>>,
|
||||
device_handle: Handle,
|
||||
root_handle: Handle,
|
||||
}
|
||||
|
||||
impl<S, V> Ext2StorageDevice<S, V>
|
||||
where
|
||||
S: SectorSize,
|
||||
V: Volume<u8, S>,
|
||||
{
|
||||
pub fn new(volume: V) -> Result<Self> {
|
||||
let fs = Synced::new(volume).map_err(|e| e.into())?;
|
||||
let root_inode = fs.root_inode();
|
||||
let device_handle = Handle::new(HandleResource::StorageDevice);
|
||||
let root = Arc::new(FsNode::new(
|
||||
FsFlags::DIRECTORY,
|
||||
root_inode.size(),
|
||||
2,
|
||||
device_handle,
|
||||
Weak::new(),
|
||||
));
|
||||
|
||||
let mut vfs = VFS.lock();
|
||||
let root_handle = vfs.add_fs_node(root.clone());
|
||||
|
||||
Ok(Self {
|
||||
fs,
|
||||
device_handle,
|
||||
root_handle,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<S, V> StorageDevice for Ext2StorageDevice<S, V>
|
||||
where
|
||||
S: SectorSize + Send,
|
||||
V: Volume<u8, S> + Send,
|
||||
{
|
||||
fn read(&self, node: &FsNode, offset: usize, size: usize, buffer: &mut Vec<u8>) -> Result<()> {
|
||||
let inode = self
|
||||
.fs
|
||||
.inode_nth(node.inode() as usize)
|
||||
.ok_or_else(|| FsError::InodeNotFound)?;
|
||||
|
||||
// FIXME: I don't really know how Ext2 works, so for now we don't
|
||||
// support non-zero offsets and buffer sizes that don't match
|
||||
// the file length. We always read the whole file.
|
||||
if offset > 0 || size != inode.size() {
|
||||
Err(FsError::UnsupportedOperation)?;
|
||||
}
|
||||
|
||||
inode.read_to_end(buffer).map_err(|e| e.into())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write(&self, _node: &FsNode, _offset: usize, _buffer: &[u8]) -> Result<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn read_dir(&self, node: &FsNode, index: usize) -> Result<DirectoryEntry> {
|
||||
let inode = self
|
||||
.fs
|
||||
.inode_nth(node.inode() as usize)
|
||||
.ok_or_else(|| FsError::InodeNotFound)?;
|
||||
let mut dir = inode.directory().ok_or_else(|| FsError::NotADirectory)?;
|
||||
let entry = dir
|
||||
.nth(index)
|
||||
.ok_or_else(|| FsError::InodeNotFound)?
|
||||
.map_err(|e| e.into())?;
|
||||
let entry_inode = self
|
||||
.fs
|
||||
.inode_nth(entry.inode)
|
||||
.ok_or_else(|| FsError::InodeNotFound)?;
|
||||
let mut vfs = VFS.lock();
|
||||
let entry_node_handle = vfs
|
||||
.find_fs_node(entry.inode, self.device_handle)
|
||||
.unwrap_or_else(|| {
|
||||
vfs.add_fs_node(Arc::new(FsNode::new(
|
||||
ext2_type_to_fs_flags(entry_inode.type_perm()),
|
||||
entry_inode.size(),
|
||||
entry.inode,
|
||||
self.device_handle,
|
||||
Weak::new(),
|
||||
)))
|
||||
});
|
||||
|
||||
Ok(DirectoryEntry::new(
|
||||
entry.file_name_string(),
|
||||
entry_node_handle,
|
||||
))
|
||||
}
|
||||
|
||||
fn find_dir(&self, vfs: &mut VirtualFileSystem, node: &FsNode, name: &str) -> Result<Handle> {
|
||||
let inode = self
|
||||
.fs
|
||||
.inode_nth(node.inode() as usize)
|
||||
.ok_or_else(|| FsError::InodeNotFound)?;
|
||||
let dir = inode.directory().ok_or_else(|| FsError::NotADirectory)?;
|
||||
let mut found_node = Err(FsError::NotFound);
|
||||
for entry in dir {
|
||||
if entry.is_err() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let entry = entry.unwrap();
|
||||
let entry_inode = self
|
||||
.fs
|
||||
.inode_nth(entry.inode as usize)
|
||||
.ok_or_else(|| FsError::InodeNotFound)?;
|
||||
if entry.file_name_string() == name {
|
||||
found_node = Ok(vfs
|
||||
.find_fs_node(entry.inode, self.device_handle)
|
||||
.unwrap_or_else(|| {
|
||||
vfs.add_fs_node(Arc::new(FsNode::new(
|
||||
ext2_type_to_fs_flags(entry_inode.type_perm()),
|
||||
entry_inode.size(),
|
||||
entry.inode,
|
||||
self.device_handle,
|
||||
Weak::new(),
|
||||
)))
|
||||
}));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
found_node
|
||||
}
|
||||
|
||||
fn root(&self) -> Handle {
|
||||
self.root_handle
|
||||
}
|
||||
|
||||
fn device_handle(&self) -> Handle {
|
||||
self.device_handle
|
||||
}
|
||||
}
|
||||
|
||||
fn ext2_type_to_fs_flags(type_perm: TypePerm) -> FsFlags {
|
||||
trace!("{type_perm:?}");
|
||||
let is_directory = type_perm & TypePerm::DIRECTORY == TypePerm::DIRECTORY;
|
||||
let is_symlink = type_perm & TypePerm::SYMLINK == TypePerm::SYMLINK;
|
||||
let t = if is_directory {
|
||||
FsFlags::DIRECTORY
|
||||
} else {
|
||||
FsFlags::FILE
|
||||
};
|
||||
let s = if is_symlink {
|
||||
FsFlags::SYMBOLIC_LINK
|
||||
} else {
|
||||
FsFlags::empty()
|
||||
};
|
||||
|
||||
t | s
|
||||
}
|
|
@ -1,90 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2022, Umut İnan Erdoğan <umutinanerdogan@pm.me>
|
||||
*
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
pub mod errors;
|
||||
pub mod ext2;
|
||||
pub mod vfs;
|
||||
|
||||
use ::ext2::sector::Size1024;
|
||||
use alloc::sync::Arc;
|
||||
|
||||
use crate::{filesystem::vfs::VFS, handle::Handle, KERNEL_STATE};
|
||||
|
||||
use self::{
|
||||
errors::FsError,
|
||||
ext2::Ext2StorageDevice,
|
||||
vfs::{DirectoryEntry, FsNode, VirtualFileSystem},
|
||||
};
|
||||
use FsResult as Result;
|
||||
|
||||
pub type FsResult<T> = core::result::Result<T, FsError>;
|
||||
|
||||
/// The methods on this trait are to be used internally.
|
||||
pub trait StorageDevice
|
||||
where
|
||||
Self: Send,
|
||||
{
|
||||
fn read(&self, node: &FsNode, offset: usize, size: usize, buffer: &mut Vec<u8>) -> Result<()>;
|
||||
fn write(&self, node: &FsNode, offset: usize, buffer: &[u8]) -> Result<()>;
|
||||
fn read_dir(&self, node: &FsNode, index: usize) -> Result<DirectoryEntry>;
|
||||
fn find_dir(&self, vfs: &mut VirtualFileSystem, node: &FsNode, name: &str) -> Result<Handle>;
|
||||
// TODO: flush to disk
|
||||
|
||||
fn root(&self) -> Handle;
|
||||
fn device_handle(&self) -> Handle;
|
||||
}
|
||||
|
||||
pub fn init() -> Result<()> {
|
||||
let mut state = KERNEL_STATE.lock();
|
||||
let fs = load_fs()?;
|
||||
let mut vfs = VFS.lock();
|
||||
vfs.set_root(fs.root())?;
|
||||
state.add_storage_device(fs);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn load_fs() -> Result<Ext2StorageDevice<Size1024, Vec<u8>>> {
|
||||
let mut volume = Vec::new();
|
||||
volume.extend_from_slice(include_bytes!("../../../userland/root_fs/ext2.img"));
|
||||
|
||||
Ext2StorageDevice::new(volume)
|
||||
}
|
||||
|
||||
pub fn tree(path: &str) -> Result<()> {
|
||||
let dir = {
|
||||
let mut vfs = VFS.lock();
|
||||
let handle = vfs.resolve(path)?;
|
||||
vfs.fs_node(handle).ok_or_else(|| FsError::NotFound)?
|
||||
};
|
||||
|
||||
tree_inner(
|
||||
dir,
|
||||
if path.starts_with('/') {
|
||||
&path[1..]
|
||||
} else {
|
||||
path
|
||||
},
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn tree_inner<S: Into<String>>(dir: Arc<FsNode>, path: S) {
|
||||
let path = path.into();
|
||||
if let Some(dir) = dir.directory() {
|
||||
for entry in dir {
|
||||
let fs_node = {
|
||||
let vfs = VFS.lock();
|
||||
vfs.fs_node(entry.node()).unwrap()
|
||||
};
|
||||
|
||||
println!("{}/{} => {}", path, entry.name(), fs_node.inode());
|
||||
trace!("{entry:#?}");
|
||||
if entry.name() != "." && entry.name() != ".." {
|
||||
tree_inner(fs_node, format!("{}/{}", path, entry.name()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,305 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2022, Umut İnan Erdoğan <umutinanerdogan@pm.me>
|
||||
*
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
use core::cmp;
|
||||
|
||||
use alloc::sync::{Arc, Weak};
|
||||
use hashbrown::HashMap;
|
||||
use lazy_static::lazy_static;
|
||||
use spin::Mutex;
|
||||
|
||||
use super::{errors::FsError, FsResult as Result};
|
||||
use crate::{
|
||||
handle::{Handle, HandleResource},
|
||||
KERNEL_STATE,
|
||||
};
|
||||
|
||||
/// The limit for symlink recursion. In POSIX, this is at least 8. In Linux, this is 40.
|
||||
const SYMLINK_RECURSION_LIMIT: u8 = 8;
|
||||
|
||||
lazy_static! {
|
||||
pub static ref VFS: Mutex<VirtualFileSystem> = Default::default();
|
||||
}
|
||||
|
||||
pub struct VirtualFileSystem {
|
||||
fs_nodes: HashMap<Handle, Arc<FsNode>>,
|
||||
root_node: Weak<FsNode>,
|
||||
root_handle: Option<Handle>,
|
||||
}
|
||||
|
||||
impl VirtualFileSystem {
|
||||
/// Sets the VFS root to the given VFS node handle.
|
||||
pub fn set_root(&mut self, handle: Handle) -> Result<()> {
|
||||
let root_node = self.fs_node(handle).ok_or_else(|| FsError::NotFound)?;
|
||||
self.root_node = Arc::downgrade(&root_node);
|
||||
self.root_handle = Some(handle);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Resolves the path to a handle. If the resulting node is a symlink,
|
||||
/// the symlink itself is returned. All symlinks but the resulting node
|
||||
/// are traversed.
|
||||
///
|
||||
/// Requires a mutable reference because internally it might open new VFS
|
||||
/// nodes while resolving the path.
|
||||
pub fn resolve<S: AsRef<str>>(&mut self, path: S) -> Result<Handle> {
|
||||
// TODO: caching
|
||||
let path = path.as_ref();
|
||||
|
||||
if !path.starts_with('/') {
|
||||
// FIXME: use current process working directory for relative paths?
|
||||
Err(FsError::NotAbsolute)?;
|
||||
}
|
||||
|
||||
let mut components = path.split_terminator('/');
|
||||
components.next(); // throw the empty string caused by the root /
|
||||
// will be initialised beforehand so okay to unwrap
|
||||
let mut resolved_node = self.root_handle.unwrap();
|
||||
// let mut symlink_recursion_level = 0;
|
||||
for component in components {
|
||||
// if symlink_recursion_level >= SYMLINK_RECURSION_LIMIT {
|
||||
// Err(FsError::Recursion)?;
|
||||
// }
|
||||
|
||||
if component == "" {
|
||||
Err(FsError::InvalidPath)?;
|
||||
}
|
||||
|
||||
// checked by previous iteration so okay to unwrap
|
||||
let parent = self.fs_node(resolved_node).unwrap();
|
||||
|
||||
// TODO: permission checks
|
||||
|
||||
// FIXME: find_dir checks that this is a directory already but
|
||||
// that's just more boilerplate in StorageDevice impls
|
||||
// we should probably check that here instead to reduce
|
||||
// required boilerplate
|
||||
// if !parent.is_dir() {
|
||||
// Err(FsError::NotADirectory)?;
|
||||
// }
|
||||
|
||||
// FIXME: handle mount points
|
||||
// FIXME: handle symlinks
|
||||
|
||||
resolved_node = parent.find_dir(self, component)?;
|
||||
}
|
||||
|
||||
Ok(resolved_node)
|
||||
}
|
||||
|
||||
pub fn add_fs_node(&mut self, fs_node: Arc<FsNode>) -> Handle {
|
||||
let handle = Handle::new(HandleResource::FsNode);
|
||||
self.fs_nodes.insert(handle, fs_node);
|
||||
handle
|
||||
}
|
||||
|
||||
pub fn find_fs_node(&mut self, inode: usize, device_handle: Handle) -> Option<Handle> {
|
||||
self.fs_nodes.iter().find_map(|(handle, fs_node)| {
|
||||
if fs_node.inode == inode && fs_node.device_handle == device_handle {
|
||||
Some(*handle)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn fs_node(&self, handle: Handle) -> Option<Arc<FsNode>> {
|
||||
self.fs_nodes.get(&handle).cloned()
|
||||
}
|
||||
|
||||
pub fn root_node(&self) -> Arc<FsNode> {
|
||||
// okay to unwrap since this should never be called before init
|
||||
self.root_node.upgrade().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for VirtualFileSystem {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
fs_nodes: HashMap::new(),
|
||||
root_node: Weak::new(),
|
||||
root_handle: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A VFS node, that can either be a file or a directory.
|
||||
///
|
||||
/// VFS nodes are created whenever a file that doesn't have an open VFS node is
|
||||
/// opened. When there are no open file descriptors to a file, the associated
|
||||
/// VFS node is dropped.
|
||||
#[derive(Debug)]
|
||||
pub struct FsNode {
|
||||
flags: FsFlags,
|
||||
size: usize, // in bytes
|
||||
inode: usize, // implementation specific identifier for the node
|
||||
device_handle: Handle, // uniquely assigned device handle
|
||||
ptr: Weak<FsNode>, // used by mountpoints and symlinks
|
||||
// TODO: permissions mask
|
||||
// TODO: owning user/group
|
||||
}
|
||||
|
||||
impl FsNode {
|
||||
pub fn new(
|
||||
flags: FsFlags,
|
||||
size: usize,
|
||||
inode: usize,
|
||||
device_handle: Handle,
|
||||
ptr: Weak<FsNode>,
|
||||
) -> Self {
|
||||
Self {
|
||||
flags,
|
||||
size,
|
||||
inode,
|
||||
device_handle,
|
||||
ptr,
|
||||
}
|
||||
}
|
||||
|
||||
/// This method opens a new file descriptor for this VFS node.
|
||||
// TODO: make this take flags
|
||||
pub fn open(self: Arc<Self>) -> Result<Handle> {
|
||||
let mut state = KERNEL_STATE.lock();
|
||||
let handle = state.open_file_descriptor(self);
|
||||
|
||||
Ok(handle)
|
||||
}
|
||||
|
||||
/// This method reads from the VFS node without opening a new file
|
||||
/// descriptor. This is intended to be used internally, if you're trying to
|
||||
/// read a file then you probably want to read from a file descriptor.
|
||||
pub fn read(&self, offset: usize, size: usize, buffer: &mut Vec<u8>) -> Result<usize> {
|
||||
let state = KERNEL_STATE.lock();
|
||||
let device = state
|
||||
.storage_device(self.device_handle)
|
||||
.ok_or_else(|| FsError::InvalidDevice)?;
|
||||
|
||||
if self.is_dir() {
|
||||
Err(FsError::IsDirectory)?;
|
||||
}
|
||||
|
||||
if offset > self.size {
|
||||
Err(FsError::EndOfFile)?;
|
||||
}
|
||||
|
||||
let readable_size = cmp::min(size, self.size - offset);
|
||||
device.read(self, offset, readable_size, buffer)?;
|
||||
Ok(readable_size)
|
||||
}
|
||||
|
||||
/// This method writes to the VFS node without opening a new file
|
||||
/// descriptor. This is intended to be used internally, if you're trying to
|
||||
/// write to a file then you probably want to write to a file descriptor.
|
||||
pub fn write(&self, offset: usize, buffer: &[u8]) -> Result<()> {
|
||||
let state = KERNEL_STATE.lock();
|
||||
let device = state
|
||||
.storage_device(self.device_handle)
|
||||
.ok_or_else(|| FsError::InvalidDevice)?;
|
||||
|
||||
device.write(self, offset, buffer)
|
||||
}
|
||||
|
||||
pub fn read_dir(&self, index: usize) -> Result<DirectoryEntry> {
|
||||
let state = KERNEL_STATE.lock();
|
||||
let device = state
|
||||
.storage_device(self.device_handle)
|
||||
.ok_or_else(|| FsError::InvalidDevice)?;
|
||||
|
||||
device.read_dir(self, index)
|
||||
}
|
||||
|
||||
pub fn find_dir(&self, vfs: &mut VirtualFileSystem, name: &str) -> Result<Handle> {
|
||||
let state = KERNEL_STATE.lock();
|
||||
let device = state
|
||||
.storage_device(self.device_handle)
|
||||
.ok_or_else(|| FsError::InvalidDevice)?;
|
||||
|
||||
device.find_dir(vfs, self, name)
|
||||
}
|
||||
|
||||
pub fn directory(self: Arc<Self>) -> Option<Directory> {
|
||||
if self.is_dir() {
|
||||
Some(Directory::new(self))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_dir(&self) -> bool {
|
||||
(self.flags & FsFlags::DIRECTORY) == FsFlags::DIRECTORY
|
||||
}
|
||||
|
||||
pub fn inode(&self) -> usize {
|
||||
self.inode
|
||||
}
|
||||
|
||||
pub fn size(&self) -> usize {
|
||||
self.size
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for FsNode {
|
||||
fn drop(&mut self) {
|
||||
trace!("dropping VFS node: {self:#?}");
|
||||
// TODO: flush to disk here
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// Flags associated with VFS nodes and file descriptors
|
||||
///
|
||||
/// 0x00000MST \
|
||||
/// T is set to 0 for files, 1 for directories \
|
||||
/// S is set when the file is a symbolic link \
|
||||
/// M is set if the file is an active mount point
|
||||
pub struct FsFlags: u8 {
|
||||
const FILE = 0b00000000;
|
||||
const DIRECTORY = 0b00000001;
|
||||
const SYMBOLIC_LINK = 0b00000010;
|
||||
const MOUNT_POINT = 0b00000100;
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Directory {
|
||||
node: Arc<FsNode>,
|
||||
index: usize,
|
||||
}
|
||||
|
||||
impl Directory {
|
||||
fn new(node: Arc<FsNode>) -> Self {
|
||||
Self { node, index: 0 }
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for Directory {
|
||||
type Item = DirectoryEntry;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let value = self.node.read_dir(self.index).ok();
|
||||
self.index += 1;
|
||||
value
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct DirectoryEntry {
|
||||
name: String,
|
||||
node: Handle,
|
||||
}
|
||||
|
||||
impl DirectoryEntry {
|
||||
pub(super) fn new(name: String, node: Handle) -> Self {
|
||||
Self { name, node }
|
||||
}
|
||||
|
||||
pub fn name(&self) -> String {
|
||||
self.name.clone()
|
||||
}
|
||||
|
||||
pub fn node(&self) -> Handle {
|
||||
self.node
|
||||
}
|
||||
}
|
|
@ -1,342 +0,0 @@
|
|||
pub mod pixel_format;
|
||||
|
||||
use spin::Lazy;
|
||||
use vga::{colors::Color16, writers::GraphicsWriter};
|
||||
|
||||
use crate::vga_e::VGAE;
|
||||
|
||||
use pixel_format::*;
|
||||
|
||||
pub static SCREEN_BUFFER: Lazy<spin::Mutex<ScreenBuffer>> =
|
||||
Lazy::new(|| spin::Mutex::new(ScreenBuffer::new(640, 480)));
|
||||
|
||||
const FONT_SCALE: f32 = 1.6;
|
||||
|
||||
const GLYPH_HEIGHT: f32 = 18.0;
|
||||
const GLYPH_WIDTH: f32 = 10.0;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ScreenSize {
|
||||
pub x: usize,
|
||||
pub y: usize,
|
||||
}
|
||||
|
||||
impl ScreenSize {
|
||||
pub fn new(x: usize, y: usize) -> Self {
|
||||
Self { x, y }
|
||||
}
|
||||
}
|
||||
|
||||
pub enum GraphicsReturn {
|
||||
Ok,
|
||||
ImproperScreenSize,
|
||||
}
|
||||
|
||||
pub struct ScreenBuffer {
|
||||
pub size: ScreenSize,
|
||||
pub clear_color: Rgba64,
|
||||
pub buff: Box<[Rgba64]>,
|
||||
}
|
||||
|
||||
impl ScreenBuffer {
|
||||
// Add optional size later
|
||||
pub fn new(x: usize, y: usize) -> Self {
|
||||
Self {
|
||||
size: ScreenSize::new(x, y),
|
||||
clear_color: 0,
|
||||
buff: vec![0u64; x * y].into_boxed_slice(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw_filled_circle(&mut self, cx: i32, cy: i32, radius: usize, color: Rgba64) {
|
||||
let r = radius as i32 * 2;
|
||||
for y in 0..640 {
|
||||
for x in 0..480 {
|
||||
let dx = cx - x as i32 * 2 - 1;
|
||||
let dy = cy - y as i32 * 2 - 1;
|
||||
|
||||
if dx * dx + dy * dy <= r * r {
|
||||
self.set_pixel(x, y, color);
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_pixel(&mut self, x: usize, y: usize, color: Rgba64) {
|
||||
self.buff[y * self.size.x + x] = color;
|
||||
}
|
||||
|
||||
pub fn clear(&mut self) {
|
||||
self.buff = vec![0u64; self.buff.len()].into_boxed_slice();
|
||||
}
|
||||
|
||||
pub fn blit(&mut self, _width: usize, _height: usize) {}
|
||||
|
||||
pub fn draw_filled_rect(&mut self, x1: usize, y1: usize, x2: usize, y2: usize, color: Rgba64) {
|
||||
for y in y1..y2 {
|
||||
for x in x1..x2 {
|
||||
self.set_pixel(x, y, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
pub fn draw_unfilled_rect(
|
||||
&mut self,
|
||||
x1: usize,
|
||||
y1: usize,
|
||||
x2: usize,
|
||||
y2: usize,
|
||||
color: Rgba64,
|
||||
) {
|
||||
// x1 y1 => x2 y1 => x2 y2 => x1 y2 => x1 y1
|
||||
self.draw_line(x1, y1, x2, y1, color);
|
||||
self.draw_line(x2, y1, x2, y2, color);
|
||||
self.draw_line(x2, y2, x1, y2, color);
|
||||
self.draw_line(x1, y2, x1, y1, color);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn draw_line(&mut self, x1: usize, y1: usize, x2: usize, y2: usize, color: Rgba64) {
|
||||
let x = crate::graphics::get_coordinates(
|
||||
x1.try_into().unwrap(),
|
||||
y1.try_into().unwrap(),
|
||||
x2.try_into().unwrap(),
|
||||
y2.try_into().unwrap(),
|
||||
);
|
||||
|
||||
for coord in x {
|
||||
self.set_pixel(coord.0, coord.1, color);
|
||||
}
|
||||
}
|
||||
|
||||
// pub fn shade(&mut self) {
|
||||
// for y in 0..100 {
|
||||
// for x in 0..100 {
|
||||
// let rgba_ret = evaluate_shader(x, y, self.buff[y * self.size.x + x]);
|
||||
// match rgba_ret {
|
||||
// Ok(pixel) => {
|
||||
// // info!("{:?}", pixel);
|
||||
// self.set_pixel(x, y, pixel);
|
||||
// }
|
||||
|
||||
// Err(err) => error!("{}", err),
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// info!("Shaders done");
|
||||
// }
|
||||
|
||||
// TODO force clear
|
||||
pub fn force_redraw(&mut self) {
|
||||
let vga = VGAE.lock();
|
||||
vga.set_mode();
|
||||
vga.clear_screen(vga::colors::Color16::Black);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_coordinates(x1: i32, y1: i32, x2: i32, y2: i32) -> Vec<(usize, usize)> {
|
||||
let mut coordinates: Vec<(usize, usize)> = vec![];
|
||||
let dx: i32 = i32::abs(x2 - x1);
|
||||
let dy: i32 = i32::abs(y2 - y1);
|
||||
let sx: i32 = {
|
||||
if x1 < x2 {
|
||||
1
|
||||
} else {
|
||||
-1
|
||||
}
|
||||
};
|
||||
let sy: i32 = {
|
||||
if y1 < y2 {
|
||||
1
|
||||
} else {
|
||||
-1
|
||||
}
|
||||
};
|
||||
let mut error: i32 = (if dx > dy { dx } else { -dy }) / 2;
|
||||
let mut current_x: i32 = x1;
|
||||
let mut current_y: i32 = y1;
|
||||
loop {
|
||||
coordinates.push((current_x as usize, current_y as usize));
|
||||
// info!("0 {:?}", (current_x, current_y));
|
||||
|
||||
if current_x == x2 && current_y == y2 {
|
||||
break;
|
||||
}
|
||||
|
||||
let error2: i32 = error;
|
||||
|
||||
if error2 > -dx {
|
||||
error -= dy;
|
||||
current_x += sx;
|
||||
}
|
||||
if error2 < dy {
|
||||
error += dx;
|
||||
current_y += sy;
|
||||
}
|
||||
}
|
||||
|
||||
coordinates
|
||||
}
|
||||
|
||||
pub trait VgaBuffer {
|
||||
fn copy_to_buffer(&self) -> GraphicsReturn;
|
||||
}
|
||||
impl VgaBuffer for ScreenBuffer {
|
||||
fn copy_to_buffer(&self) -> GraphicsReturn {
|
||||
let mode = VGAE.lock();
|
||||
for y in 0..self.size.y {
|
||||
for x in 0..self.size.x {
|
||||
let vga_color = into_vga_16(self.buff[y * self.size.x + x]);
|
||||
if into_vga_16(self.clear_color) != vga_color {
|
||||
mode.set_pixel(x, y, vga_color);
|
||||
}
|
||||
}
|
||||
}
|
||||
GraphicsReturn::Ok
|
||||
}
|
||||
}
|
||||
|
||||
pub fn into_vga_16(rgba_64: Rgba64) -> Color16 {
|
||||
use pixel_format::ChannelValue::*;
|
||||
use vga::colors::Color16::*;
|
||||
match (
|
||||
get_r(rgba_64).into(),
|
||||
get_g(rgba_64).into(),
|
||||
get_b(rgba_64).into(),
|
||||
) {
|
||||
(Dark, Dark, Dark) => Black,
|
||||
(Dark, Dark, Low) => Black,
|
||||
(Dark, Dark, Mid) => Blue,
|
||||
(Dark, Dark, High) => Blue,
|
||||
(Dark, Low, Dark) => Black,
|
||||
(Dark, Low, Low) => Black,
|
||||
(Dark, Low, Mid) => Blue,
|
||||
(Dark, Low, High) => Blue,
|
||||
(Dark, Mid, Dark) => Green,
|
||||
(Dark, Mid, Low) => Green,
|
||||
(Dark, Mid, Mid) => Cyan,
|
||||
(Dark, Mid, High) => Cyan,
|
||||
(Dark, High, Dark) => Green,
|
||||
(Dark, High, Low) => Green,
|
||||
(Dark, High, Mid) => Green,
|
||||
(Dark, High, High) => Cyan,
|
||||
(Low, Dark, Dark) => Black,
|
||||
(Low, Dark, Low) => Black,
|
||||
(Low, Dark, Mid) => Blue,
|
||||
(Low, Dark, High) => Blue,
|
||||
(Low, Low, Dark) => Black,
|
||||
(Low, Low, Low) => DarkGrey,
|
||||
(Low, Low, Mid) => LightGrey,
|
||||
(Low, Low, High) => Blue,
|
||||
(Low, Mid, Dark) => DarkGrey,
|
||||
(Low, Mid, Low) => LightGrey,
|
||||
(Low, Mid, Mid) => Cyan,
|
||||
(Low, Mid, High) => Cyan,
|
||||
(Low, High, Dark) => Green,
|
||||
(Low, High, Low) => Green,
|
||||
(Low, High, Mid) => Cyan,
|
||||
(Low, High, High) => Cyan,
|
||||
(Mid, Dark, Dark) => Red,
|
||||
(Mid, Dark, Low) => Red,
|
||||
(Mid, Dark, Mid) => Magenta,
|
||||
(Mid, Dark, High) => Magenta,
|
||||
(Mid, Low, Dark) => Brown,
|
||||
(Mid, Low, Low) => Red,
|
||||
(Mid, Low, Mid) => DarkGrey,
|
||||
(Mid, Low, High) => LightBlue,
|
||||
(Mid, Mid, Dark) => Brown,
|
||||
(Mid, Mid, Low) => Brown,
|
||||
(Mid, Mid, Mid) => LightGrey,
|
||||
(Mid, Mid, High) => LightBlue,
|
||||
(Mid, High, Dark) => Green,
|
||||
(Mid, High, Low) => Green,
|
||||
(Mid, High, Mid) => LightGreen,
|
||||
(Mid, High, High) => LightCyan,
|
||||
(High, Dark, Dark) => Red,
|
||||
(High, Dark, _) => Magenta,
|
||||
(High, Low, Dark) => Red,
|
||||
(High, Low, Low) => LightRed,
|
||||
(High, Low, Mid) => Pink,
|
||||
(High, Low, High) => Magenta,
|
||||
(High, Mid, Dark) => Yellow,
|
||||
(High, Mid, Low) => Yellow,
|
||||
(High, Mid, Mid) => LightRed,
|
||||
(High, Mid, High) => Pink,
|
||||
(High, High, Dark) => Yellow,
|
||||
(High, High, Low) => White,
|
||||
(High, High, Mid) => White,
|
||||
(High, High, High) => White,
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Incorporate this into the ableos vga crate
|
||||
// /// Draw a glyph on the screen at the given position
|
||||
// ///
|
||||
// /// # Arguments
|
||||
// /// * `x` - the x position of the glyph
|
||||
// /// * `y` - the y position of the glyph
|
||||
// /// * `glyph` - the glyph to draw
|
||||
// /// * `color` - the color of the glyph
|
||||
// pub fn draw_char(&mut self, mut x: u32, mut y: u32, character: char, color: Rgba64) {
|
||||
// // trace!["Judy Hopps is thicc af"];
|
||||
// // let mode = *VGAE.lock();
|
||||
// // trace!["She got them bouncy bunny buns"];
|
||||
|
||||
// let basic_multingual_plane = FontRef::try_from_slice(include_bytes!(
|
||||
// "../../../ableos/assets/fonts/unifont-14.0.01.ttf"
|
||||
// ))
|
||||
// .unwrap();
|
||||
|
||||
// let supplementary_multilingual_plane = FontRef::try_from_slice(include_bytes!(
|
||||
// "../../../ableos/assets/fonts/unifont_upper-14.0.01.ttf"
|
||||
// ))
|
||||
// .unwrap();
|
||||
|
||||
// // let mut has_char = false;
|
||||
// // for x in font.codepoint_ids() {
|
||||
// // if x.1 == character {
|
||||
// // has_char = true;
|
||||
// // break;
|
||||
// // }
|
||||
// // }
|
||||
|
||||
// let in_supp_plane = character as u32 > 0xffff;
|
||||
|
||||
// let plane = match in_supp_plane {
|
||||
// false => basic_multingual_plane,
|
||||
// true => supplementary_multilingual_plane,
|
||||
// };
|
||||
|
||||
// match character {
|
||||
// '\n' => {
|
||||
// // x = 0;
|
||||
// // y += (GLYPH_HEIGHT * FONT_SCALE) as u32;
|
||||
// }
|
||||
// _ => {
|
||||
// let q_glyph: Glyph = plane.glyph_id(character).with_scale_and_position(
|
||||
// 20.0 * FONT_SCALE,
|
||||
// ab_glyph::point(GLYPH_WIDTH * FONT_SCALE, GLYPH_HEIGHT * FONT_SCALE),
|
||||
// );
|
||||
|
||||
// // elf: I don't know if GLYPH_HEIGHT is in the right units here. I'm just guessing.
|
||||
// if x as usize > self.size.x {
|
||||
// x = 0;
|
||||
// y += (GLYPH_HEIGHT * FONT_SCALE) as u32;
|
||||
// }
|
||||
|
||||
// if let Some(q) = plane.outline_glyph(q_glyph) {
|
||||
// q.draw(|gx, gy, c| {
|
||||
// if c > 0.0015 {
|
||||
// let corner = q.px_bounds().min;
|
||||
// self.set_pixel(
|
||||
// gx as usize + corner.x as usize + x as usize,
|
||||
// gy as usize + corner.y as usize + y as usize,
|
||||
// color,
|
||||
// );
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
|
@ -1,55 +0,0 @@
|
|||
use core::ops::{BitAnd, BitOr, Shr};
|
||||
pub type Rgba64 = u64;
|
||||
pub enum ChannelValue {
|
||||
Dark,
|
||||
Low,
|
||||
Mid,
|
||||
High,
|
||||
}
|
||||
impl From<u8> for ChannelValue {
|
||||
fn from(b: u8) -> Self {
|
||||
use ChannelValue::*;
|
||||
match b {
|
||||
0x00..=0x3f => Dark,
|
||||
0x40..=0x7f => Low,
|
||||
0x80..=0xbf => Mid,
|
||||
0xc0..=0xff => High,
|
||||
}
|
||||
}
|
||||
}
|
||||
pub fn get_r(rgba: Rgba64) -> u8 {
|
||||
rgba.bitand(0xff_00_00_00).shr(0o30) as u8
|
||||
}
|
||||
pub fn get_g(rgba: Rgba64) -> u8 {
|
||||
rgba.bitand(0xff_00_00).shr(0o20) as u8
|
||||
}
|
||||
pub fn get_b(rgba: Rgba64) -> u8 {
|
||||
rgba.bitand(0xff_00).shr(0o10) as u8
|
||||
}
|
||||
pub fn get_a(rgba: Rgba64) -> u8 {
|
||||
(rgba & 0xff) as u8
|
||||
}
|
||||
pub fn set_r(rgba: Rgba64, r: u8) -> Rgba64 {
|
||||
rgba.bitand(0xffffffff_00_ff_ff_ff)
|
||||
.bitor((r as Rgba64).shr(0o30))
|
||||
}
|
||||
pub fn set_g(rgba: Rgba64, g: u8) -> Rgba64 {
|
||||
rgba.bitand(0xffffffff_ff_00_ff_ff)
|
||||
.bitor((g as Rgba64).shr(0o20))
|
||||
}
|
||||
pub fn set_b(rgba: Rgba64, b: u8) -> Rgba64 {
|
||||
rgba.bitand(0xffffffff_ff_ff_00_ff)
|
||||
.bitor((b as Rgba64).shr(0o10))
|
||||
}
|
||||
pub fn set_a(rgba: Rgba64, a: u8) -> Rgba64 {
|
||||
rgba.bitand(0xffffffff_ff_ff_ff_00).bitor(a as Rgba64)
|
||||
}
|
||||
pub fn rgba_div(a: Rgba64, b: Rgba64) -> Rgba64 {
|
||||
set_r(0, get_r(a) / get_r(b))
|
||||
| set_g(0, get_g(a) / get_g(b))
|
||||
| set_g(0, get_b(a) / get_b(b))
|
||||
| set_g(0, get_a(a) / get_a(b))
|
||||
}
|
||||
pub fn new_rgba64(r: u8, g: u8, b: u8, a: u8) -> Rgba64 {
|
||||
set_r(0, r) | set_g(0, g) | set_b(0, b) | set_a(0, a)
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
// TODO: Reorganize and make part of this into a limine agnostic API for general purpose graphics
|
||||
use crate::kmain::FRAMEBUFFER;
|
||||
pub fn clear_screen() {
|
||||
{
|
||||
// TODO: setup a proper framebuffer handler
|
||||
let fb_response = FRAMEBUFFER.get_response().get().unwrap();
|
||||
for fb in fb_response.framebuffers().unwrap() {
|
||||
trace!("Framebuffer {}x{}", fb.width, fb.height);
|
||||
trace!("{}", fb.memory_model);
|
||||
trace!("{}", fb.bpp);
|
||||
let mut count = 0;
|
||||
let total = fb.width * fb.height * 3;
|
||||
while count != total {
|
||||
unsafe {
|
||||
let fb_ptr = fb.address.as_mut_ptr().unwrap();
|
||||
*fb_ptr.offset((count).try_into().unwrap()) = 0x00;
|
||||
*fb_ptr.offset((count + 1).try_into().unwrap()) = 0x00;
|
||||
*fb_ptr.offset((count + 2).try_into().unwrap()) = 0x00;
|
||||
}
|
||||
count += 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue