feat: Can start normally
This commit is contained in:
parent
920f7f5fc8
commit
4977f17e79
15
builder/Cargo.toml
Normal file
15
builder/Cargo.toml
Normal file
@ -0,0 +1,15 @@
|
||||
[package]
|
||||
name = "cure-builder"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
|
||||
[build-dependencies]
|
||||
bootloader = "0.11.12"
|
||||
|
||||
# artifact dependency - 指定 kernel 的 target
|
||||
[build-dependencies.cure-kernel]
|
||||
path = "../kernel"
|
||||
artifact = "bin"
|
||||
target = "x86_64-unknown-none"
|
||||
34
builder/build.rs
Normal file
34
builder/build.rs
Normal file
@ -0,0 +1,34 @@
|
||||
use std::path::PathBuf;
|
||||
|
||||
fn main() {
|
||||
// 從環境變數獲取內核路徑(運行時)
|
||||
let kernel_path = PathBuf::from(
|
||||
std::env::var("CARGO_BIN_FILE_CURE_KERNEL_cure-kernel")
|
||||
.expect("CARGO_BIN_FILE_CURE_KERNEL_cure-kernel not set")
|
||||
);
|
||||
|
||||
println!("cargo:warning=Kernel path: {:?}", kernel_path);
|
||||
|
||||
// 創建輸出目錄
|
||||
let out_dir = PathBuf::from(std::env::var("OUT_DIR").unwrap());
|
||||
|
||||
// 創建 BIOS 磁盤映像
|
||||
let bios_path = out_dir.join("cure-bios.img");
|
||||
bootloader::BiosBoot::new(&kernel_path)
|
||||
.create_disk_image(&bios_path)
|
||||
.expect("Failed to create BIOS disk image");
|
||||
|
||||
// 創建 UEFI 磁盤映像
|
||||
let uefi_path = out_dir.join("cure-uefi.img");
|
||||
bootloader::UefiBoot::new(&kernel_path)
|
||||
.create_disk_image(&uefi_path)
|
||||
.expect("Failed to create UEFI disk image");
|
||||
|
||||
// 輸出路徑信息
|
||||
println!("cargo:warning=✓ BIOS image: {:?}", bios_path);
|
||||
println!("cargo:warning=✓ UEFI image: {:?}", uefi_path);
|
||||
|
||||
// 讓 cargo 知道磁盤映像的位置
|
||||
println!("cargo:rustc-env=BIOS_IMAGE={}", bios_path.display());
|
||||
println!("cargo:rustc-env=UEFI_IMAGE={}", uefi_path.display());
|
||||
}
|
||||
4
builder/src/main.rs
Normal file
4
builder/src/main.rs
Normal file
@ -0,0 +1,4 @@
|
||||
fn main() {
|
||||
println!("Build completed successfully!");
|
||||
println!("Disk images created in target directory");
|
||||
}
|
||||
7
kernel/.cargo/config.toml
Normal file
7
kernel/.cargo/config.toml
Normal file
@ -0,0 +1,7 @@
|
||||
[unstable]
|
||||
bindeps = true
|
||||
|
||||
# 只對 kernel 套用 no_std target
|
||||
[target.x86_64-unknown-none]
|
||||
build-std = ["core", "compiler_builtins"]
|
||||
build-std-features = ["compiler-builtins-mem"]
|
||||
15
kernel/Cargo.toml
Normal file
15
kernel/Cargo.toml
Normal file
@ -0,0 +1,15 @@
|
||||
[package]
|
||||
name = "cure-kernel"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
bootloader_api = "0.11.12"
|
||||
lazy_static = { version = "1.5.0", features = ["spin_no_std"] }
|
||||
x86_64 = { version = "0.15.2", features = ["instructions"] }
|
||||
spin = "0.10.0"
|
||||
raw-cpuid = "10.7.0"
|
||||
|
||||
[package.metadata.bootloader]
|
||||
map-physical-memory = true
|
||||
physical-memory-offset = "0xFFFF800000000000"
|
||||
279
kernel/src/hal/cpu.rs
Normal file
279
kernel/src/hal/cpu.rs
Normal file
@ -0,0 +1,279 @@
|
||||
// kernel/src/hal/cpu.rs
|
||||
use x86_64::registers::control::{Cr0, Cr0Flags, Cr2, Cr3, Cr4, Cr4Flags};
|
||||
use x86_64::instructions::{interrupts, hlt};
|
||||
use core::arch::asm;
|
||||
use x86_64::VirtAddr;
|
||||
|
||||
/// 64 位元暫存器類型
|
||||
#[allow(dead_code)]
|
||||
pub type Reg64 = u64;
|
||||
/// 32 位元暫存器類型
|
||||
#[allow(dead_code)]
|
||||
pub type Reg32 = u32;
|
||||
/// 16 位元暫存器類型
|
||||
#[allow(dead_code)]
|
||||
pub type Reg16 = u16;
|
||||
|
||||
/// 通用目的暫存器結構 (64-bit)
|
||||
#[allow(dead_code)]
|
||||
#[repr(C, packed)]
|
||||
pub struct GpRegs {
|
||||
pub rax: Reg64,
|
||||
pub rbx: Reg64,
|
||||
pub rcx: Reg64,
|
||||
pub rdx: Reg64,
|
||||
pub rdi: Reg64,
|
||||
pub rbp: Reg64,
|
||||
pub rsi: Reg64,
|
||||
pub rsp: Reg64,
|
||||
pub r8: Reg64,
|
||||
pub r9: Reg64,
|
||||
pub r10: Reg64,
|
||||
pub r11: Reg64,
|
||||
pub r12: Reg64,
|
||||
pub r13: Reg64,
|
||||
pub r14: Reg64,
|
||||
pub r15: Reg64,
|
||||
}
|
||||
|
||||
/// 段暫存器結構
|
||||
#[allow(dead_code)]
|
||||
#[repr(C, packed)]
|
||||
pub struct SgReg {
|
||||
pub ss: Reg16,
|
||||
pub es: Reg16,
|
||||
pub ds: Reg16,
|
||||
pub fs: Reg16,
|
||||
pub gs: Reg16,
|
||||
pub cs: Reg16,
|
||||
}
|
||||
|
||||
// ============ 控制寄存器 ============
|
||||
|
||||
/// 讀取 CR0 暫存器
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
pub fn cpu_r_cr0() -> Cr0Flags {
|
||||
Cr0::read()
|
||||
}
|
||||
|
||||
/// 讀取 CR2 暫存器
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
pub fn cpu_r_cr2() -> u64 {
|
||||
Cr2::read_raw()
|
||||
}
|
||||
|
||||
/// 讀取 CR3 暫存器
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
pub fn cpu_r_cr3() -> u64 {
|
||||
Cr3::read().0.start_address().as_u64()
|
||||
}
|
||||
|
||||
/// 讀取 CR4 暫存器
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
pub fn cpu_r_cr4() -> Cr4Flags {
|
||||
Cr4::read()
|
||||
}
|
||||
|
||||
/// 寫入 CR0 暫存器
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
pub fn cpu_w_cr0(val: Cr0Flags) {
|
||||
unsafe { Cr0::write(val); }
|
||||
}
|
||||
|
||||
/// 寫入 CR3 暫存器
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
pub fn cpu_w_cr3(val: u64) {
|
||||
use x86_64::{PhysAddr, structures::paging::PhysFrame};
|
||||
|
||||
let frame = PhysFrame::containing_address(PhysAddr::new(val));
|
||||
unsafe {
|
||||
Cr3::write(frame, Cr3::read().1);
|
||||
}
|
||||
}
|
||||
|
||||
/// 寫入 CR4 暫存器
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
pub fn cpu_w_cr4(val: Cr4Flags) {
|
||||
unsafe { Cr4::write(val); }
|
||||
}
|
||||
|
||||
// ============ CPU 資訊 ============
|
||||
|
||||
/// 獲取 CPU 供應商 ID
|
||||
///
|
||||
/// # 參數
|
||||
/// * `model_out` - 輸出緩衝區,至少需要 13 bytes
|
||||
/// # 返回
|
||||
/// 字符串切片,表示 CPU 供應商資訊
|
||||
#[allow(dead_code)]
|
||||
pub fn cpu_get_model(model_out: &mut [u8]) -> &str {
|
||||
if model_out.len() < 13 {
|
||||
return "Buffer too small";
|
||||
}
|
||||
|
||||
// 使用 raw_cpuid crate
|
||||
use raw_cpuid::CpuId;
|
||||
let cpuid = CpuId::new();
|
||||
|
||||
if let Some(vendor) = cpuid.get_vendor_info() {
|
||||
let vendor_string = vendor.as_str();
|
||||
let bytes = vendor_string.as_bytes();
|
||||
let copy_len = core::cmp::min(bytes.len(), model_out.len() - 1);
|
||||
|
||||
model_out[..copy_len].copy_from_slice(&bytes[..copy_len]);
|
||||
model_out[copy_len] = 0; // null terminator
|
||||
|
||||
match core::str::from_utf8(&model_out[..copy_len]) {
|
||||
Ok(s) => s,
|
||||
Err(_) => "Invalid UTF-8"
|
||||
}
|
||||
} else {
|
||||
model_out[0] = b'?';
|
||||
model_out[1] = 0;
|
||||
"Unknown Vendor"
|
||||
}
|
||||
}
|
||||
|
||||
/// 檢查是否支持品牌字串
|
||||
#[allow(dead_code)]
|
||||
pub fn cpu_brand_string_supported() -> bool {
|
||||
use raw_cpuid::CpuId;
|
||||
let cpuid = CpuId::new();
|
||||
cpuid.get_processor_brand_string().is_some()
|
||||
}
|
||||
|
||||
/// 獲取 CPU 品牌字串
|
||||
///
|
||||
/// # 參數
|
||||
/// * `brand_out` - 輸出緩衝區,至少需要 49 bytes
|
||||
///
|
||||
/// # 返回
|
||||
/// 字符串切片,表示 CPU 品牌
|
||||
#[allow(dead_code)]
|
||||
pub fn cpu_get_brand(brand_out: &mut [u8]) -> &str {
|
||||
if brand_out.len() < 49 {
|
||||
return "Buffer too small";
|
||||
}
|
||||
|
||||
use raw_cpuid::CpuId;
|
||||
let cpuid = CpuId::new();
|
||||
|
||||
if let Some(brand) = cpuid.get_processor_brand_string() {
|
||||
let brand_string = brand.as_str();
|
||||
let bytes = brand_string.as_bytes();
|
||||
let copy_len = core::cmp::min(bytes.len(), brand_out.len() - 1);
|
||||
|
||||
brand_out[..copy_len].copy_from_slice(&bytes[..copy_len]);
|
||||
brand_out[copy_len] = 0; // null terminator
|
||||
|
||||
core::str::from_utf8(&brand_out[..copy_len]).unwrap_or_else(|_| "Invalid UTF-8")
|
||||
} else {
|
||||
brand_out[0] = b'?';
|
||||
brand_out[1] = 0;
|
||||
"Unknown CPU"
|
||||
}
|
||||
}
|
||||
|
||||
// ============ CPU 指令 ============
|
||||
|
||||
/// 讀取 CPU 時間戳計數器 (TSC)
|
||||
///
|
||||
/// # 返回
|
||||
/// 時間戳計數值
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
pub fn cpu_rdtsc() -> u64 {
|
||||
unsafe {
|
||||
let low: u32;
|
||||
let high: u32;
|
||||
asm!(
|
||||
"rdtsc",
|
||||
out("eax") low,
|
||||
out("edx") high,
|
||||
options(nomem, nostack, preserves_flags)
|
||||
);
|
||||
((high as u64) << 32) | (low as u64)
|
||||
}
|
||||
}
|
||||
|
||||
/// 執行 CPU 暫停指令 (減少功耗)
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
pub fn cpu_pause() {
|
||||
core::hint::spin_loop();
|
||||
}
|
||||
|
||||
/// 停止 CPU 執行,直到下一個中斷發生
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
pub fn cpu_halt() {
|
||||
hlt();
|
||||
}
|
||||
|
||||
/// 停止 CPU 並進入低功耗模式 (等同於 cpu_halt)
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
pub fn cpu_idle() {
|
||||
hlt();
|
||||
}
|
||||
|
||||
/// 啟用中斷
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
pub fn cpu_enable_interrupts() {
|
||||
interrupts::enable();
|
||||
}
|
||||
|
||||
/// 禁用中斷
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
pub fn cpu_disable_interrupts() {
|
||||
interrupts::disable();
|
||||
}
|
||||
|
||||
/// 檢查中斷是否啟用
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
pub fn cpu_interrupts_enabled() -> bool {
|
||||
interrupts::are_enabled()
|
||||
}
|
||||
|
||||
/// 在禁用中斷的情況下執行閉包
|
||||
///
|
||||
/// # 範例
|
||||
/// ```
|
||||
/// cpu_without_interrupts(|| {
|
||||
/// // 臨界區代碼
|
||||
/// // 中斷被禁用
|
||||
/// });
|
||||
/// // 中斷恢復到之前的狀態
|
||||
/// ```
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
pub fn cpu_without_interrupts<F, R>(f: F) -> R
|
||||
where
|
||||
F: FnOnce() -> R,
|
||||
{
|
||||
interrupts::without_interrupts(f)
|
||||
}
|
||||
|
||||
/// 無條件觸發斷點異常 (用於調試)
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
pub fn cpu_breakpoint() {
|
||||
x86_64::instructions::interrupts::int3();
|
||||
}
|
||||
|
||||
/// 讀取 RFLAGS 寄存器
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
pub fn cpu_read_flags() -> u64 {
|
||||
x86_64::registers::rflags::read().bits()
|
||||
}
|
||||
83
kernel/src/hal/io.rs
Normal file
83
kernel/src/hal/io.rs
Normal file
@ -0,0 +1,83 @@
|
||||
// kernel/src/hal/io.rs
|
||||
use x86_64::instructions::port::{Port, PortReadOnly, PortWriteOnly};
|
||||
|
||||
/// 向 I/O 端口寫入一個字節
|
||||
///
|
||||
/// # 參數
|
||||
/// * `port` - 端口號
|
||||
/// * `value` - 要寫入的值
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
pub fn io_port_wb(port: u16, value: u8) {
|
||||
unsafe {
|
||||
Port::new(port).write(value);
|
||||
}
|
||||
}
|
||||
|
||||
/// 從 I/O 端口讀取一個字節
|
||||
///
|
||||
/// # 參數
|
||||
/// * `port` - 端口號
|
||||
/// # 返回
|
||||
/// 讀取到的值
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
pub fn io_port_rb(port: u16) -> u8 {
|
||||
unsafe {
|
||||
Port::new(port).read()
|
||||
}
|
||||
}
|
||||
|
||||
/// 向 I/O 端口寫入一個字 (16-bit)
|
||||
///
|
||||
/// # 參數
|
||||
/// * `port` - 端口號
|
||||
/// * `value` - 要寫入的值
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
pub fn io_port_ww(port: u16, value: u16) {
|
||||
unsafe {
|
||||
Port::new(port).write(value);
|
||||
}
|
||||
}
|
||||
|
||||
/// 從 I/O 端口讀取一個字 (16-bit)
|
||||
///
|
||||
/// # 參數
|
||||
/// * `port` - 端口號
|
||||
/// # 返回
|
||||
/// 讀取到的值
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
pub fn io_port_rw(port: u16) -> u16 {
|
||||
unsafe {
|
||||
Port::new(port).read()
|
||||
}
|
||||
}
|
||||
|
||||
/// 向 I/O 端口寫入一個雙字 (32-bit)
|
||||
///
|
||||
/// # 參數
|
||||
/// * `port` - 端口號
|
||||
/// * `value` - 要寫入的值
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
pub fn io_port_wl(port: u16, value: u32) {
|
||||
unsafe {
|
||||
Port::new(port).write(value);
|
||||
}
|
||||
}
|
||||
|
||||
/// 從 I/O 端口讀取一個雙字 (32-bit)
|
||||
///
|
||||
/// # 參數
|
||||
/// * `port` - 端口號
|
||||
/// # 返回
|
||||
/// 讀取到的值
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
pub fn io_port_rl(port: u16) -> u32 {
|
||||
unsafe {
|
||||
Port::new(port).read()
|
||||
}
|
||||
}
|
||||
22
kernel/src/hal/mod.rs
Normal file
22
kernel/src/hal/mod.rs
Normal file
@ -0,0 +1,22 @@
|
||||
pub mod io;
|
||||
pub mod cpu;
|
||||
|
||||
pub use io::io_port_wb;
|
||||
pub use io::io_port_wl;
|
||||
pub use io::io_port_rb;
|
||||
pub use io::io_port_rl;
|
||||
|
||||
pub use cpu::cpu_r_cr0;
|
||||
pub use cpu::cpu_r_cr2;
|
||||
pub use cpu::cpu_r_cr3;
|
||||
pub use cpu::cpu_w_cr0;
|
||||
pub use cpu::cpu_w_cr3;
|
||||
pub use cpu::cpu_get_model;
|
||||
pub use cpu::cpu_brand_string_supported;
|
||||
pub use cpu::cpu_get_brand;
|
||||
pub use cpu::cpu_rdtsc;
|
||||
pub use cpu::cpu_pause;
|
||||
pub use cpu::cpu_halt;
|
||||
pub use cpu::cpu_idle;
|
||||
pub use cpu::cpu_enable_interrupts;
|
||||
pub use cpu::cpu_disable_interrupts;
|
||||
1
kernel/src/kernel/asm/mod.rs
Normal file
1
kernel/src/kernel/asm/mod.rs
Normal file
@ -0,0 +1 @@
|
||||
pub mod x86;
|
||||
64
kernel/src/kernel/asm/x86/gdt.rs
Normal file
64
kernel/src/kernel/asm/x86/gdt.rs
Normal file
@ -0,0 +1,64 @@
|
||||
// kernel/src/gdt.rs
|
||||
use x86_64::structures::gdt::{GlobalDescriptorTable, Descriptor, SegmentSelector};
|
||||
use x86_64::structures::tss::TaskStateSegment;
|
||||
use x86_64::VirtAddr;
|
||||
use lazy_static::lazy_static;
|
||||
|
||||
pub const DOUBLE_FAULT_IST_INDEX: u16 = 0;
|
||||
|
||||
// === 步驟 1: 創建 TSS ===
|
||||
lazy_static! {
|
||||
static ref TSS: TaskStateSegment = {
|
||||
let mut tss = TaskStateSegment::new();
|
||||
|
||||
tss.interrupt_stack_table[DOUBLE_FAULT_IST_INDEX as usize] = {
|
||||
const STACK_SIZE: usize = 4096 * 5; // 20KB
|
||||
static mut STACK: [u8; STACK_SIZE] = [0; STACK_SIZE];
|
||||
|
||||
let stack_start = VirtAddr::new(unsafe { &raw const STACK as *const _ as u64 });
|
||||
let stack_end = stack_start + STACK_SIZE as u64;
|
||||
|
||||
stack_end
|
||||
};
|
||||
|
||||
tss
|
||||
};
|
||||
}
|
||||
|
||||
// === 步驟 2: 創建 GDT ===
|
||||
lazy_static! {
|
||||
static ref GDT: (GlobalDescriptorTable, Selectors) = {
|
||||
let mut gdt = GlobalDescriptorTable::new();
|
||||
|
||||
let code_selector = gdt.append(Descriptor::kernel_code_segment());
|
||||
let data_selector = gdt.append(Descriptor::kernel_data_segment());
|
||||
let tss_selector = gdt.append(Descriptor::tss_segment(&TSS));
|
||||
|
||||
(
|
||||
gdt,
|
||||
Selectors {
|
||||
code_selector,
|
||||
data_selector,
|
||||
tss_selector,
|
||||
},
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
struct Selectors {
|
||||
code_selector: SegmentSelector,
|
||||
data_selector: SegmentSelector,
|
||||
tss_selector: SegmentSelector,
|
||||
}
|
||||
|
||||
pub fn init() {
|
||||
use x86_64::instructions::segmentation::{Segment, CS};
|
||||
use x86_64::instructions::tables::load_tss;
|
||||
|
||||
GDT.0.load();
|
||||
|
||||
unsafe {
|
||||
CS::set_reg(GDT.1.code_selector);
|
||||
load_tss(GDT.1.tss_selector);
|
||||
}
|
||||
}
|
||||
0
kernel/src/kernel/asm/x86/idt.rs
Normal file
0
kernel/src/kernel/asm/x86/idt.rs
Normal file
0
kernel/src/kernel/asm/x86/interrupt.S
Normal file
0
kernel/src/kernel/asm/x86/interrupt.S
Normal file
0
kernel/src/kernel/asm/x86/interrupt.rs
Normal file
0
kernel/src/kernel/asm/x86/interrupt.rs
Normal file
4
kernel/src/kernel/asm/x86/mod.rs
Normal file
4
kernel/src/kernel/asm/x86/mod.rs
Normal file
@ -0,0 +1,4 @@
|
||||
pub mod gdt;
|
||||
// pub mod idt;
|
||||
// pub mod interrupt;
|
||||
// pub mod segment;
|
||||
0
kernel/src/kernel/asm/x86/segment.rs
Normal file
0
kernel/src/kernel/asm/x86/segment.rs
Normal file
5
kernel/src/kernel/mod.rs
Normal file
5
kernel/src/kernel/mod.rs
Normal file
@ -0,0 +1,5 @@
|
||||
pub mod tty;
|
||||
pub mod asm;
|
||||
|
||||
// 重新導出由 boot.S 調用的入口點
|
||||
// pub use kernel::{_kernel_init, _kernel_main};
|
||||
133
kernel/src/kernel/tty/font.rs
Normal file
133
kernel/src/kernel/tty/font.rs
Normal file
@ -0,0 +1,133 @@
|
||||
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub static FONT_BASIC: [[u8; 16]; 128] = [
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ], //0x00,
|
||||
[ 0x00, 0x00, 0x7E, 0x81, 0xA5, 0x81, 0x81, 0xBD, 0x99, 0x81, 0x81, 0x7E, 0x00, 0x00, 0x00, 0x00, ], //0x01,
|
||||
[ 0x00, 0x00, 0x7E, 0xFF, 0xDB, 0xFF, 0xFF, 0xC3, 0xE7, 0xFF, 0xFF, 0x7E, 0x00, 0x00, 0x00, 0x00, ], //0x02,
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x6C, 0xFE, 0xFE, 0xFE, 0xFE, 0x7C, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, ], //0x03,
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7C, 0xFE, 0x7C, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, ], //0x04,
|
||||
[ 0x00, 0x00, 0x00, 0x18, 0x3C, 0x3C, 0xE7, 0xE7, 0xE7, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00, ], //0x05,
|
||||
[ 0x00, 0x00, 0x00, 0x18, 0x3C, 0x7E, 0xFF, 0xFF, 0x7E, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00, ], //0x06,
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3C, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ], //0x07,
|
||||
[ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0xC3, 0xC3, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ], //0x08,
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x66, 0x42, 0x42, 0x66, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, ], //0x09,
|
||||
[ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC3, 0x99, 0xBD, 0xBD, 0x99, 0xC3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ], //0x0A,
|
||||
[ 0x00, 0x00, 0x1E, 0x0E, 0x1A, 0x32, 0x78, 0xCC, 0xCC, 0xCC, 0xCC, 0x78, 0x00, 0x00, 0x00, 0x00, ], //0x0B,
|
||||
[ 0x00, 0x00, 0x3C, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, ], //0x0C,
|
||||
[ 0x00, 0x00, 0x3F, 0x33, 0x3F, 0x30, 0x30, 0x30, 0x30, 0x70, 0xF0, 0xE0, 0x00, 0x00, 0x00, 0x00, ], //0x0D,
|
||||
[ 0x00, 0x00, 0x7F, 0x63, 0x7F, 0x63, 0x63, 0x63, 0x63, 0x67, 0xE7, 0xE6, 0xC0, 0x00, 0x00, 0x00, ], //0x0E,
|
||||
[ 0x00, 0x00, 0x00, 0x18, 0x18, 0xDB, 0x3C, 0xE7, 0x3C, 0xDB, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, ], //0x0F,
|
||||
[ 0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFE, 0xF8, 0xF0, 0xE0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, ], //0x10,
|
||||
[ 0x00, 0x02, 0x06, 0x0E, 0x1E, 0x3E, 0xFE, 0x3E, 0x1E, 0x0E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, ], //0x11,
|
||||
[ 0x00, 0x00, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, ], //0x12,
|
||||
[ 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, ], //0x13,
|
||||
[ 0x00, 0x00, 0x7F, 0xDB, 0xDB, 0xDB, 0x7B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x00, 0x00, 0x00, 0x00, ], //0x14,
|
||||
[ 0x00, 0x7C, 0xC6, 0x60, 0x38, 0x6C, 0xC6, 0xC6, 0x6C, 0x38, 0x0C, 0xC6, 0x7C, 0x00, 0x00, 0x00, ], //0x15,
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00, ], //0x16,
|
||||
[ 0x00, 0x00, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x7E, 0x00, 0x00, 0x00, 0x00, ], //0x17,
|
||||
[ 0x00, 0x00, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, ], //0x18,
|
||||
[ 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00, ], //0x19,
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0C, 0xFE, 0x0C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ], //0x1A,
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xFE, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ], //0x1B, esc
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xC0, 0xC0, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ], //0x1C,
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x6C, 0xFE, 0x6C, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ], //0x1D,
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7C, 0x7C, 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, ], //0x1E,
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0x7C, 0x7C, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, ], //0x1F,
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ], //0x20, ' '
|
||||
[ 0x00, 0x00, 0x18, 0x3C, 0x3C, 0x3C, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, ], //0x21, '!'
|
||||
[ 0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ], //0x22, '"'
|
||||
[ 0x00, 0x00, 0x00, 0x6C, 0x6C, 0xFE, 0x6C, 0x6C, 0x6C, 0xFE, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00, ], //0x23, '#'
|
||||
[ 0x18, 0x18, 0x7C, 0xC6, 0xC2, 0xC0, 0x7C, 0x06, 0x06, 0x86, 0xC6, 0x7C, 0x18, 0x18, 0x00, 0x00, ], //0x24, '$'
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0xC2, 0xC6, 0x0C, 0x18, 0x30, 0x60, 0xC6, 0x86, 0x00, 0x00, 0x00, 0x00, ], //0x25, '%'
|
||||
[ 0x00, 0x00, 0x38, 0x6C, 0x6C, 0x38, 0x76, 0xDC, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, ], //0x26, '&'
|
||||
[ 0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ], //0x27, '''
|
||||
[ 0x00, 0x00, 0x0C, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0C, 0x00, 0x00, 0x00, 0x00, ], //0x28, '('
|
||||
[ 0x00, 0x00, 0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, ], //0x29, ')'
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ], //0x2A, '*'
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ], //0x2B, '+'
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, ], //0x2C, '
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ], //0x2D, '-'
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, ], //0x2E, '.'
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, ], //0x2F, '/'
|
||||
[ 0x00, 0x00, 0x38, 0x6C, 0xC6, 0xC6, 0xD6, 0xD6, 0xC6, 0xC6, 0x6C, 0x38, 0x00, 0x00, 0x00, 0x00, ], //0x30, '0'
|
||||
[ 0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x00, 0x00, 0x00, 0x00, ], //0x31, '1'
|
||||
[ 0x00, 0x00, 0x7C, 0xC6, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0xC6, 0xFE, 0x00, 0x00, 0x00, 0x00, ], //0x32, '2'
|
||||
[ 0x00, 0x00, 0x7C, 0xC6, 0x06, 0x06, 0x3C, 0x06, 0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, ], //0x33, '3'
|
||||
[ 0x00, 0x00, 0x0C, 0x1C, 0x3C, 0x6C, 0xCC, 0xFE, 0x0C, 0x0C, 0x0C, 0x1E, 0x00, 0x00, 0x00, 0x00, ], //0x34, '4'
|
||||
[ 0x00, 0x00, 0xFE, 0xC0, 0xC0, 0xC0, 0xFC, 0x06, 0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, ], //0x35, '5'
|
||||
[ 0x00, 0x00, 0x38, 0x60, 0xC0, 0xC0, 0xFC, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, ], //0x36, '6'
|
||||
[ 0x00, 0x00, 0xFE, 0xC6, 0x06, 0x06, 0x0C, 0x18, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, ], //0x37, '7'
|
||||
[ 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, ], //0x38, '8'
|
||||
[ 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0x06, 0x0C, 0x78, 0x00, 0x00, 0x00, 0x00, ], //0x39, '9'
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, ], //0x3A, ':'
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, ], //0x3B, ';'
|
||||
[ 0x00, 0x00, 0x00, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x00, 0x00, 0x00, 0x00, ], //0x3C, '<'
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ], //0x3D, '='
|
||||
[ 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, ], //0x3E, '>'
|
||||
[ 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0x0C, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, ], //0x3F, '?'
|
||||
[ 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xDE, 0xDE, 0xDE, 0xDC, 0xC0, 0x7C, 0x00, 0x00, 0x00, 0x00, ], //0x40, '@'
|
||||
[ 0x00, 0x00, 0x10, 0x38, 0x6C, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00, ], //0x41, 'A'
|
||||
[ 0x00, 0x00, 0xFC, 0x66, 0x66, 0x66, 0x7C, 0x66, 0x66, 0x66, 0x66, 0xFC, 0x00, 0x00, 0x00, 0x00, ], //0x42, 'B'
|
||||
[ 0x00, 0x00, 0x3C, 0x66, 0xC2, 0xC0, 0xC0, 0xC0, 0xC0, 0xC2, 0x66, 0x3C, 0x00, 0x00, 0x00, 0x00, ], //0x43, 'C'
|
||||
[ 0x00, 0x00, 0xF8, 0x6C, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6C, 0xF8, 0x00, 0x00, 0x00, 0x00, ], //0x44, 'D'
|
||||
[ 0x00, 0x00, 0xFE, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xFE, 0x00, 0x00, 0x00, 0x00, ], //0x45, 'E'
|
||||
[ 0x00, 0x00, 0xFE, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00, ], //0x46, 'F'
|
||||
[ 0x00, 0x00, 0x3C, 0x66, 0xC2, 0xC0, 0xC0, 0xDE, 0xC6, 0xC6, 0x66, 0x3A, 0x00, 0x00, 0x00, 0x00, ], //0x47, 'G'
|
||||
[ 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00, ], //0x48, 'H'
|
||||
[ 0x00, 0x00, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00, ], //0x49, 'I'
|
||||
[ 0x00, 0x00, 0x1E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0xCC, 0xCC, 0xCC, 0x78, 0x00, 0x00, 0x00, 0x00, ], //0x4A, 'J'
|
||||
[ 0x00, 0x00, 0xE6, 0x66, 0x66, 0x6C, 0x78, 0x78, 0x6C, 0x66, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00, ], //0x4B, 'K'
|
||||
[ 0x00, 0x00, 0xF0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x66, 0xFE, 0x00, 0x00, 0x00, 0x00, ], //0x4C, 'L'
|
||||
[ 0x00, 0x00, 0xC6, 0xEE, 0xFE, 0xFE, 0xD6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00, ], //0x4D, 'M'
|
||||
[ 0x00, 0x00, 0xC6, 0xE6, 0xF6, 0xFE, 0xDE, 0xCE, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00, ], //0x4E, 'N'
|
||||
[ 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, ], //0x4F, 'O'
|
||||
[ 0x00, 0x00, 0xFC, 0x66, 0x66, 0x66, 0x7C, 0x60, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00, ], //0x50, 'P'
|
||||
[ 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xD6, 0xDE, 0x7C, 0x0C, 0x0E, 0x00, 0x00, ], //0x51, 'Q'
|
||||
[ 0x00, 0x00, 0xFC, 0x66, 0x66, 0x66, 0x7C, 0x6C, 0x66, 0x66, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00, ], //0x52, 'R'
|
||||
[ 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0x60, 0x38, 0x0C, 0x06, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, ], //0x53, 'S'
|
||||
[ 0x00, 0x00, 0x7E, 0x7E, 0x5A, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00, ], //0x54, 'T'
|
||||
[ 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, ], //0x55, 'U'
|
||||
[ 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x6C, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, ], //0x56, 'V'
|
||||
[ 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xD6, 0xD6, 0xD6, 0xFE, 0xEE, 0x6C, 0x00, 0x00, 0x00, 0x00, ], //0x57, 'W'
|
||||
[ 0x00, 0x00, 0xC6, 0xC6, 0x6C, 0x7C, 0x38, 0x38, 0x7C, 0x6C, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00, ], //0x58, 'X'
|
||||
[ 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00, ], //0x59, 'Y'
|
||||
[ 0x00, 0x00, 0xFE, 0xC6, 0x86, 0x0C, 0x18, 0x30, 0x60, 0xC2, 0xC6, 0xFE, 0x00, 0x00, 0x00, 0x00, ], //0x5A, 'Z'
|
||||
[ 0x00, 0x00, 0x3C, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3C, 0x00, 0x00, 0x00, 0x00, ], //0x5B, '['
|
||||
[ 0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0x70, 0x38, 0x1C, 0x0E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, ], //0x5C, '\'
|
||||
[ 0x00, 0x00, 0x3C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x3C, 0x00, 0x00, 0x00, 0x00, ], //0x5D, ']'
|
||||
[ 0x10, 0x38, 0x6C, 0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ], //0x5E, '^'
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, ], //0x5F, '_'
|
||||
[ 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ], //0x60, '`'
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, ], //0x61, 'a'
|
||||
[ 0x00, 0x00, 0xE0, 0x60, 0x60, 0x78, 0x6C, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x00, 0x00, 0x00, 0x00, ], //0x62, 'b'
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC0, 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, ], //0x63, 'c'
|
||||
[ 0x00, 0x00, 0x1C, 0x0C, 0x0C, 0x3C, 0x6C, 0xCC, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, ], //0x64, 'd'
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xFE, 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, ], //0x65, 'e'
|
||||
[ 0x00, 0x00, 0x38, 0x6C, 0x64, 0x60, 0xF0, 0x60, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00, ], //0x66, 'f'
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x7C, 0x0C, 0xCC, 0x78, 0x00, ], //0x67, 'g'
|
||||
[ 0x00, 0x00, 0xE0, 0x60, 0x60, 0x6C, 0x76, 0x66, 0x66, 0x66, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00, ], //0x68, 'h'
|
||||
[ 0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00, ], //0x69, 'i'
|
||||
[ 0x00, 0x00, 0x06, 0x06, 0x00, 0x0E, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3C, 0x00, ], //0x6A, 'j'
|
||||
[ 0x00, 0x00, 0xE0, 0x60, 0x60, 0x66, 0x6C, 0x78, 0x78, 0x6C, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00, ], //0x6B, 'k'
|
||||
[ 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00, ], //0x6C, 'l'
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0xEC, 0xFE, 0xD6, 0xD6, 0xD6, 0xD6, 0xC6, 0x00, 0x00, 0x00, 0x00, ], //0x6D, 'm'
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, ], //0x6E, 'n'
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, ], //0x6F, 'o'
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x60, 0x60, 0xF0, 0x00, ], //0x70, 'p'
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x7C, 0x0C, 0x0C, 0x1E, 0x00, ], //0x71, 'q'
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x76, 0x66, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00, ], //0x72, 'r'
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0x60, 0x38, 0x0C, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, ], //0x73, 's'
|
||||
[ 0x00, 0x00, 0x10, 0x30, 0x30, 0xFC, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1C, 0x00, 0x00, 0x00, 0x00, ], //0x74, 't'
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, ], //0x75, 'u'
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00, ], //0x76, 'v'
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xD6, 0xD6, 0xD6, 0xFE, 0x6C, 0x00, 0x00, 0x00, 0x00, ], //0x77, 'w'
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0x6C, 0x38, 0x38, 0x38, 0x6C, 0xC6, 0x00, 0x00, 0x00, 0x00, ], //0x78, 'x'
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x0C, 0xF8, 0x00, ], //0x79, 'y'
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xCC, 0x18, 0x30, 0x60, 0xC6, 0xFE, 0x00, 0x00, 0x00, 0x00, ], //0x7A, 'z'
|
||||
[ 0x00, 0x00, 0x0E, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x18, 0x0E, 0x00, 0x00, 0x00, 0x00, ], //0x7B, '['
|
||||
[ 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, ], //0x7C, '|'
|
||||
[ 0x00, 0x00, 0x70, 0x18, 0x18, 0x18, 0x0E, 0x18, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00, ], //0x7D, ']'
|
||||
[ 0x00, 0x00, 0x76, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ], //0x7E, '~'
|
||||
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ], //0x7F, delete
|
||||
];
|
||||
4
kernel/src/kernel/tty/mod.rs
Normal file
4
kernel/src/kernel/tty/mod.rs
Normal file
@ -0,0 +1,4 @@
|
||||
// src/kernel/tty/mod.rs
|
||||
|
||||
pub mod tty;
|
||||
pub mod font;
|
||||
186
kernel/src/kernel/tty/tty.rs
Normal file
186
kernel/src/kernel/tty/tty.rs
Normal file
@ -0,0 +1,186 @@
|
||||
use bootloader_api::info::{FrameBuffer, FrameBufferInfo, PixelFormat};
|
||||
use crate::kernel::tty::font::FONT_BASIC;
|
||||
use core::ptr::{addr_of, addr_of_mut};
|
||||
|
||||
pub struct TTYState {
|
||||
framebuffer: *mut u8,
|
||||
fb_len: usize,
|
||||
info: Option<FrameBufferInfo>,
|
||||
cursor_x: usize,
|
||||
cursor_y: usize,
|
||||
}
|
||||
|
||||
impl TTYState {
|
||||
const fn new() -> Self {
|
||||
Self {
|
||||
framebuffer: core::ptr::null_mut(),
|
||||
fb_len: 0,
|
||||
info: None,
|
||||
cursor_x: 0,
|
||||
cursor_y: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static mut TTY_STATE: TTYState = TTYState::new();
|
||||
|
||||
pub fn init(framebuffer: &'static mut FrameBuffer) {
|
||||
let info = framebuffer.info();
|
||||
let buffer = framebuffer.buffer_mut();
|
||||
|
||||
unsafe {
|
||||
let state = &mut *addr_of_mut!(TTY_STATE);
|
||||
state.framebuffer = buffer.as_mut_ptr();
|
||||
state.fb_len = buffer.len();
|
||||
state.info = Some(info);
|
||||
state.cursor_x = 0;
|
||||
state.cursor_y = 0;
|
||||
}
|
||||
|
||||
clear(0x000000);
|
||||
}
|
||||
|
||||
pub fn clear(color: u32) {
|
||||
unsafe {
|
||||
let state = &*addr_of!(TTY_STATE);
|
||||
|
||||
if state.framebuffer.is_null() {
|
||||
return;
|
||||
}
|
||||
|
||||
let info = match state.info.as_ref() {
|
||||
Some(i) => i,
|
||||
None => return,
|
||||
};
|
||||
|
||||
let (r, g, b) = u32_to_rgb(color);
|
||||
let buffer = core::slice::from_raw_parts_mut(state.framebuffer, state.fb_len);
|
||||
|
||||
for pixel in buffer.chunks_exact_mut(info.bytes_per_pixel) {
|
||||
write_pixel(info, pixel, r, g, b);
|
||||
}
|
||||
|
||||
let state_mut = &mut *addr_of_mut!(TTY_STATE);
|
||||
state_mut.cursor_x = 0;
|
||||
state_mut.cursor_y = 0;
|
||||
}
|
||||
}
|
||||
|
||||
fn write_pixel(info: &FrameBufferInfo, pixel: &mut [u8], r: u8, g: u8, b: u8) {
|
||||
match info.pixel_format {
|
||||
PixelFormat::Rgb => {
|
||||
pixel[0] = r;
|
||||
pixel[1] = g;
|
||||
pixel[2] = b;
|
||||
}
|
||||
PixelFormat::Bgr => {
|
||||
pixel[0] = b;
|
||||
pixel[1] = g;
|
||||
pixel[2] = r;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw_pixel(x: usize, y: usize, color: u32) {
|
||||
unsafe {
|
||||
let state = &*addr_of!(TTY_STATE);
|
||||
|
||||
if state.framebuffer.is_null() {
|
||||
return;
|
||||
}
|
||||
|
||||
let info = match state.info.as_ref() {
|
||||
Some(i) => i,
|
||||
None => return,
|
||||
};
|
||||
|
||||
if x >= info.width || y >= info.height {
|
||||
return;
|
||||
}
|
||||
|
||||
let pixel_offset = (y * info.stride + x) * info.bytes_per_pixel;
|
||||
let (r, g, b) = u32_to_rgb(color);
|
||||
|
||||
let buffer = core::slice::from_raw_parts_mut(state.framebuffer, state.fb_len);
|
||||
|
||||
if let Some(pixel) = buffer.get_mut(pixel_offset..pixel_offset + info.bytes_per_pixel) {
|
||||
write_pixel(info, pixel, r, g, b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw_char(c: char, color: u32) {
|
||||
const CHAR_WIDTH: usize = 8;
|
||||
const CHAR_HEIGHT: usize = 16;
|
||||
|
||||
unsafe {
|
||||
let state = &*addr_of!(TTY_STATE);
|
||||
|
||||
if state.framebuffer.is_null() {
|
||||
return;
|
||||
}
|
||||
|
||||
let info = match state.info.as_ref() {
|
||||
Some(i) => i,
|
||||
None => return,
|
||||
};
|
||||
|
||||
let state_mut = &mut *addr_of_mut!(TTY_STATE);
|
||||
|
||||
if c == '\n' {
|
||||
state_mut.cursor_x = 0;
|
||||
state_mut.cursor_y += CHAR_HEIGHT;
|
||||
return;
|
||||
}
|
||||
|
||||
if state_mut.cursor_x + CHAR_WIDTH > info.width {
|
||||
state_mut.cursor_x = 0;
|
||||
state_mut.cursor_y += CHAR_HEIGHT;
|
||||
}
|
||||
|
||||
if state_mut.cursor_y + CHAR_HEIGHT > info.height {
|
||||
state_mut.cursor_y = 0;
|
||||
}
|
||||
|
||||
let idx = c as usize;
|
||||
if idx >= FONT_BASIC.len() {
|
||||
return;
|
||||
}
|
||||
let glyph = &FONT_BASIC[idx];
|
||||
|
||||
let cursor_x = state_mut.cursor_x;
|
||||
let cursor_y = state_mut.cursor_y;
|
||||
|
||||
for (y, row) in glyph.iter().enumerate() {
|
||||
for x in 0..8 {
|
||||
if (row >> (7 - x)) & 1 == 1 {
|
||||
draw_pixel(cursor_x + x, cursor_y + y, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
state_mut.cursor_x += CHAR_WIDTH;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_str(s: &str, color: u32) {
|
||||
for c in s.chars() {
|
||||
draw_char(c, color);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn tty_put_str(s: &str, color: Option<u32>) {
|
||||
if let Some(c) = color {
|
||||
write_str(s, c);
|
||||
} else {
|
||||
write_str(s, 0xFFFFFF);
|
||||
}
|
||||
}
|
||||
|
||||
fn u32_to_rgb(color: u32) -> (u8, u8, u8) {
|
||||
let r = ((color >> 16) & 0xFF) as u8;
|
||||
let g = ((color >> 8) & 0xFF) as u8;
|
||||
let b = (color & 0xFF) as u8;
|
||||
(r, g, b)
|
||||
}
|
||||
1
kernel/src/libs/libc/mod.rs
Normal file
1
kernel/src/libs/libc/mod.rs
Normal file
@ -0,0 +1 @@
|
||||
pub mod print;
|
||||
33
kernel/src/libs/libc/print.rs
Normal file
33
kernel/src/libs/libc/print.rs
Normal file
@ -0,0 +1,33 @@
|
||||
// src/libs/libc/print.rs
|
||||
|
||||
use core::fmt;
|
||||
use crate::kernel::tty::tty;
|
||||
|
||||
pub struct Writer;
|
||||
|
||||
impl fmt::Write for Writer {
|
||||
fn write_str(&mut self, s: &str) -> fmt::Result {
|
||||
tty::tty_put_str(s, None);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn _print(args: fmt::Arguments) {
|
||||
use core::fmt::Write;
|
||||
Writer.write_fmt(args).unwrap();
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! print {
|
||||
($($arg:tt)*) => ($crate::libs::libc::print::_print(format_args!($($arg)*)));
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! kprintln {
|
||||
() => {
|
||||
$crate::libs::libc::print::_print(format_args!("\n"))
|
||||
};
|
||||
($($arg:tt)*) => {
|
||||
$crate::libs::libc::print::_print(format_args!("{}\n", format_args!($($arg)*)))
|
||||
};
|
||||
}
|
||||
1
kernel/src/libs/mod.rs
Normal file
1
kernel/src/libs/mod.rs
Normal file
@ -0,0 +1 @@
|
||||
pub mod libc;
|
||||
55
kernel/src/main.rs
Normal file
55
kernel/src/main.rs
Normal file
@ -0,0 +1,55 @@
|
||||
// kernel/src/main.rs
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
#![feature(abi_x86_interrupt)]
|
||||
|
||||
use core::panic::PanicInfo;
|
||||
use bootloader_api::{entry_point, BootInfo};
|
||||
|
||||
mod kernel;
|
||||
mod hal;
|
||||
mod libs;
|
||||
|
||||
use kernel::tty::tty;
|
||||
use kernel::asm::x86::gdt;
|
||||
|
||||
|
||||
entry_point!(kernel_main);
|
||||
|
||||
fn kernel_main(boot_info: &'static mut BootInfo) -> ! {
|
||||
if let Some(framebuffer) = boot_info.framebuffer.as_mut() {
|
||||
tty::init(framebuffer);
|
||||
tty::clear(0x000000);
|
||||
|
||||
kprintln!("CureOS Booting...");
|
||||
kprintln!("Framebuffer initialized");
|
||||
kprintln!("Welcome to CureOS!");
|
||||
|
||||
kprintln!("initialize GDT");
|
||||
gdt::init();
|
||||
kprintln!("GDT initialized");
|
||||
|
||||
} else {
|
||||
loop {
|
||||
hal::cpu::cpu_halt();
|
||||
}
|
||||
}
|
||||
|
||||
loop {
|
||||
hal::cpu::cpu_halt();
|
||||
}
|
||||
}
|
||||
#[cfg(not(test))]
|
||||
#[panic_handler]
|
||||
fn panic(info: &PanicInfo) -> ! {
|
||||
kprintln!();
|
||||
kprintln!("================================");
|
||||
kprintln!(" KERNEL PANIC!" );
|
||||
kprintln!("================================");
|
||||
kprintln!();
|
||||
kprintln!("{}", info);
|
||||
|
||||
loop {
|
||||
hal::cpu::cpu_halt();
|
||||
}
|
||||
}
|
||||
6
old/GRUB_TEMPLATE
Normal file
6
old/GRUB_TEMPLATE
Normal file
@ -0,0 +1,6 @@
|
||||
default=0
|
||||
timeout=3
|
||||
|
||||
menuentry "$_OS_NAME" {
|
||||
multiboot /boot/$_OS_NAME.bin
|
||||
}
|
||||
5
old/config-grub.sh
Normal file
5
old/config-grub.sh
Normal file
@ -0,0 +1,5 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
export _OS_NAME=$1
|
||||
|
||||
cat GRUB_TEMPLATE | envsubst > "$2"
|
||||
23
old/linker.ld
Normal file
23
old/linker.ld
Normal file
@ -0,0 +1,23 @@
|
||||
ENTRY(start_)
|
||||
|
||||
SECTIONS {
|
||||
. = 0x100000;
|
||||
|
||||
.text BLOCK(4K): {
|
||||
* (.multiboot) /* boot.o (.multiboot) */
|
||||
* (.text)
|
||||
}
|
||||
|
||||
.bss BLOCK(4K): {
|
||||
* (COMMON)
|
||||
* (.bss)
|
||||
}
|
||||
|
||||
.data BLOCK(4K): {
|
||||
* (.data)
|
||||
}
|
||||
|
||||
.rodata BLOCK(4k): {
|
||||
* (.rodata)
|
||||
}
|
||||
}
|
||||
98
old/makefile
Normal file
98
old/makefile
Normal file
@ -0,0 +1,98 @@
|
||||
include config/make-locations
|
||||
include config/make-os
|
||||
include config/make-debug-tool
|
||||
|
||||
BUILD_MODE := release
|
||||
CARGO_FLAGS := --release
|
||||
|
||||
# Rust target for bootloader
|
||||
RUST_TARGET := x86_64-unknown-none
|
||||
|
||||
.PHONY: all all-debug clean run debug-qemu debug-bochs rust-kernel
|
||||
|
||||
$(BUILD_DIR):
|
||||
@mkdir -p $(BUILD_DIR)
|
||||
|
||||
$(BIN_DIR):
|
||||
@mkdir -p $(BIN_DIR)
|
||||
|
||||
$(ISO_DIR):
|
||||
@mkdir -p $(ISO_DIR)
|
||||
@mkdir -p $(ISO_BOOT_DIR)
|
||||
@mkdir -p $(ISO_GRUB_DIR)
|
||||
|
||||
# 構建 Rust kernel + bootloader,提取 bin 文件
|
||||
rust-kernel: $(BUILD_DIR) $(BIN_DIR)
|
||||
@echo "Building Rust kernel with bootloader..."
|
||||
@cargo build -p cure-builder $(CARGO_FLAGS)
|
||||
@echo "Finding kernel binary..."
|
||||
@KERNEL_BIN=$$(find target/$(RUST_TARGET)/$(BUILD_MODE) -name "cure-kernel" -type f | head -1); \
|
||||
if [ -z "$$KERNEL_BIN" ]; then \
|
||||
echo "Error: Kernel binary not found!"; \
|
||||
exit 1; \
|
||||
fi; \
|
||||
echo "Copying kernel binary to $(BIN_DIR)/$(OS_BIN)"; \
|
||||
cp "$$KERNEL_BIN" $(BIN_DIR)/$(OS_BIN)
|
||||
|
||||
# 創建 ISO(使用 GRUB Multiboot2)
|
||||
$(BUILD_DIR)/$(OS_ISO): $(ISO_DIR) rust-kernel
|
||||
@echo "Creating ISO image..."
|
||||
@./config-grub.sh $(OS_NAME) $(ISO_GRUB_DIR)/grub.cfg
|
||||
@cp $(BIN_DIR)/$(OS_BIN) $(ISO_BOOT_DIR)/$(OS_BIN)
|
||||
@echo "Running grub-mkrescue..."
|
||||
@grub-mkrescue -o $(BUILD_DIR)/$(OS_ISO) $(ISO_DIR) 2>&1 || \
|
||||
(echo "Error: grub-mkrescue failed. Installing grub-pc-bin..."; \
|
||||
sudo apt install -y grub-pc-bin xorriso mtools && \
|
||||
grub-mkrescue -o $(BUILD_DIR)/$(OS_ISO) $(ISO_DIR))
|
||||
@echo "ISO created at $(BUILD_DIR)/$(OS_ISO)"
|
||||
|
||||
all: $(BUILD_DIR)/$(OS_ISO)
|
||||
|
||||
all-debug: BUILD_MODE := debug
|
||||
all-debug: CARGO_FLAGS :=
|
||||
all-debug: $(BUILD_DIR)/$(OS_ISO)
|
||||
@echo "Debug build completed"
|
||||
|
||||
clean:
|
||||
@rm -rf $(BUILD_DIR)
|
||||
@cargo clean
|
||||
@echo "Cleaned build artifacts"
|
||||
|
||||
# 使用 QEMU 運行 ISO
|
||||
run: $(BUILD_DIR)/$(OS_ISO)
|
||||
@echo "Running $(OS_ISO) with QEMU..."
|
||||
@qemu-system-x86_64 -cdrom $(BUILD_DIR)/$(OS_ISO) -m 512M -serial stdio
|
||||
|
||||
# 使用 Bochs 運行 ISO
|
||||
run-bochs: $(BUILD_DIR)/$(OS_ISO)
|
||||
@echo "Running ISO with Bochs..."
|
||||
@bochs -q -f bochs.cfg
|
||||
|
||||
# QEMU 調試模式
|
||||
debug-qemu: all-debug
|
||||
@echo "Starting QEMU in debug mode..."
|
||||
@qemu-system-x86_64 -cdrom $(BUILD_DIR)/$(OS_ISO) -m 512M \
|
||||
-serial stdio -s -S &
|
||||
@sleep 1
|
||||
@echo "QEMU waiting for GDB connection on localhost:1234"
|
||||
@echo "Run: gdb target/$(RUST_TARGET)/debug/cure-kernel"
|
||||
@echo "Then: (gdb) target remote localhost:1234"
|
||||
|
||||
# Bochs 調試模式
|
||||
debug-bochs: all-debug
|
||||
@echo "Running Bochs in debug mode..."
|
||||
@bochs -q -f bochs.cfg
|
||||
|
||||
# 幫助信息
|
||||
help:
|
||||
@echo "CureOS Build System"
|
||||
@echo ""
|
||||
@echo "Targets:"
|
||||
@echo " all - Build ISO image (release mode)"
|
||||
@echo " all-debug - Build ISO image (debug mode)"
|
||||
@echo " clean - Clean all build artifacts"
|
||||
@echo " run - Build and run ISO with QEMU"
|
||||
@echo " run-bochs - Build and run ISO with Bochs"
|
||||
@echo " debug-qemu - Run QEMU in debug mode"
|
||||
@echo " debug-bochs - Run Bochs in debug mode"
|
||||
@echo " help - Show this help message"
|
||||
Loading…
x
Reference in New Issue
Block a user