forked from LowLevelDevs/FoundryOS
Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d9b66f8008 | |||
| 2be5b63af7 | |||
| 7e62bdae35 | |||
| b8aa203c05 | |||
| 9f83c5f295 | |||
| 914cb4e409 | |||
| 43b1db41ca | |||
| c763f512f1 | |||
| 5dc73e7000 | |||
| ca906767db | |||
| ef8d028211 | |||
| 2886fe5ecf | |||
| c2c552ef25 | |||
| e722874cee | |||
| 27b0ed634c |
+13
-2
@@ -9,5 +9,16 @@ build-std-features = ["compiler-builtins-mem"]
|
||||
[env]
|
||||
RUST_TARGET_PATH = { value = "kernel", relative = true }
|
||||
|
||||
[target.x86_64-kernel]
|
||||
runner = "scripts/run.sh"
|
||||
# Run in debug mode.
|
||||
[target.'cfg(all(target_arch = "x86_64", target_os = "none", debug_assertions))']
|
||||
runner = "scripts/run_debug.sh"
|
||||
|
||||
# Otherwise we run in release mode.
|
||||
[target.'cfg(all(target_arch = "x86_64", target_os = "none", not(debug_assertions)))']
|
||||
runner = "scripts/run_release.sh"
|
||||
|
||||
# [registry]
|
||||
# default = "gitea"
|
||||
|
||||
[registries.gitea]
|
||||
index = "sparse+https://git.zxq5.dev/api/packages/OsDev/cargo/" # Sparse index
|
||||
|
||||
-15
@@ -1,15 +0,0 @@
|
||||
[submodule "lib/lib_application"]
|
||||
path = lib/lib_application
|
||||
url = https://git.zxq5.dev/OsDev/FoundryOS-lib_application.git
|
||||
[submodule "lib/lib_ascii"]
|
||||
path = lib/lib_ascii
|
||||
url = https://git.zxq5.dev/OsDev/FoundryOS-lib_ascii.git
|
||||
[submodule "lib/lib_framebuffer"]
|
||||
path = lib/lib_framebuffer
|
||||
url = https://git.zxq5.dev/OsDev/FoundryOS-lib_framebuffer.git
|
||||
[submodule "lib/lib_serial"]
|
||||
path = lib/lib_serial
|
||||
url = https://git.zxq5.dev/OsDev/FoundryOS-lib_serial.git
|
||||
[submodule "lib/lib_alloc"]
|
||||
path = lib/lib_alloc
|
||||
url = https://git.zxq5.dev/OsDev/FoundryOS-lib_alloc.git
|
||||
Vendored
+2
-2
@@ -4,6 +4,6 @@
|
||||
"[rust]": {
|
||||
"editor.defaultFormatter": "rust-lang.rust-analyzer",
|
||||
"editor.formatOnSave": true
|
||||
}
|
||||
},
|
||||
"rust-analyzer.check.command": "clippy",
|
||||
}
|
||||
|
||||
|
||||
Generated
+74
-44
@@ -22,22 +22,54 @@ checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.2.14"
|
||||
version = "1.2.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0c3d1b2e905a3a7b00a6141adb0e4c0bb941d11caf55349d863942a1cc44e3c9"
|
||||
checksum = "c736e259eea577f443d5c86c304f9f4ae0295c43f3ba05c21f1d66b5f06001af"
|
||||
dependencies = [
|
||||
"shlex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam"
|
||||
version = "0.8.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1137cd7e7fc0fb5d3c5a8678be38ec56e819125d8d7907411fe24ccb943faca8"
|
||||
dependencies = [
|
||||
"crossbeam-epoch",
|
||||
"crossbeam-queue",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-epoch"
|
||||
version = "0.9.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
|
||||
dependencies = [
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-queue"
|
||||
version = "0.3.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115"
|
||||
dependencies = [
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
|
||||
|
||||
[[package]]
|
||||
name = "foundry_os"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"lib_alloc",
|
||||
"lib_ascii",
|
||||
"lib_framebuffer",
|
||||
"lib_serial",
|
||||
"libk",
|
||||
"limine",
|
||||
"pc-keyboard",
|
||||
"pic8259",
|
||||
@@ -46,52 +78,38 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.5.0"
|
||||
name = "futures-core"
|
||||
version = "0.3.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
||||
checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
|
||||
|
||||
[[package]]
|
||||
name = "futures-task"
|
||||
version = "0.3.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988"
|
||||
|
||||
[[package]]
|
||||
name = "futures-util"
|
||||
version = "0.3.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81"
|
||||
dependencies = [
|
||||
"spin",
|
||||
"futures-core",
|
||||
"futures-task",
|
||||
"pin-project-lite",
|
||||
"pin-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lib_alloc"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"linked_list_allocator",
|
||||
"x86_64",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lib_application"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"lib_ascii",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lib_ascii"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"lib_framebuffer",
|
||||
"spin",
|
||||
"x86_64",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lib_framebuffer"
|
||||
name = "libk"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"crossbeam",
|
||||
"futures-util",
|
||||
"limine",
|
||||
"spin",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lib_serial"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"linked_list_allocator",
|
||||
"pc-keyboard",
|
||||
"spin",
|
||||
"x86_64",
|
||||
]
|
||||
@@ -139,6 +157,18 @@ dependencies = [
|
||||
"x86_64",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-lite"
|
||||
version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
|
||||
|
||||
[[package]]
|
||||
name = "pin-utils"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.19"
|
||||
|
||||
+6
-9
@@ -1,21 +1,18 @@
|
||||
[workspace]
|
||||
members = [
|
||||
"lib/lib_framebuffer",
|
||||
"lib/lib_serial",
|
||||
"lib/lib_ascii",
|
||||
"kernel",
|
||||
"lib/lib_application",
|
||||
"lib/lib_alloc",
|
||||
]
|
||||
members = ["kernel", "libk"]
|
||||
resolver = "2"
|
||||
|
||||
[workspace.package]
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
edition = "2024"
|
||||
authors = ["The FoundryOS Contributors"]
|
||||
|
||||
[profile.dev]
|
||||
opt-level = "z"
|
||||
debug = true
|
||||
# Leave this on to force Cargo to use the debug runner,
|
||||
# which adds the necessary flags for GDB debugging if you
|
||||
# set $USE_GDB (to any value) e.g. USE_GDB=1 cargo run
|
||||
debug-assertions = true
|
||||
overflow-checks = true
|
||||
lto = false
|
||||
|
||||
@@ -5,18 +5,20 @@
|
||||
Here are some simple steps to get started:
|
||||
|
||||
```sh
|
||||
# If you have not yet cloned the repo:
|
||||
git clone --recurse-submodules https://git.zxq5.dev/OsDev/FoundryOS.git
|
||||
# If you already cloned the repo:
|
||||
git submodule update --init --recursive
|
||||
|
||||
cargo build
|
||||
# This will build the binaries if required - no need to call cargo build.
|
||||
git clone https://git.zxq5.dev/OsDev/FoundryOS.git
|
||||
cargo run
|
||||
```
|
||||
|
||||
## Running in GDB:
|
||||
```sh
|
||||
USE_GDB=1 cargo run
|
||||
```
|
||||
|
||||
### Build dependencies
|
||||
|
||||
* jq: checks whether the app is to be run in debugging mode.
|
||||
* libisoburn: creates ISO images to be booted from.
|
||||
* qemu: to run the kernel.
|
||||
|
||||
Optionally,
|
||||
|
||||
* GDB: for debugging the kernel.
|
||||
@@ -1,4 +1,4 @@
|
||||
#usage
|
||||
# Usage
|
||||
### Requirements
|
||||
- Latest rust nightly release
|
||||
> rustup update
|
||||
|
||||
+5
-6
@@ -1,14 +1,12 @@
|
||||
[package]
|
||||
name = "foundry_os"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
edition.workspace = true
|
||||
version.workspace = true
|
||||
authors.workspace = true
|
||||
|
||||
[dependencies]
|
||||
limine = "0.3.1"
|
||||
lib_framebuffer = { path = "../lib/lib_framebuffer" }
|
||||
lib_serial = { path = "../lib/lib_serial" }
|
||||
lib_ascii = { path = "../lib/lib_ascii" }
|
||||
lib_alloc = { path = "../lib/lib_alloc" }
|
||||
libk = { path = "../libk" }
|
||||
x86_64 = "0.15.2"
|
||||
spin = "0.9.8"
|
||||
pic8259 = "0.11.0"
|
||||
@@ -23,3 +21,4 @@ default = []
|
||||
[[bin]]
|
||||
name = "kernel"
|
||||
path = "src/main.rs"
|
||||
test = false
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
use cc;
|
||||
use std::process::Command;
|
||||
use std::{env, path::Path};
|
||||
|
||||
fn main() {
|
||||
// Tell cargo to rerun if these files change
|
||||
println!("cargo:rerun-if-changed=src");
|
||||
|
||||
@@ -19,8 +19,8 @@ static TSS: Lazy<TaskStateSegment> = Lazy::new(|| {
|
||||
static mut STACK: [u8; STACK_SIZE] = [0; STACK_SIZE];
|
||||
|
||||
let stack_start = VirtAddr::from_ptr(&raw const STACK);
|
||||
let stack_end = stack_start + STACK_SIZE.try_into().unwrap();
|
||||
stack_end
|
||||
|
||||
stack_start + STACK_SIZE.try_into().unwrap()
|
||||
};
|
||||
tss
|
||||
});
|
||||
@@ -40,8 +40,8 @@ static GDT: Lazy<(GlobalDescriptorTable, Selectors)> = Lazy::new(|| {
|
||||
Selectors {
|
||||
code_selector,
|
||||
data_selector,
|
||||
user_code_selector,
|
||||
user_data_selector,
|
||||
_user_code_selector: user_code_selector,
|
||||
_user_data_selector: user_data_selector,
|
||||
tss_selector,
|
||||
},
|
||||
)
|
||||
@@ -50,8 +50,8 @@ static GDT: Lazy<(GlobalDescriptorTable, Selectors)> = Lazy::new(|| {
|
||||
struct Selectors {
|
||||
code_selector: SegmentSelector,
|
||||
data_selector: SegmentSelector,
|
||||
user_code_selector: SegmentSelector,
|
||||
user_data_selector: SegmentSelector,
|
||||
_user_code_selector: SegmentSelector,
|
||||
_user_data_selector: SegmentSelector,
|
||||
tss_selector: SegmentSelector,
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
use lib_ascii::{print, println_log};
|
||||
use lib_serial::serial_println;
|
||||
use x86_64::instructions::port::Port;
|
||||
use libk::prelude::*;
|
||||
use x86_64::registers::control::Cr2;
|
||||
use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame, PageFaultErrorCode};
|
||||
|
||||
@@ -81,30 +79,24 @@ extern "x86-interrupt" fn double_fault_handler(
|
||||
}
|
||||
|
||||
extern "x86-interrupt" fn keyboard_interrupt_handler(_stack_frame: InterruptStackFrame) {
|
||||
use pc_keyboard::{layouts, DecodedKey, HandleControl, Keyboard, ScancodeSet1};
|
||||
use pc_keyboard::{layouts, HandleControl, Keyboard, ScancodeSet1};
|
||||
// use pc_keyboard::DecodedKey;
|
||||
use spin::Mutex;
|
||||
use x86_64::instructions::port::Port;
|
||||
|
||||
static KEYBOARD: Lazy<Mutex<Keyboard<layouts::Us104Key, ScancodeSet1>>> = Lazy::new(|| {
|
||||
static KEYBOARD: Lazy<Mutex<Keyboard<layouts::Uk105Key, ScancodeSet1>>> = Lazy::new(|| {
|
||||
Mutex::new(Keyboard::new(
|
||||
ScancodeSet1::new(),
|
||||
layouts::Us104Key,
|
||||
layouts::Uk105Key,
|
||||
HandleControl::Ignore,
|
||||
))
|
||||
});
|
||||
|
||||
let mut keyboard = KEYBOARD.lock();
|
||||
let _keyboard = KEYBOARD.lock();
|
||||
let mut port = Port::new(0x60);
|
||||
|
||||
let scancode: u8 = unsafe { port.read() };
|
||||
if let Ok(Some(key_event)) = keyboard.add_byte(scancode) {
|
||||
if let Some(key) = keyboard.process_keyevent(key_event) {
|
||||
match key {
|
||||
DecodedKey::Unicode(character) => print!("{}", character),
|
||||
DecodedKey::RawKey(key) => print!("{:?}", key),
|
||||
}
|
||||
}
|
||||
}
|
||||
libk::io::keyboard::add_scancode(scancode);
|
||||
|
||||
unsafe {
|
||||
PICS.lock()
|
||||
|
||||
@@ -7,11 +7,11 @@ use limine::{
|
||||
use spin::Lazy;
|
||||
|
||||
#[used]
|
||||
#[link_section = ".requests"]
|
||||
#[unsafe(link_section = ".requests")]
|
||||
static MEMORY_MAP_REQUEST: MemoryMapRequest = MemoryMapRequest::new();
|
||||
|
||||
#[used]
|
||||
#[link_section = ".requests"]
|
||||
#[unsafe(link_section = ".requests")]
|
||||
static HIGHER_HALF_DIRECT_MAP_REQUEST: HhdmRequest = HhdmRequest::new();
|
||||
|
||||
/// ```rs
|
||||
@@ -26,7 +26,7 @@ pub static PHYSICAL_MEMORY_OFFSET: Lazy<u64> = Lazy::new(|| {
|
||||
});
|
||||
|
||||
#[used]
|
||||
#[link_section = ".requests"]
|
||||
#[unsafe(link_section = ".requests")]
|
||||
static KERNEL_ADDRESS_REQUEST: KernelAddressRequest = KernelAddressRequest::new();
|
||||
|
||||
/// Converts virtual addresses in the kernel to a physical address like this:
|
||||
@@ -35,7 +35,7 @@ static KERNEL_ADDRESS_REQUEST: KernelAddressRequest = KernelAddressRequest::new(
|
||||
/// ```
|
||||
///
|
||||
/// Returns (virtual_base, physical_base)
|
||||
pub static KERNEL_PHYSICAL_MEMORY_OFFSET: Lazy<(u64, u64)> = Lazy::new(|| {
|
||||
pub static _KERNEL_PHYSICAL_MEMORY_OFFSET: Lazy<(u64, u64)> = Lazy::new(|| {
|
||||
let resp = KERNEL_ADDRESS_REQUEST.get_response().unwrap();
|
||||
|
||||
// These are base addresses, using Limine's built in page table.
|
||||
@@ -49,7 +49,7 @@ pub static KERNEL_PHYSICAL_MEMORY_OFFSET: Lazy<(u64, u64)> = Lazy::new(|| {
|
||||
/// Panics if the memory map was not found in MEMORY_MAP_REQUEST.
|
||||
pub fn get_memory_map() -> &'static MemoryMapResponse {
|
||||
if let Some(memory_map) = MEMORY_MAP_REQUEST.get_response() {
|
||||
return memory_map;
|
||||
memory_map
|
||||
} else {
|
||||
unreachable!("Could not fetch memory map from Limine.")
|
||||
}
|
||||
|
||||
@@ -1,12 +1,18 @@
|
||||
use lib_alloc::allocator::FoundryAllocator;
|
||||
// use lib_alloc::allocator::FoundryAllocator;
|
||||
use limine::{memory_map::EntryType, response::MemoryMapResponse};
|
||||
use x86_64::{
|
||||
addr,
|
||||
PhysAddr,
|
||||
VirtAddr,
|
||||
// addr,
|
||||
registers::control::Cr3,
|
||||
structures::paging::{
|
||||
page_table::FrameError, FrameAllocator, OffsetPageTable, PageTable, PhysFrame, Size4KiB,
|
||||
// page_table::FrameError,
|
||||
FrameAllocator,
|
||||
OffsetPageTable,
|
||||
PageTable,
|
||||
PhysFrame,
|
||||
Size4KiB,
|
||||
},
|
||||
PhysAddr, VirtAddr,
|
||||
};
|
||||
|
||||
/// Returns a mutable reference to the current level 4 page table.
|
||||
@@ -21,7 +27,7 @@ unsafe fn active_l4_table(physical_memory_offset: VirtAddr) -> &'static mut Page
|
||||
|
||||
let phys_addr = level_4_frame.start_address();
|
||||
let virt = phys_addr.as_u64() + physical_memory_offset.as_u64();
|
||||
&mut *(virt as *mut PageTable)
|
||||
unsafe { &mut *(virt as *mut PageTable) }
|
||||
}
|
||||
|
||||
/// Initializes the `OffsetPageTable` for the current CPU architecture.
|
||||
@@ -43,8 +49,10 @@ unsafe fn active_l4_table(physical_memory_offset: VirtAddr) -> &'static mut Page
|
||||
/// Returns an `OffsetPageTable` that allows for manipulation of the page
|
||||
/// tables for the current CPU architecture.
|
||||
pub unsafe fn init(physical_memory_offset: VirtAddr) -> OffsetPageTable<'static> {
|
||||
unsafe {
|
||||
let l4_table = active_l4_table(physical_memory_offset);
|
||||
OffsetPageTable::new(l4_table, physical_memory_offset)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct FoundryOSFrameAllocator {
|
||||
@@ -70,7 +78,7 @@ impl FoundryOSFrameAllocator {
|
||||
/// Yields one `PhysFrame` for each available 4KiB frame in the memory map.
|
||||
///
|
||||
/// This function is used to allocate frames for the pagemap.
|
||||
fn usable_frames(&self) -> impl Iterator<Item = PhysFrame> {
|
||||
fn usable_frames(&self) -> impl Iterator<Item = PhysFrame> + use<> {
|
||||
let regions = self.memory_map.entries().iter();
|
||||
let usable_regions = regions.filter(|region| region.entry_type == EntryType::USABLE);
|
||||
|
||||
@@ -93,7 +101,6 @@ unsafe impl FrameAllocator<Size4KiB> for FoundryOSFrameAllocator {
|
||||
///
|
||||
/// - `Some(PhysFrame)`: If a usable frame is available.
|
||||
/// - `None`: If there are no more usable frames to allocate.
|
||||
|
||||
fn allocate_frame(&mut self) -> Option<PhysFrame> {
|
||||
let frame = self.usable_frames().nth(self.next);
|
||||
self.next += 1;
|
||||
|
||||
+8
-18
@@ -4,14 +4,12 @@
|
||||
extern crate alloc;
|
||||
|
||||
use core::arch::asm;
|
||||
use lib_alloc::allocator::init_heap;
|
||||
use limine::request::{RequestsEndMarker, RequestsStartMarker};
|
||||
use limine::BaseRevision;
|
||||
|
||||
pub use lib_ascii::{print, print_log, println, println_log, WRITER};
|
||||
pub use lib_serial::{serial_print, serial_println, serial_read};
|
||||
use x86_64::structures::paging::Translate;
|
||||
use x86_64::{PhysAddr, VirtAddr};
|
||||
use libk::alloc::init_heap;
|
||||
use libk::prelude::*;
|
||||
|
||||
use x86_64::VirtAddr;
|
||||
|
||||
mod arch;
|
||||
|
||||
@@ -20,17 +18,9 @@ mod arch;
|
||||
/// Be sure to mark all limine requests with #[used], otherwise they may be removed by the compiler.
|
||||
#[used]
|
||||
// The .requests section allows limine to find the requests faster and more safely.
|
||||
#[link_section = ".requests"]
|
||||
#[unsafe(link_section = ".requests")]
|
||||
static BASE_REVISION: BaseRevision = BaseRevision::new();
|
||||
|
||||
/// Define the stand and end markers for Limine requests.
|
||||
#[used]
|
||||
#[link_section = ".requests_start_marker"]
|
||||
static _START_MARKER: RequestsStartMarker = RequestsStartMarker::new();
|
||||
#[used]
|
||||
#[link_section = ".requests_end_marker"]
|
||||
static _END_MARKER: RequestsEndMarker = RequestsEndMarker::new();
|
||||
|
||||
#[panic_handler]
|
||||
fn rust_panic(_info: &core::panic::PanicInfo) -> ! {
|
||||
println!("Kernel panic: {}", _info);
|
||||
@@ -61,7 +51,7 @@ pub fn boot() -> Result<(), &'static str> {
|
||||
let memory_map = memmap::get_memory_map();
|
||||
|
||||
print_log!(" Initialising Serial... ");
|
||||
lib_serial::init()?;
|
||||
libk::io::serial::init()?;
|
||||
println_log!("[Success]");
|
||||
|
||||
print_log!(" Setting Up Global Descriptor Table... ");
|
||||
@@ -82,8 +72,8 @@ pub fn boot() -> Result<(), &'static str> {
|
||||
println_log!("[Success]");
|
||||
|
||||
print_log!(" Initialising Heap... ");
|
||||
if let Err(e) = init_heap(&mut l4_table, &mut frame_allocator) {
|
||||
return Err("Failed to initialise heap");
|
||||
if init_heap(&mut l4_table, &mut frame_allocator).is_err() {
|
||||
return Err("Failed to initialise heap: error");
|
||||
}
|
||||
println_log!("[Success]");
|
||||
|
||||
|
||||
+13
-10
@@ -3,15 +3,14 @@
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
use alloc::vec::Vec;
|
||||
|
||||
use foundry_os::{println, println_log};
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn kmain() -> ! {
|
||||
// All limine requests must also be referenced in a called function, otherwise they may be
|
||||
// removed by the linker.
|
||||
use libk::{
|
||||
io,
|
||||
prelude::*,
|
||||
scheduling::task::{Executor, Task},
|
||||
};
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
extern "C" fn kmain() -> ! {
|
||||
println_log!(" [ Initialising Kernel Systems ] ");
|
||||
if let Err(err) = foundry_os::boot() {
|
||||
panic!("{}", err);
|
||||
@@ -19,8 +18,8 @@ unsafe extern "C" fn kmain() -> ! {
|
||||
|
||||
println_log!("[ Kernel Initialised Successfully ] ");
|
||||
|
||||
let dimensions = lib_ascii::screensize_chars();
|
||||
let dimensions2 = lib_framebuffer::screensize_px();
|
||||
let dimensions = io::ascii::screensize_chars();
|
||||
let dimensions2 = io::ascii::screensize_px();
|
||||
|
||||
println!("Dimensions: {}x{} (px)", dimensions2.0, dimensions2.1);
|
||||
println!("Dimensions: {}x{} (chars)", dimensions.0, dimensions.1);
|
||||
@@ -46,5 +45,9 @@ unsafe extern "C" fn kmain() -> ! {
|
||||
"
|
||||
);
|
||||
|
||||
let mut executor = Executor::new();
|
||||
executor.spawn(Task::new(io::keyboard::print_keypresses()));
|
||||
executor.try_run();
|
||||
|
||||
loop {}
|
||||
}
|
||||
|
||||
Submodule lib/lib_alloc deleted from af814bf2ab
Submodule lib/lib_application deleted from 4b1c60676a
Submodule lib/lib_ascii deleted from 70d528b2e8
Submodule lib/lib_framebuffer deleted from 53553278d1
Submodule lib/lib_serial deleted from ed2fa6b501
@@ -0,0 +1,21 @@
|
||||
[package]
|
||||
name = "libk"
|
||||
publish = ["gitea"]
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
authors.workspace = true
|
||||
description = "A library crate used to write the kernel for Foundry OS."
|
||||
|
||||
[dependencies]
|
||||
limine = "0.3.1"
|
||||
x86_64 = "0.15.2"
|
||||
crossbeam = { version = "0.8.4", default-features = false, features = [
|
||||
"alloc",
|
||||
"crossbeam-queue",
|
||||
] }
|
||||
pc-keyboard = "0.8.0"
|
||||
spin = "0.9.8"
|
||||
futures-util = { version = "0.3.31", default-features = false, features = [
|
||||
"alloc",
|
||||
] }
|
||||
linked_list_allocator = "0.10.5"
|
||||
@@ -0,0 +1,24 @@
|
||||
# libk is for the code that did not make the kernel*
|
||||
|
||||
\*crate, lol.
|
||||
|
||||
libk is an attempt to move away from the godforsaken git submodules that plagued our forefathers. Now we have a crate containing a bunch of code that didn't quite make the core kernel crate, which should be:
|
||||
|
||||
* simpler to maintain
|
||||
* has a catchier name
|
||||
* less fighting with Cargo.toml manifests
|
||||
|
||||
## TODO:
|
||||
|
||||
A lot of things must be improved and worked on, feel free to add extra TODOs below.
|
||||
|
||||
[] Create a kernel logging abstraction similar to Linux. (this should probably just use the serial drivers)
|
||||
|
||||
The rationale behind this is that we want some sort of debug log/tracing support so we aren't just printf debugging forever.
|
||||
|
||||
## Authors
|
||||
|
||||
Again, write your name below if you like:
|
||||
|
||||
* @zxq5 (wrote most of the libraries as of 23/02/25)
|
||||
* @nullndvoid (made this lushious library crate)
|
||||
@@ -0,0 +1,3 @@
|
||||
pub mod allocator;
|
||||
|
||||
pub use self::allocator::init_heap;
|
||||
@@ -0,0 +1,45 @@
|
||||
use linked_list_allocator::LockedHeap;
|
||||
use x86_64::{
|
||||
structures::paging::{
|
||||
mapper::MapToError, FrameAllocator, Mapper, Page, PageTableFlags, Size4KiB,
|
||||
},
|
||||
VirtAddr,
|
||||
};
|
||||
|
||||
/// We are currently using a linked list heap allocator which uses our underlying page allocator.
|
||||
pub type FoundryAllocator = LockedHeap;
|
||||
|
||||
#[global_allocator]
|
||||
/// This is now Rust's global allocator, so we can use stuff requiring heap allocations.
|
||||
static ALLOCATOR: FoundryAllocator = FoundryAllocator::empty();
|
||||
|
||||
pub const HEAP_START: usize = 0x4444_4444_0000;
|
||||
pub const HEAP_SIZE: usize = 1000 * 1024;
|
||||
|
||||
/// Sets up the heap using the backing page frame allocator.
|
||||
pub fn init_heap(
|
||||
mapper: &mut impl Mapper<Size4KiB>,
|
||||
frame_allocator: &mut impl FrameAllocator<Size4KiB>,
|
||||
) -> Result<(), MapToError<Size4KiB>> {
|
||||
let range = {
|
||||
let heap_start = VirtAddr::new(HEAP_START as u64);
|
||||
let heap_end = heap_start + HEAP_SIZE as u64 - 1u64;
|
||||
let heap_start_page = Page::<Size4KiB>::containing_address(heap_start);
|
||||
let heap_end_page = Page::<Size4KiB>::containing_address(heap_end);
|
||||
Page::range_inclusive(heap_start_page, heap_end_page)
|
||||
};
|
||||
|
||||
for page in 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 {
|
||||
ALLOCATOR.lock().init(HEAP_START as *mut u8, HEAP_SIZE);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
pub mod ascii;
|
||||
pub mod framebuffer;
|
||||
pub mod keyboard;
|
||||
pub mod port;
|
||||
pub mod serial;
|
||||
|
||||
// Re-exported macro definitions.
|
||||
|
||||
pub use crate::print;
|
||||
pub use crate::print_log;
|
||||
pub use crate::printerr;
|
||||
pub use crate::println;
|
||||
pub use crate::println_log;
|
||||
pub use crate::printlnerr;
|
||||
|
||||
pub use crate::serial_print;
|
||||
pub use crate::serial_println;
|
||||
@@ -0,0 +1,216 @@
|
||||
use core::fmt;
|
||||
use spin::{Lazy, Mutex};
|
||||
use x86_64::instructions::interrupts;
|
||||
|
||||
pub use super::framebuffer::screensize_px;
|
||||
use super::framebuffer::{Colour, FRAMEBUFFER_WRITER};
|
||||
|
||||
mod font;
|
||||
use font::FONT;
|
||||
|
||||
static FONT_WIDTH: u32 = 8;
|
||||
static FONT_HEIGHT: u32 = 16;
|
||||
|
||||
pub static WRITER: Lazy<Mutex<Writer>> = Lazy::new(|| Mutex::new(Writer::new()));
|
||||
|
||||
pub fn screensize_chars() -> (u32, u32) {
|
||||
let writer = WRITER.lock();
|
||||
(writer.screen_width, writer.screen_height)
|
||||
}
|
||||
|
||||
pub struct Writer {
|
||||
/// Measured in chars not pixels.
|
||||
screen_width: u32,
|
||||
/// Measured in chars not pixels.
|
||||
screen_height: u32,
|
||||
/// 16 pixels tall.
|
||||
text_line: u32,
|
||||
/// 8 pixels wide.
|
||||
text_col: u32,
|
||||
|
||||
fg_color: Colour,
|
||||
bg_color: Colour,
|
||||
|
||||
offset1: usize,
|
||||
offset2: usize,
|
||||
}
|
||||
|
||||
impl Default for Writer {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl Writer {
|
||||
pub fn new() -> Self {
|
||||
FRAMEBUFFER_WRITER.lock().as_mut().map_or_else(
|
||||
|| {
|
||||
panic!("Framebuffer writer not initialized.");
|
||||
},
|
||||
|writer| Self {
|
||||
screen_width: writer.width() / 8,
|
||||
screen_height: writer.height() / 16,
|
||||
text_line: 0,
|
||||
text_col: 0,
|
||||
fg_color: Colour::White,
|
||||
bg_color: Colour::Black,
|
||||
offset1: 16,
|
||||
offset2: 0,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
pub fn write_glyph(&mut self, c: u16) {
|
||||
if c as u8 == b'\n' {
|
||||
self.newline();
|
||||
return;
|
||||
}
|
||||
|
||||
// get the character data from the font array. -- each byte is a row of pixels
|
||||
let data: &[u8] = &FONT[c as usize * 16..(c as usize + 1) * 16];
|
||||
|
||||
if let Some(writer) = FRAMEBUFFER_WRITER.lock().as_mut() {
|
||||
for (row, line) in data.iter().enumerate().take(16) {
|
||||
for col in 0..8 {
|
||||
let pixel_x: u32 = self.text_col * FONT_WIDTH + col;
|
||||
let pixel_y: u32 = self.text_line * FONT_HEIGHT + row as u32;
|
||||
|
||||
if line & (0x80 >> col) != 0 {
|
||||
// write the foreground color
|
||||
writer.write_pixel(pixel_x as usize, pixel_y as usize, self.fg_color);
|
||||
} else {
|
||||
// write the background color
|
||||
writer.write_pixel(pixel_x as usize, pixel_y as usize, self.bg_color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// go to next position
|
||||
if self.text_col + 1 >= self.screen_width {
|
||||
self.newline();
|
||||
} else {
|
||||
self.text_col += 1;
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn set_offset(&mut self, offset1: usize, offset2: usize) {
|
||||
self.offset1 = offset1;
|
||||
self.offset2 = offset2;
|
||||
}
|
||||
|
||||
pub const fn dimensions(&self) -> (u32, u32) {
|
||||
(self.screen_width, self.screen_height)
|
||||
}
|
||||
|
||||
pub const fn next_char(&mut self) {
|
||||
self.text_col += 1;
|
||||
}
|
||||
|
||||
pub const fn newline(&mut self) {
|
||||
self.text_col = 0;
|
||||
|
||||
if self.text_line + 1 >= self.screen_height {
|
||||
self.text_line = 0;
|
||||
} else {
|
||||
self.text_line += 1;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_string(&mut self, s: &str) {
|
||||
for c in s.chars() {
|
||||
self.write_glyph(c as u16);
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn set_colour(&mut self, fg: Colour, bg: Colour) {
|
||||
self.fg_color = fg;
|
||||
self.bg_color = bg;
|
||||
}
|
||||
|
||||
pub const fn reset_colour(&mut self) {
|
||||
self.fg_color = Colour::White;
|
||||
self.bg_color = Colour::Black;
|
||||
}
|
||||
}
|
||||
|
||||
impl core::fmt::Write for Writer {
|
||||
fn write_str(&mut self, s: &str) -> core::fmt::Result {
|
||||
self.write_string(s);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn write(args: fmt::Arguments, fg: Colour, bg: Colour) {
|
||||
use core::fmt::Write;
|
||||
|
||||
interrupts::without_interrupts(|| {
|
||||
let mut writer = WRITER.lock();
|
||||
writer.set_colour(fg, bg);
|
||||
writer.write_fmt(args).unwrap();
|
||||
writer.reset_colour();
|
||||
});
|
||||
}
|
||||
|
||||
pub fn _print(args: fmt::Arguments) {
|
||||
x86_64::instructions::interrupts::without_interrupts(|| {
|
||||
write(args, Colour::White, Colour::Black);
|
||||
})
|
||||
}
|
||||
|
||||
pub fn _print_err(args: fmt::Arguments) {
|
||||
x86_64::instructions::interrupts::without_interrupts(|| {
|
||||
write(args, Colour::Red, Colour::Black);
|
||||
})
|
||||
}
|
||||
|
||||
pub fn _print_log(args: fmt::Arguments) {
|
||||
x86_64::instructions::interrupts::without_interrupts(|| {
|
||||
write(args, Colour::Yellow, Colour::Black);
|
||||
})
|
||||
}
|
||||
|
||||
pub fn clear_screen() {
|
||||
interrupts::without_interrupts(|| {
|
||||
let mut writer = WRITER.lock();
|
||||
writer.text_line = 0;
|
||||
writer.text_col = 0;
|
||||
|
||||
if let Some(writer) = FRAMEBUFFER_WRITER.lock().as_mut() {
|
||||
writer.clear();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! println_log {
|
||||
() => ($crate::print_log!("\n"));
|
||||
($($arg:tt)*) => ($crate::print_log!("{}\n", format_args!($($arg)*)));
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! print_log {
|
||||
($($arg:tt)*) => ($crate::io::ascii::_print_log(format_args!($($arg)*)));
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! println {
|
||||
() => ($crate::print!("\n"));
|
||||
($($arg:tt)*) => ($crate::print!("{}\n", format_args!($($arg)*)));
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! print {
|
||||
($($arg:tt)*) => ($crate::io::ascii::_print(format_args!($($arg)*)));
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! printlnerr {
|
||||
() => ($crate::printerr!("\n"));
|
||||
($($arg:tt)*) => ($crate::printerr!("{}\n", format_args!($($arg)*)));
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! printerr {
|
||||
($($arg:tt)*) => ($crate::_print_err(format_args!($($arg)*)));
|
||||
}
|
||||
@@ -0,0 +1,578 @@
|
||||
pub static FONT: [u8; 288 * 16] = [
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // 0
|
||||
0x00, 0x00, 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x30, 0x30, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x00,
|
||||
0x00, // 1
|
||||
0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xbd, 0x99, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00,
|
||||
0x00, // 2
|
||||
0x00, 0x00, 0x7e, 0xff, 0xdb, 0xff, 0xff, 0xc3, 0xe7, 0xff, 0xff, 0x7e, 0x00, 0x00, 0x00,
|
||||
0x00, // 3
|
||||
0x00, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00,
|
||||
0x00, // 4
|
||||
0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // 5
|
||||
0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0xe7, 0xe7, 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
|
||||
0x00, // 6
|
||||
0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
|
||||
0x00, // 7
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // 8
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, // 9
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // 10
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd, 0xbd, 0x99, 0xc3, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, // 11
|
||||
0x00, 0x00, 0x1e, 0x0e, 0x1a, 0x32, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00,
|
||||
0x00, // 12
|
||||
0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00,
|
||||
0x00, // 13
|
||||
0x00, 0x00, 0x7f, 0x63, 0x7f, 0x63, 0x63, 0x63, 0x63, 0x67, 0xe7, 0xe6, 0xc0, 0x00, 0x00,
|
||||
0x00, // 14
|
||||
0x00, 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7, 0x3c, 0xdb, 0x18, 0x18, 0x00, 0x00, 0x00,
|
||||
0x00, // 15
|
||||
0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfe, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00,
|
||||
0x00, // 16
|
||||
0x00, 0x02, 0x06, 0x0e, 0x1e, 0x3e, 0xfe, 0x3e, 0x1e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00,
|
||||
0x00, // 17
|
||||
0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // 18
|
||||
0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00,
|
||||
0x00, // 19
|
||||
0x00, 0x00, 0x7f, 0xdb, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00,
|
||||
0x00, // 20
|
||||
0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00,
|
||||
0x00, // 21
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00,
|
||||
0x00, // 22
|
||||
0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00,
|
||||
0x00, // 23
|
||||
0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00,
|
||||
0x00, // 24
|
||||
0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00,
|
||||
0x00, // 25
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // 26
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // 27
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // 28
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x6c, 0xfe, 0x6c, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // 29
|
||||
0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // 30
|
||||
0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // 31
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // 32
|
||||
0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00,
|
||||
0x00, // 33
|
||||
0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // 34
|
||||
0x00, 0x00, 0x00, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, 0x00, 0x00,
|
||||
0x00, // 35
|
||||
0x18, 0x18, 0x7c, 0xc6, 0xc2, 0xc0, 0x7c, 0x06, 0x06, 0x86, 0xc6, 0x7c, 0x18, 0x18, 0x00,
|
||||
0x00, // 36
|
||||
0x00, 0x00, 0x00, 0x00, 0xc2, 0xc6, 0x0c, 0x18, 0x30, 0x60, 0xc6, 0x86, 0x00, 0x00, 0x00,
|
||||
0x00, // 37
|
||||
0x00, 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x76, 0xdc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00,
|
||||
0x00, // 38
|
||||
0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // 39
|
||||
0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00,
|
||||
0x00, // 40
|
||||
0x00, 0x00, 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00,
|
||||
0x00, // 41
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // 42
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // 43
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00,
|
||||
0x00, // 44
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // 45
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00,
|
||||
0x00, // 46
|
||||
0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00,
|
||||
0x00, // 47
|
||||
0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xd6, 0xd6, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00,
|
||||
0x00, // 48
|
||||
0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00,
|
||||
0x00, // 49
|
||||
0x00, 0x00, 0x7c, 0xc6, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xc6, 0xfe, 0x00, 0x00, 0x00,
|
||||
0x00, // 50
|
||||
0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x3c, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00,
|
||||
0x00, // 51
|
||||
0x00, 0x00, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, 0x0c, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00,
|
||||
0x00, // 52
|
||||
0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xfc, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00,
|
||||
0x00, // 53
|
||||
0x00, 0x00, 0x38, 0x60, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
|
||||
0x00, // 54
|
||||
0x00, 0x00, 0xfe, 0xc6, 0x06, 0x06, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00,
|
||||
0x00, // 55
|
||||
0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
|
||||
0x00, // 56
|
||||
0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x0c, 0x78, 0x00, 0x00, 0x00,
|
||||
0x00, // 57
|
||||
0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // 58
|
||||
0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00,
|
||||
0x00, // 59
|
||||
0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x00, 0x00, 0x00,
|
||||
0x00, // 60
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // 61
|
||||
0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00,
|
||||
0x00, // 62
|
||||
0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00,
|
||||
0x00, // 63
|
||||
0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xde, 0xde, 0xde, 0xdc, 0xc0, 0x7c, 0x00, 0x00, 0x00,
|
||||
0x00, // 64
|
||||
0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00,
|
||||
0x00, // 65
|
||||
0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00,
|
||||
0x00, // 66
|
||||
0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00,
|
||||
0x00, // 67
|
||||
0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00,
|
||||
0x00, // 68
|
||||
0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00,
|
||||
0x00, // 69
|
||||
0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00,
|
||||
0x00, // 70
|
||||
0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00,
|
||||
0x00, // 71
|
||||
0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00,
|
||||
0x00, // 72
|
||||
0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
|
||||
0x00, // 73
|
||||
0x00, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00,
|
||||
0x00, // 74
|
||||
0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00,
|
||||
0x00, // 75
|
||||
0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00,
|
||||
0x00, // 76
|
||||
0x00, 0x00, 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00,
|
||||
0x00, // 77
|
||||
0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00,
|
||||
0x00, // 78
|
||||
0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
|
||||
0x00, // 79
|
||||
0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00,
|
||||
0x00, // 80
|
||||
0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xde, 0x7c, 0x0c, 0x0e, 0x00,
|
||||
0x00, // 81
|
||||
0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00,
|
||||
0x00, // 82
|
||||
0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
|
||||
0x00, // 83
|
||||
0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
|
||||
0x00, // 84
|
||||
0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
|
||||
0x00, // 85
|
||||
0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x10, 0x00, 0x00, 0x00,
|
||||
0x00, // 86
|
||||
0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0xee, 0x6c, 0x00, 0x00, 0x00,
|
||||
0x00, // 87
|
||||
0x00, 0x00, 0xc6, 0xc6, 0x6c, 0x7c, 0x38, 0x38, 0x7c, 0x6c, 0xc6, 0xc6, 0x00, 0x00, 0x00,
|
||||
0x00, // 88
|
||||
0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
|
||||
0x00, // 89
|
||||
0x00, 0x00, 0xfe, 0xc6, 0x86, 0x0c, 0x18, 0x30, 0x60, 0xc2, 0xc6, 0xfe, 0x00, 0x00, 0x00,
|
||||
0x00, // 90
|
||||
0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00,
|
||||
0x00, // 91
|
||||
0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0x70, 0x38, 0x1c, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00,
|
||||
0x00, // 92
|
||||
0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c, 0x00, 0x00, 0x00,
|
||||
0x00, // 93
|
||||
0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // 94
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
|
||||
0x00, // 95
|
||||
0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // 96
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00,
|
||||
0x00, // 97
|
||||
0x00, 0x00, 0xe0, 0x60, 0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00,
|
||||
0x00, // 98
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00,
|
||||
0x00, // 99
|
||||
0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00,
|
||||
0x00, // 100
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00,
|
||||
0x00, // 101
|
||||
0x00, 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00,
|
||||
0x00, // 102
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78,
|
||||
0x00, // 103
|
||||
0x00, 0x00, 0xe0, 0x60, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00,
|
||||
0x00, // 104
|
||||
0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
|
||||
0x00, // 105
|
||||
0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c,
|
||||
0x00, // 106
|
||||
0x00, 0x00, 0xe0, 0x60, 0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00,
|
||||
0x00, // 107
|
||||
0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
|
||||
0x00, // 108
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0xfe, 0xd6, 0xd6, 0xd6, 0xd6, 0xc6, 0x00, 0x00, 0x00,
|
||||
0x00, // 109
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00,
|
||||
0x00, // 110
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
|
||||
0x00, // 111
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0,
|
||||
0x00, // 112
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x1e,
|
||||
0x00, // 113
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00,
|
||||
0x00, // 114
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00,
|
||||
0x00, // 115
|
||||
0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00,
|
||||
0x00, // 116
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00,
|
||||
0x00, // 117
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00,
|
||||
0x00, // 118
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00,
|
||||
0x00, // 119
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x6c, 0x38, 0x38, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00,
|
||||
0x00, // 120
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8,
|
||||
0x00, // 121
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00,
|
||||
0x00, // 122
|
||||
0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00,
|
||||
0x00, // 123
|
||||
0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00,
|
||||
0x00, // 124
|
||||
0x00, 0x00, 0x70, 0x18, 0x18, 0x18, 0x0e, 0x18, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00,
|
||||
0x00, // 125
|
||||
0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // 126
|
||||
0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // 127
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // 128
|
||||
0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00,
|
||||
0x00, // 129
|
||||
0x00, 0x18, 0x18, 0x3c, 0x66, 0x60, 0x60, 0x60, 0x66, 0x3c, 0x18, 0x18, 0x00, 0x00, 0x00,
|
||||
0x00, // 130
|
||||
0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xe6, 0xfc, 0x00, 0x00, 0x00,
|
||||
0x00, // 131
|
||||
0x00, 0x00, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00,
|
||||
0x00, // 132
|
||||
0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00,
|
||||
0x00, // 133
|
||||
0x00, 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // 134
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // 135
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // 136
|
||||
0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // 137
|
||||
0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
|
||||
0x00, // 138
|
||||
0x00, 0x70, 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // 139
|
||||
0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xc0, 0x00, 0x00,
|
||||
0x00, // 140
|
||||
0x00, 0x00, 0x7f, 0xdb, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00,
|
||||
0x00, // 141
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // 142
|
||||
0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // 143
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36, 0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // 144
|
||||
0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x66, 0xce, 0x9e, 0x3e, 0x06, 0x06, 0x00,
|
||||
0x00, // 145
|
||||
0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xdc, 0x86, 0x0c, 0x18, 0x3e, 0x00,
|
||||
0x00, // 146
|
||||
0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, 0xc0, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
|
||||
0x00, // 147
|
||||
0x00, 0xc6, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00,
|
||||
0x00, // 148
|
||||
0x38, 0x6c, 0x38, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00,
|
||||
0x00, // 149
|
||||
0x00, 0x00, 0x3e, 0x6c, 0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00,
|
||||
0x00, // 150
|
||||
0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x0c, 0x06, 0x7c, 0x00,
|
||||
0x00, // 151
|
||||
0x18, 0x30, 0x60, 0x00, 0xfe, 0x66, 0x60, 0x7c, 0x60, 0x60, 0x66, 0xfe, 0x00, 0x00, 0x00,
|
||||
0x00, // 152
|
||||
0x76, 0xdc, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00,
|
||||
0x00, // 153
|
||||
0x00, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
|
||||
0x00, // 154
|
||||
0x00, 0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
|
||||
0x00, // 155
|
||||
0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xd8, 0xcc, 0xc6, 0xc6, 0xc6, 0xcc, 0x00, 0x00, 0x00,
|
||||
0x00, // 156
|
||||
0x00, 0x60, 0x30, 0x18, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00,
|
||||
0x00, // 157
|
||||
0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00,
|
||||
0x00, // 158
|
||||
0x00, 0x10, 0x38, 0x6c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00,
|
||||
0x00, // 159
|
||||
0x00, 0x00, 0xcc, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00,
|
||||
0x00, // 160
|
||||
0x00, 0x38, 0x6c, 0x38, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00,
|
||||
0x00, // 161
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0x76, 0x36, 0x7e, 0xd8, 0xd8, 0x6e, 0x00, 0x00, 0x00,
|
||||
0x00, // 162
|
||||
0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x60, 0x60, 0x66, 0x3c, 0x0c, 0x06, 0x3c, 0x00, 0x00,
|
||||
0x00, // 163
|
||||
0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00,
|
||||
0x00, // 164
|
||||
0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00,
|
||||
0x00, // 165
|
||||
0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00,
|
||||
0x00, // 166
|
||||
0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00,
|
||||
0x00, // 167
|
||||
0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
|
||||
0x00, // 168
|
||||
0x00, 0x0c, 0x18, 0x30, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
|
||||
0x00, // 169
|
||||
0x00, 0x18, 0x3c, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
|
||||
0x00, // 170
|
||||
0x00, 0x00, 0x66, 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
|
||||
0x00, // 171
|
||||
0x00, 0x00, 0x76, 0xdc, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00,
|
||||
0x00, // 172
|
||||
0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
|
||||
0x00, // 173
|
||||
0x00, 0x18, 0x30, 0x60, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
|
||||
0x00, // 174
|
||||
0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
|
||||
0x00, // 175
|
||||
0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
|
||||
0x00, // 176
|
||||
0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // 177
|
||||
0x00, 0x60, 0x30, 0x18, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00,
|
||||
0x00, // 178
|
||||
0x00, 0x18, 0x30, 0x60, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00,
|
||||
0x00, // 179
|
||||
0x00, 0x30, 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00,
|
||||
0x00, // 180
|
||||
0x00, 0x00, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00,
|
||||
0x00, // 181
|
||||
0x00, 0x00, 0xc6, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0x78,
|
||||
0x00, // 182
|
||||
0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0x70, 0x00,
|
||||
0x00, // 183
|
||||
0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00,
|
||||
0x00, // 184
|
||||
0x00, 0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00,
|
||||
0x00, // 185
|
||||
0x00, 0x00, 0x00, 0xfe, 0xc6, 0x60, 0x30, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00,
|
||||
0x00, // 186
|
||||
0x00, 0x00, 0x00, 0x7e, 0x18, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00,
|
||||
0x00, // 187
|
||||
0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0x6c, 0xee, 0x00, 0x00, 0x00,
|
||||
0x00, // 188
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0xd8, 0xd8, 0xd8, 0xdc, 0x76, 0x00, 0x00, 0x00,
|
||||
0x00, // 189
|
||||
0x00, 0x00, 0x1e, 0x30, 0x18, 0x0c, 0x3e, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00,
|
||||
0x00, // 190
|
||||
0x00, 0x00, 0x1c, 0x30, 0x60, 0x60, 0x7c, 0x60, 0x60, 0x60, 0x30, 0x1c, 0x00, 0x00, 0x00,
|
||||
0x00, // 191
|
||||
0x00, 0x00, 0x00, 0x00, 0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00,
|
||||
0x00, // 192
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00,
|
||||
0x00, // 193
|
||||
0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00,
|
||||
0x00, // 194
|
||||
0x00, 0x00, 0x00, 0x03, 0x06, 0x7e, 0xdb, 0xdb, 0xf3, 0x7e, 0x60, 0xc0, 0x00, 0x00, 0x00,
|
||||
0x00, // 195
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // 196
|
||||
0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00,
|
||||
0x00, // 197
|
||||
0x00, 0xd8, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // 198
|
||||
0x00, 0xf8, 0xcc, 0xcc, 0xf8, 0xc4, 0xcc, 0xde, 0xcc, 0xcc, 0xcc, 0xc6, 0x00, 0x00, 0x00,
|
||||
0x00, // 199
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // 200
|
||||
0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00,
|
||||
0x00, // 201
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // 202
|
||||
0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00,
|
||||
0x00, // 203
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x6c, 0xfe, 0x6c, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // 204
|
||||
0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // 205
|
||||
0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00,
|
||||
0x00, // 206
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // 207
|
||||
0x00, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x6c, 0x3c, 0x1c, 0x00, 0x00, 0x00,
|
||||
0x00, // 208
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xdb, 0xdb, 0xdb, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // 209
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // 210
|
||||
0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00,
|
||||
0x00, // 211
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // 212
|
||||
0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // 213
|
||||
0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, 0x7e, 0x00, 0x00, 0x00,
|
||||
0x00, // 214
|
||||
0x00, 0x00, 0x00, 0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x00, 0x7e, 0x00, 0x00, 0x00,
|
||||
0x00, // 215
|
||||
0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // 216
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // 217
|
||||
0x00, 0x00, 0x0e, 0x1b, 0x1b, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||
0x18, // 218
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00,
|
||||
0x00, // 219
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // 220
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||
0x18, // 221
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||
0x18, // 222
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||
0x18, // 223
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // 224
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // 225
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||
0x18, // 226
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||
0x18, // 227
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||
0x18, // 228
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // 229
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||
0x18, // 230
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // 231
|
||||
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
|
||||
0x36, // 232
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||
0x18, // 233
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
|
||||
0x36, // 234
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
|
||||
0x36, // 235
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||
0x18, // 236
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
|
||||
0x36, // 237
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
|
||||
0x36, // 238
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // 239
|
||||
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // 240
|
||||
0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // 241
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // 242
|
||||
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // 243
|
||||
0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // 244
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||
0x18, // 245
|
||||
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
|
||||
0x36, // 246
|
||||
0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
|
||||
0x36, // 247
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||
0x18, // 248
|
||||
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
|
||||
0x36, // 249
|
||||
0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
|
||||
0x36, // 250
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||
0x18, // 251
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
|
||||
0x36, // 252
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
|
||||
0x36, // 253
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // 254
|
||||
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // 255
|
||||
0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // 256
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||
0x18, // 257
|
||||
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
|
||||
0x36, // 258
|
||||
0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
|
||||
0x36, // 259
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // 260
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, // 261
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, // 262
|
||||
0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
|
||||
0xf0, // 263
|
||||
0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
|
||||
0x0f, // 264
|
||||
0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11,
|
||||
0x44, // 265
|
||||
0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55,
|
||||
0xaa, // 266
|
||||
0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd,
|
||||
0x77, // 267
|
||||
0x00, 0x00, 0x00, 0x00, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // 268
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00,
|
||||
0x00, // 269
|
||||
0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // 270
|
||||
0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfe, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00,
|
||||
0x00, // 271
|
||||
0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // 272
|
||||
0x00, 0x02, 0x06, 0x0e, 0x1e, 0x3e, 0xfe, 0x3e, 0x1e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00,
|
||||
0x00, // 273
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // 274
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, // 275
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd, 0xbd, 0x99, 0xc3, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, // 276
|
||||
0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xbd, 0x99, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00,
|
||||
0x00, // 277
|
||||
0x00, 0x00, 0x7e, 0xff, 0xdb, 0xff, 0xff, 0xc3, 0xe7, 0xff, 0xff, 0x7e, 0x00, 0x00, 0x00,
|
||||
0x00, // 278
|
||||
0x00, 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7, 0x3c, 0xdb, 0x18, 0x18, 0x00, 0x00, 0x00,
|
||||
0x00, // 279
|
||||
0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00,
|
||||
0x00, // 280
|
||||
0x00, 0x00, 0x1e, 0x0e, 0x1a, 0x32, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00,
|
||||
0x00, // 281
|
||||
0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
|
||||
0x00, // 282
|
||||
0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0xe7, 0xe7, 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
|
||||
0x00, // 283
|
||||
0x00, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00,
|
||||
0x00, // 284
|
||||
0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // 285
|
||||
0x00, 0x00, 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x30, 0x30, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x00,
|
||||
0x00, // 286
|
||||
0x00, 0x00, 0x7f, 0x63, 0x7f, 0x63, 0x63, 0x63, 0x63, 0x67, 0xe7, 0xe6, 0xc0, 0x00, 0x00,
|
||||
0x00, // 287
|
||||
];
|
||||
@@ -0,0 +1,99 @@
|
||||
use limine::request::FramebufferRequest;
|
||||
|
||||
#[used]
|
||||
#[unsafe(link_section = ".requests")]
|
||||
static FRAMEBUFFER_REQUEST: FramebufferRequest = FramebufferRequest::new();
|
||||
|
||||
mod colour;
|
||||
|
||||
pub use colour::Colour;
|
||||
use core::panic;
|
||||
|
||||
use limine::framebuffer::Framebuffer;
|
||||
use spin::{Lazy, Mutex};
|
||||
|
||||
pub static FRAMEBUFFER_WRITER: Lazy<Mutex<Option<FramebufferWriter>>> = Lazy::new(|| {
|
||||
Mutex::new(FRAMEBUFFER_REQUEST.get_response().map_or_else(
|
||||
|| {
|
||||
panic!("Framebuffer request failed");
|
||||
},
|
||||
|framebuffer_response| {
|
||||
let framebuffer = framebuffer_response.framebuffers().next().unwrap();
|
||||
Some(FramebufferWriter::new(framebuffer))
|
||||
},
|
||||
))
|
||||
});
|
||||
|
||||
/// The updated writer stores necessary fields from the [Framebuffer].
|
||||
/// This ensures that the contained types are Send, as Framebuffer was
|
||||
/// not marked as Send.
|
||||
///
|
||||
/// It also avoids the requirement for lifetimes.
|
||||
///
|
||||
/// Note this does not implement Writer as these functions only handle drawing pixels.
|
||||
pub struct FramebufferWriter {
|
||||
pitch: u64,
|
||||
bpp: u16,
|
||||
addr: *mut u8,
|
||||
width: u64,
|
||||
height: u64,
|
||||
}
|
||||
|
||||
unsafe impl Send for FramebufferWriter {}
|
||||
unsafe impl Sync for FramebufferWriter {}
|
||||
|
||||
impl FramebufferWriter {
|
||||
pub fn new(framebuffer: Framebuffer) -> Self {
|
||||
Self {
|
||||
pitch: framebuffer.pitch(),
|
||||
bpp: framebuffer.bpp(),
|
||||
addr: framebuffer.addr(),
|
||||
width: framebuffer.width(),
|
||||
height: framebuffer.height(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_pixel(&self, x: usize, y: usize, color: Colour) {
|
||||
let pitch = self.pitch as usize;
|
||||
let bpp = (self.bpp / 8) as usize;
|
||||
let pixel_offset = y * pitch + x * bpp;
|
||||
|
||||
unsafe {
|
||||
*(self.addr.add(pixel_offset) as *mut u32) = color.into();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render_frame(&self, buffer: &[Colour; 1280 * 800]) {
|
||||
for (y, row) in buffer.chunks(1280).enumerate() {
|
||||
for (x, pixel) in row.iter().enumerate() {
|
||||
self.write_pixel(x, y, *pixel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn width(&self) -> u32 {
|
||||
self.width as u32
|
||||
}
|
||||
|
||||
pub const fn height(&self) -> u32 {
|
||||
self.height as u32
|
||||
}
|
||||
|
||||
pub fn clear(&self) {
|
||||
let width = self.width as usize;
|
||||
let height = self.height as usize;
|
||||
|
||||
for y in 0..height {
|
||||
for x in 0..width {
|
||||
self.write_pixel(x, y, Colour::Black);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn screensize_px() -> (u32, u32) {
|
||||
FRAMEBUFFER_WRITER
|
||||
.lock()
|
||||
.as_mut()
|
||||
.map_or_else(|| (0, 0), |writer| (writer.width(), writer.height()))
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
#[repr(u32)]
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
pub enum Colour {
|
||||
ARGB(u8, u8, u8, u8),
|
||||
RGB(u8, u8, u8),
|
||||
HexARGB(u32),
|
||||
Black = 0x000000FF,
|
||||
Blue = 0x0000FFFF,
|
||||
Green = 0x00FF00FF,
|
||||
Cyan = 0x00FFFFFF,
|
||||
Red = 0xFF0000FF,
|
||||
Magenta = 0xFF00FFFF,
|
||||
Yellow = 0xFFFF00FF,
|
||||
White = 0xFFFFFFFF,
|
||||
}
|
||||
|
||||
#[allow(clippy::use_self)]
|
||||
impl From<Colour> for u32 {
|
||||
fn from(val: Colour) -> Self {
|
||||
match val {
|
||||
Colour::ARGB(a, r, g, b) => {
|
||||
(a as u32) << 24 | (r as u32) << 16 | (g as u32) << 8 | (b as u32)
|
||||
}
|
||||
Colour::RGB(r, g, b) => ((r as u32) << 16) | (g as u32) << 8 | (b as u32),
|
||||
Colour::HexARGB(hex) => hex,
|
||||
Colour::Black => 0xFF000000,
|
||||
Colour::Blue => 0xFF0000FF,
|
||||
Colour::Green => 0xFF00FF00,
|
||||
Colour::Cyan => 0xFF00FFFF,
|
||||
Colour::Red => 0xFFFF0000,
|
||||
Colour::Magenta => 0xFFFF00FF,
|
||||
Colour::Yellow => 0xFFFFFF00,
|
||||
Colour::White => 0xFFFFFFFF,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl core::fmt::Display for Colour {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
match self {
|
||||
Self::ARGB(r, g, b, a) => write!(f, "RGBA(#{:x}{:x}{:x}{:x})", r, g, b, a),
|
||||
Self::RGB(r, g, b) => write!(f, "RGB(#{:x}{:x}{:x})", r, g, b),
|
||||
Self::HexARGB(hex) => write!(f, "Hex(#{:x})", hex),
|
||||
Self::Black => write!(f, "Black"),
|
||||
Self::Blue => write!(f, "Blue"),
|
||||
Self::Green => write!(f, "Green"),
|
||||
Self::Cyan => write!(f, "Cyan"),
|
||||
Self::Red => write!(f, "Red"),
|
||||
Self::Magenta => write!(f, "Magenta"),
|
||||
Self::Yellow => write!(f, "Yellow"),
|
||||
Self::White => write!(f, "White"),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
extern crate alloc;
|
||||
|
||||
use core::{
|
||||
pin::Pin,
|
||||
task::{Context, Poll},
|
||||
};
|
||||
|
||||
use crate::prelude::*;
|
||||
use crossbeam::queue::ArrayQueue;
|
||||
use futures_util::{Stream, task::AtomicWaker};
|
||||
use spin::Once;
|
||||
|
||||
static KBD_QUEUE: Once<ArrayQueue<u8>> = Once::new();
|
||||
static WAKER: AtomicWaker = AtomicWaker::new();
|
||||
|
||||
pub fn add_scancode(scancode: u8) {
|
||||
if let Some(queue) = KBD_QUEUE.get() {
|
||||
if queue.push(scancode).is_err() {
|
||||
println!("WARNING: scancode queue full; dropping keyboard input");
|
||||
} else {
|
||||
println!("waking waker");
|
||||
WAKER.wake();
|
||||
}
|
||||
} else {
|
||||
println!("WARNING: scancode queue not initialised");
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ScanCodeStream {
|
||||
_private: (),
|
||||
}
|
||||
|
||||
impl ScanCodeStream {
|
||||
pub fn new() -> Self {
|
||||
KBD_QUEUE.call_once(|| ArrayQueue::new(5));
|
||||
|
||||
Self { _private: () }
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for ScanCodeStream {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl Stream for ScanCodeStream {
|
||||
type Item = u8;
|
||||
|
||||
fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
|
||||
let queue = KBD_QUEUE.get().expect("scancode queue not initialized");
|
||||
serial_println!("This is called once.");
|
||||
WAKER.register(cx.waker());
|
||||
|
||||
// fast path
|
||||
if let Some(scancode) = queue.pop() {
|
||||
return Poll::Ready(Some(scancode));
|
||||
}
|
||||
|
||||
queue.pop().map_or_else(
|
||||
|| {
|
||||
print!("Returning");
|
||||
Poll::Pending
|
||||
},
|
||||
|scancode| {
|
||||
print!("Scancode found");
|
||||
WAKER.take();
|
||||
Poll::Ready(Some(scancode))
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
use futures_util::stream::StreamExt;
|
||||
use pc_keyboard::{DecodedKey, HandleControl, Keyboard, ScancodeSet1, layouts};
|
||||
|
||||
pub async fn print_keypresses() {
|
||||
let mut scancodes = ScanCodeStream::new();
|
||||
let mut keyboard = Keyboard::new(
|
||||
ScancodeSet1::new(),
|
||||
layouts::Us104Key,
|
||||
HandleControl::Ignore,
|
||||
);
|
||||
|
||||
serial_println!("Printing keypresses.");
|
||||
|
||||
while let Some(scancode) = scancodes.next().await {
|
||||
if let Ok(Some(key_event)) = keyboard.add_byte(scancode) {
|
||||
if let Some(key) = keyboard.process_keyevent(key_event) {
|
||||
match key {
|
||||
DecodedKey::Unicode(character) => print!("{}", character),
|
||||
DecodedKey::RawKey(key) => print!("{:?}", key),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
//! Functions for IO using ports.
|
||||
|
||||
use core::arch::asm;
|
||||
|
||||
#[inline]
|
||||
pub fn inb(port: u16) -> u8 {
|
||||
let value: u8;
|
||||
unsafe {
|
||||
asm!(
|
||||
"in al, dx",
|
||||
out("al") value,
|
||||
in("dx") port,
|
||||
options(nomem, nostack, preserves_flags)
|
||||
);
|
||||
}
|
||||
value
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn outb(port: u16, value: u8) {
|
||||
unsafe {
|
||||
asm!(
|
||||
"out dx, al",
|
||||
in("dx") port,
|
||||
in("al") value,
|
||||
options(nomem, nostack, preserves_flags)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
use core::{
|
||||
fmt,
|
||||
sync::atomic::{AtomicUsize, Ordering},
|
||||
};
|
||||
use spin::{Lazy, Mutex};
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! serial_println {
|
||||
() => ($crate::serial_print!("\n"));
|
||||
($($arg:tt)*) => ($crate::io::serial_print!("{}\n", format_args!($($arg)*)));
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! serial_print {
|
||||
($($arg:tt)*) => ($crate::io::serial::_serial_write(format_args!($($arg)*)));
|
||||
}
|
||||
|
||||
use super::port::{inb, outb};
|
||||
|
||||
use x86_64::instructions::interrupts;
|
||||
|
||||
pub fn _serial_write(args: fmt::Arguments) {
|
||||
use core::fmt::Write;
|
||||
|
||||
interrupts::without_interrupts(|| {
|
||||
if let Some(writer) = WRITER.lock().as_mut() {
|
||||
writer.write_fmt(args).unwrap();
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn serial_read() -> &'static str {
|
||||
serial_println!("getting value!");
|
||||
|
||||
interrupts::without_interrupts(|| {
|
||||
if let Some(reader) = READER.lock().as_mut() {
|
||||
serial_println!("stuff happnin.");
|
||||
reader.read_str_to_buffer();
|
||||
} else {
|
||||
serial_println!("failed to get writer");
|
||||
}
|
||||
});
|
||||
|
||||
serial_println!("eee");
|
||||
|
||||
let i = BUFFER_LEN.load(Ordering::SeqCst);
|
||||
|
||||
unsafe {
|
||||
if i != 0 {
|
||||
core::str::from_utf8(&BUFFER[..i - 1]).unwrap()
|
||||
} else {
|
||||
serial_println!("empty string");
|
||||
""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static PORT: u16 = 0x3f8;
|
||||
static mut BUFFER: [u8; 256] = [0; 256];
|
||||
static BUFFER_LEN: AtomicUsize = AtomicUsize::new(0);
|
||||
|
||||
static READER: Lazy<Mutex<Option<Reader>>> = Lazy::new(|| Mutex::new(None));
|
||||
static WRITER: Lazy<Mutex<Option<Writer>>> = Lazy::new(|| Mutex::new(None));
|
||||
|
||||
struct Reader;
|
||||
|
||||
struct Writer;
|
||||
|
||||
impl fmt::Write for Writer {
|
||||
fn write_str(&mut self, s: &str) -> fmt::Result {
|
||||
for c in s.chars() {
|
||||
self.write_byte(c as u8);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Writer {
|
||||
unsafe fn write_success(&self) -> bool {
|
||||
inb(PORT + 5) & 0x20 != 0
|
||||
}
|
||||
|
||||
pub fn write_byte(&self, data: u8) {
|
||||
unsafe {
|
||||
while !self.write_success() {}
|
||||
outb(PORT, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init() -> Result<(), &'static str> {
|
||||
test()?;
|
||||
|
||||
if READER.lock().is_none() {
|
||||
*READER.lock() = Some(Reader);
|
||||
}
|
||||
|
||||
if WRITER.lock().is_none() {
|
||||
*WRITER.lock() = Some(Writer);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn test() -> Result<(), &'static str> {
|
||||
outb(PORT + 1, 0x00); // Disable all interrupts
|
||||
outb(PORT + 3, 0x80); // Enable DLAB (set baud rate divisor)
|
||||
outb(PORT, 0x03); // Set divisor to 3 (lo byte) 38400 baud
|
||||
outb(PORT + 1, 0x00); // (hi byte)
|
||||
outb(PORT + 3, 0x03); // 8 bits, no parity, one stop bit
|
||||
outb(PORT + 2, 0xC7); // Enable FIFO, clear them, with 14-bytethreshold
|
||||
outb(PORT + 4, 0x0B); // IRQs enabled, RTS/DSR set
|
||||
outb(PORT + 4, 0x1E); // Set in loopback mode, test the serial chip
|
||||
outb(PORT, 0xAE); // Test serial chip (send byte 0xAE and check if serial returns same byte)
|
||||
|
||||
if inb(PORT) != 0xAE {
|
||||
return Err("serial test failed");
|
||||
}
|
||||
|
||||
outb(PORT + 4, 0x0F);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
impl Reader {
|
||||
pub fn read_str_to_buffer(&mut self) {
|
||||
unsafe {
|
||||
while !self.read_ready() {}
|
||||
|
||||
BUFFER_LEN.store(0, Ordering::SeqCst);
|
||||
|
||||
while BUFFER_LEN.load(Ordering::SeqCst) < 256 {
|
||||
let c = self.read();
|
||||
BUFFER[BUFFER_LEN.load(Ordering::SeqCst)] = c;
|
||||
if c as char == '\r' {
|
||||
break;
|
||||
}
|
||||
BUFFER_LEN.fetch_add(1, Ordering::SeqCst);
|
||||
}
|
||||
|
||||
serial_println!("returning")
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn read_ready(&self) -> bool {
|
||||
inb(PORT + 5) & 1 != 0
|
||||
}
|
||||
|
||||
pub fn read(&self) -> u8 {
|
||||
unsafe {
|
||||
while !self.read_ready() {}
|
||||
inb(PORT)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#![no_std]
|
||||
#![warn(tail_expr_drop_order)]
|
||||
#![warn(clippy::correctness, clippy::perf, clippy::nursery)]
|
||||
// alloc
|
||||
// io : serial, framebuffer, ascii(?), keyboard
|
||||
// ?????
|
||||
// scheduling / tasks : async
|
||||
|
||||
pub mod alloc;
|
||||
pub mod io;
|
||||
pub mod scheduling;
|
||||
|
||||
/// Re-exports most of the IO macros.
|
||||
pub mod prelude {
|
||||
pub use crate::{print, print_log, println, println_log, serial_print, serial_println};
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
pub mod task;
|
||||
@@ -0,0 +1,139 @@
|
||||
extern crate alloc;
|
||||
use alloc::{boxed::Box, collections::BTreeMap, sync::Arc, task::Wake};
|
||||
use core::{
|
||||
future::Future,
|
||||
pin::Pin,
|
||||
sync::atomic::{AtomicU64, Ordering},
|
||||
task::{Context, Poll, Waker},
|
||||
};
|
||||
use crossbeam::queue::ArrayQueue;
|
||||
|
||||
pub struct Task {
|
||||
id: TaskId,
|
||||
future: Pin<Box<dyn Future<Output = ()>>>,
|
||||
}
|
||||
|
||||
impl Task {
|
||||
pub fn new(future: impl Future<Output = ()> + 'static) -> Self {
|
||||
Self {
|
||||
id: TaskId::new(),
|
||||
future: Box::pin(future),
|
||||
}
|
||||
}
|
||||
|
||||
fn poll(&mut self, context: &mut Context) -> Poll<()> {
|
||||
self.future.as_mut().poll(context)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Executor {
|
||||
tasks: BTreeMap<TaskId, Task>,
|
||||
task_queue: Arc<ArrayQueue<TaskId>>,
|
||||
waker_cache: BTreeMap<TaskId, Waker>,
|
||||
}
|
||||
|
||||
impl Default for Executor {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl Executor {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
tasks: BTreeMap::new(),
|
||||
task_queue: Arc::new(ArrayQueue::new(100)),
|
||||
waker_cache: BTreeMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn spawn(&mut self, task: Task) {
|
||||
let task_id = task.id;
|
||||
if self.tasks.insert(task.id, task).is_some() {
|
||||
panic!("a task with this id has already been allocated");
|
||||
}
|
||||
self.task_queue.push(task_id).expect("task queue is full");
|
||||
}
|
||||
|
||||
fn run_ready_tasks(&mut self) {
|
||||
let Self {
|
||||
tasks,
|
||||
task_queue,
|
||||
waker_cache,
|
||||
} = self;
|
||||
|
||||
while let Some(task_id) = task_queue.pop() {
|
||||
let task = match tasks.get_mut(&task_id) {
|
||||
Some(task) => task,
|
||||
None => continue,
|
||||
};
|
||||
let waker = waker_cache
|
||||
.entry(task_id)
|
||||
.or_insert_with(|| TaskWaker::waker(task_id, task_queue.clone()));
|
||||
let mut context = Context::from_waker(waker);
|
||||
match task.poll(&mut context) {
|
||||
Poll::Ready(()) => {
|
||||
tasks.remove(&task_id);
|
||||
waker_cache.remove(&task_id);
|
||||
}
|
||||
Poll::Pending => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn try_run(&mut self) {
|
||||
self.run_ready_tasks();
|
||||
self.sleep_if_idle();
|
||||
}
|
||||
|
||||
fn sleep_if_idle(&self) {
|
||||
use x86_64::instructions::interrupts::{self, enable_and_hlt};
|
||||
|
||||
interrupts::disable();
|
||||
if self.task_queue.is_empty() {
|
||||
enable_and_hlt();
|
||||
} else {
|
||||
interrupts::enable();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct TaskWaker {
|
||||
task_id: TaskId,
|
||||
task_queue: Arc<ArrayQueue<TaskId>>,
|
||||
}
|
||||
|
||||
impl TaskWaker {
|
||||
fn waker(task_id: TaskId, task_queue: Arc<ArrayQueue<TaskId>>) -> Waker {
|
||||
Waker::from(Arc::new(Self {
|
||||
task_id,
|
||||
task_queue,
|
||||
}))
|
||||
}
|
||||
|
||||
fn wake_task(&self) {
|
||||
self.task_queue
|
||||
.push(self.task_id)
|
||||
.expect("task queue is full!");
|
||||
}
|
||||
}
|
||||
|
||||
impl Wake for TaskWaker {
|
||||
fn wake(self: Arc<Self>) {
|
||||
self.wake_task();
|
||||
}
|
||||
|
||||
fn wake_by_ref(self: &Arc<Self>) {
|
||||
self.wake_task();
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||
struct TaskId(u64);
|
||||
|
||||
impl TaskId {
|
||||
fn new() -> Self {
|
||||
static NEXT: AtomicU64 = AtomicU64::new(0);
|
||||
Self(NEXT.fetch_add(1, Ordering::Relaxed))
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Script originally written by zxq5, I added separate scripts to remove `jq` dependency.
|
||||
|
||||
# Colors
|
||||
GREEN='\033[0;32m'
|
||||
BLUE='\033[0;34m'
|
||||
@@ -16,6 +18,8 @@ trap 'echo -e "${RED}${BOLD}error${NC}: build failed" >&2' ERR
|
||||
script_dir=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd)
|
||||
project_root=$(cd "$script_dir/.." &>/dev/null && pwd)
|
||||
|
||||
echo -e "${GREEN}${BOLD} Running kernel in debug mode."
|
||||
|
||||
# Logging functions
|
||||
info() {
|
||||
echo -e "${BLUE}${BOLD}info${NC}: $1"
|
||||
@@ -124,8 +128,8 @@ else
|
||||
kvm_flag=""
|
||||
fi
|
||||
|
||||
# Check if we're running in debug mode
|
||||
if [[ "$(cargo metadata --format-version=1 | jq -r '.workspace_members[0]' | cut -d' ' -f2)" == "(debug)" ]]; then
|
||||
# Enable using GDB with $USE_GDB.
|
||||
if [ $USE_GDB ]; then
|
||||
debug_flags="-s -S"
|
||||
else
|
||||
debug_flags=""
|
||||
Executable
+186
@@ -0,0 +1,186 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Script originally written by zxq5, I added separate scripts to remove `jq` dependency.
|
||||
|
||||
# Colors
|
||||
GREEN='\033[0;32m'
|
||||
BLUE='\033[0;34m'
|
||||
YELLOW='\033[0;33m'
|
||||
RED='\033[0;31m'
|
||||
BOLD='\033[1m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Error handling
|
||||
set -e
|
||||
trap 'echo -e "${RED}${BOLD}error${NC}: build failed" >&2' ERR
|
||||
|
||||
# Get absolute path to project root
|
||||
script_dir=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd)
|
||||
project_root=$(cd "$script_dir/.." &>/dev/null && pwd)
|
||||
|
||||
echo -e "${GREEN}${BOLD} Running kernel in release mode."
|
||||
|
||||
# Logging functions
|
||||
info() {
|
||||
echo -e "${BLUE}${BOLD}info${NC}: $1"
|
||||
}
|
||||
|
||||
compiling() {
|
||||
echo -e "${GREEN}${BOLD}Compiling${NC}: $1"
|
||||
}
|
||||
|
||||
warning() {
|
||||
echo -e "${YELLOW}${BOLD}warning${NC}: $1" >&2
|
||||
}
|
||||
|
||||
building() {
|
||||
echo -e "${GREEN}${BOLD}Building${NC}: $1"
|
||||
}
|
||||
|
||||
copying() {
|
||||
echo -e "${GREEN}${BOLD} Copying${NC}: $1 to $2"
|
||||
}
|
||||
|
||||
error() {
|
||||
echo -e "${RED}${BOLD}error${NC}: $1" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
copy_file() {
|
||||
copying $1 $2
|
||||
cp "$1" "$2" || error $3
|
||||
}
|
||||
|
||||
build_dir="$project_root/build"
|
||||
iso_root="$build_dir/iso_root"
|
||||
|
||||
# Check if we're running tests
|
||||
is_test=0
|
||||
if [[ $1 == *"deps"* ]]; then
|
||||
is_test=1
|
||||
kernel_path="$1"
|
||||
else
|
||||
# Build the kernel normally
|
||||
cd "$project_root"
|
||||
# cargo build
|
||||
kernel_path="$build_dir/target/x86_64-kernel/release/kernel"
|
||||
fi
|
||||
|
||||
# Check for required tools
|
||||
check_tools() {
|
||||
local missing=0
|
||||
for tool in xorriso git qemu-system-x86_64; do
|
||||
if ! command -v $tool >/dev/null 2>&1; then
|
||||
error "required tool '$tool' is not installed"
|
||||
missing=1
|
||||
fi
|
||||
done
|
||||
if [ $missing -eq 1 ]; then
|
||||
error "missing required tools"
|
||||
fi
|
||||
}
|
||||
|
||||
# Create build directory structure
|
||||
info "Creating build directory structure"
|
||||
mkdir -p "$iso_root/boot/limine"
|
||||
mkdir -p "$iso_root/EFI/BOOT"
|
||||
|
||||
# Clone Limine if needed
|
||||
if [ ! -d "$build_dir/limine" ]; then
|
||||
compiling "limine bootloader"
|
||||
cd "$build_dir"
|
||||
git clone https://github.com/limine-bootloader/limine.git --branch=v9.x-binary --depth=1 "$build_dir/limine" || error "failed to clone limine"
|
||||
make -C "$build_dir/limine" || error "failed to build limine"
|
||||
cd "$project_root"
|
||||
fi
|
||||
|
||||
# Copy files
|
||||
info "Copying files to ISO root"
|
||||
copy_file "$kernel_path" "$iso_root/boot/kernel" "failed to copy kernel"
|
||||
copy_file "$project_root/config/limine.conf" "$iso_root/boot/limine/limine.conf" "failed to copy limine config"
|
||||
copy_file "$build_dir/limine/limine-bios-cd.bin" "$iso_root/boot/limine/" "failed to copy limine-bios-cd.bin"
|
||||
copy_file "$build_dir/limine/limine-uefi-cd.bin" "$iso_root/boot/limine/" "failed to copy limine-uefi-cd.bin"
|
||||
copy_file "$build_dir/limine/limine-bios.sys" "$iso_root/boot/limine/" "failed to copy limine-bios.sys"
|
||||
copy_file "$build_dir/limine/BOOTX64.EFI" "$iso_root/EFI/BOOT/" "failed to copy BOOTX64.EFI"
|
||||
copy_file "$build_dir/limine/BOOTIA32.EFI" "$iso_root/EFI/BOOT/" "failed to copy BOOTIA32.EFI"
|
||||
|
||||
# Create ISO
|
||||
building "bootable ISO image"
|
||||
xorriso -as mkisofs -R -r -J -b boot/limine/limine-bios-cd.bin \
|
||||
-no-emul-boot -boot-load-size 4 -boot-info-table -hfsplus \
|
||||
-apm-block-size 2048 --efi-boot boot/limine/limine-uefi-cd.bin \
|
||||
-efi-boot-part --efi-boot-image --protective-msdos-label \
|
||||
"$iso_root" -o "$build_dir/image.iso" || error "failed to create ISO"
|
||||
|
||||
# Install Limine
|
||||
info "Installing Limine bootloader"
|
||||
"$build_dir/limine/limine" bios-install "$build_dir/image.iso" || error "failed to install limine"
|
||||
|
||||
# Check if KVM is available
|
||||
if [ "${KVM_FLAG:-enable}" = "disable" ]; then
|
||||
warning "KVM acceleration disabled by user"
|
||||
kvm_flag=""
|
||||
elif [ -c "/dev/kvm" ] && [ -w "/dev/kvm" ]; then
|
||||
info "KVM acceleration enabled"
|
||||
kvm_flag="-enable-kvm"
|
||||
else
|
||||
warning "KVM acceleration not available (is kvm module loaded?)"
|
||||
kvm_flag=""
|
||||
fi
|
||||
|
||||
# I'm lazy but I just remove GDB flags when running this script.
|
||||
debug_flags=""
|
||||
|
||||
# Set up test-specific flags
|
||||
if [ $is_test -eq 1 ]; then
|
||||
test_flags="-device isa-debug-exit,iobase=0xf4,iosize=0x04 -display none"
|
||||
serial_flags="-serial stdio"
|
||||
else
|
||||
test_flags=""
|
||||
# serial_flags="-serial tcp:127.0.0.1:1234,server -monitor telnet:127.0.0.1:1235,server"
|
||||
serial_flags="-serial stdio"
|
||||
fi
|
||||
|
||||
# Run in QEMU
|
||||
if [[ ${QEMU_FLAGS} == *-S* ]]; then
|
||||
info "Running OS in QEMU with GDB debugging enabled"
|
||||
info "To connect GDB, run: gdb"
|
||||
info "At the GDB prompt, type: target remote localhost:1234"
|
||||
else
|
||||
info "Running OS in QEMU..."
|
||||
fi
|
||||
|
||||
check_test_res() {
|
||||
qemu_exit_code=$?
|
||||
if [ $qemu_exit_code -eq 33 ]; then
|
||||
# Success case (0x10 << 1) | 1 = 33
|
||||
info "All tests passed"
|
||||
exit 0
|
||||
elif [ $qemu_exit_code -eq 35 ]; then
|
||||
# Failure case (0x11 << 1) | 1 = 35
|
||||
warning "Some tests failed"
|
||||
exit 1
|
||||
else
|
||||
# Any other exit code is treated as a failure
|
||||
warning "Some tests failed"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
kvm_flag=""
|
||||
|
||||
trap 'check_test_res "tests completed"' ERR
|
||||
|
||||
cd "$project_root"
|
||||
qemu-system-x86_64 -M q35 \
|
||||
${kvm_flag} \
|
||||
-cdrom "$build_dir/image.iso" \
|
||||
-boot d \
|
||||
-m 2G \
|
||||
${serial_flags} \
|
||||
-no-reboot \
|
||||
${test_flags} \
|
||||
${debug_flags} \
|
||||
${QEMU_FLAGS:-}
|
||||
|
||||
Reference in New Issue
Block a user