diff --git a/Makefile b/Makefile
index 653577f..11f06a7 100644
--- a/Makefile
+++ b/Makefile
@@ -4,9 +4,12 @@ ISO_PARTITION_TYPE ?= GPT
MODE ?= release
ARCH ?= x86_64
MEMORY ?= 512M
+# In MB
+ISO_SIZE ?= 256
QEMU_OPTS ?=
MKSQUASHFS_OPTS ?=
GDB ?=
+ESP_BITS ?= 16
ISO_PATH = ${ARTIFACTS_PATH}/iso_root
INITRAMFS_PATH = ${ARTIFACTS_PATH}/initramfs
@@ -62,6 +65,7 @@ prepare-bin-files:
mkdir -p ${ARTIFACTS_PATH}
mkdir -p ${ISO_PATH}
mkdir -p ${INITRAMFS_PATH}
+ mkdir -p ${ARTIFACTS_PATH}/mnt
copy-initramfs-files:
echo "Hello World from Initramfs" > ${INITRAMFS_PATH}/example.txt
@@ -87,6 +91,8 @@ run-scripts:
python scripts/font.py
mv scripts/font.psf ${INITRAMFS_PATH}/
+ # python scripts/initramfs-test.py 1000 ${INITRAMFS_PATH}/
+
copy-iso-files:
# Limine files
mkdir -p ${ISO_PATH}/boot/limine
@@ -109,35 +115,40 @@ copy-iso-files:
partition-iso: copy-iso-files
# Make empty ISO of 64M in size
- dd if=/dev/zero of=${IMAGE_PATH} bs=1M count=0 seek=64
+ dd if=/dev/zero of=${IMAGE_PATH} bs=1M count=0 seek=${ISO_SIZE}
ifeq (${ISO_PARTITION_TYPE},GPT)
- # Make ISO a GPT disk with 1 partition starting at sector 2048 that is 32768 sectors, or 16MiB, in size
- # Then a second partition spanning the rest of the disk
- sgdisk ${IMAGE_PATH} -n 1:2048:+32768 -t 1:ef00 -n 2
+ parted -s ${IMAGE_PATH} mklabel gpt
+ parted -s ${IMAGE_PATH} mkpart ESP fat${ESP_BITS} 2048s 34815s
+
else
- # Make ISO a MBR disk with 1 partition starting at sector 2048 that is 32768 sectors, or 16MiB, in size
- # Then a second partition spanning the rest of the disk
- parted -a none ${IMAGE_PATH} mklabel msdos
- parted -a none ${IMAGE_PATH} mkpart primary 2048s 34815s
- parted -a none ${IMAGE_PATH} mkpart primary 34816s 100%
- parted -a none ${IMAGE_PATH} set 1 boot on
+ parted -s ${IMAGE_PATH} mklabel msdos
+ parted -s ${IMAGE_PATH} mkpart primary fat${ESP_BITS} 2048s 34815s
endif
+ # Make ISO with 1 partition starting at sector 2048 that is 32768 sectors, or 16MiB, in size
+ # Then a second partition spanning the rest of the disk
+ parted -s ${IMAGE_PATH} mkpart primary 34816s 100%
+ parted -s ${IMAGE_PATH} set 1 esp on
+
build-iso: partition-iso copy-initramfs-files
ifeq (${ARCH},x86_64)
# Install the Limine bootloader for bios installs
./limine/limine bios-install ${IMAGE_PATH}
endif
- # Make a FAT32 FS and copy files in /bin/iso_root into the ISO starting at 1M or exactly 2048 sectors
- mformat -F -i ${IMAGE_PATH}@@1M
- mmd -i ${IMAGE_PATH}@@1M ::/EFI ::/EFI/BOOT
- mcopy -i ${IMAGE_PATH}@@1M -s ${ISO_PATH}/* ::/
+ sudo losetup -Pf --show ${IMAGE_PATH} > loopback_dev
+ sudo mkfs.fat -F ${ESP_BITS} `cat loopback_dev`p1
+ sudo mount `cat loopback_dev`p1 ${ARTIFACTS_PATH}/mnt
+ sudo cp -r ${ISO_PATH}/* ${ARTIFACTS_PATH}/mnt
+ sync
+ sudo umount ${ARTIFACTS_PATH}/mnt
+ sudo losetup -d `cat loopback_dev`
+ rm -rf loopback_dev
compile-bootloader:
@if [ ! -d "limine" ]; then \
echo "Cloning Limine into limine/..."; \
- git clone https://github.com/limine-bootloader/limine.git --branch=v5.x-branch-binary --depth=1; \
+ git clone https://github.com/limine-bootloader/limine.git --branch=v6.x-branch-binary --depth=1; \
else \
echo "Folder limine already exists. Skipping clone."; \
fi
@@ -182,5 +193,5 @@ line-count:
cloc --quiet --exclude-dir=bin --csv src/ | tail -n 1 | awk -F, '{print $$5}'
clean:
cargo clean
- rm -rf bin
+ rm -rf ${ARTIFACTS_PATH}
make clean -C limine
\ No newline at end of file
diff --git a/README.md b/README.md
index 087cf3f..e2247be 100644
--- a/README.md
+++ b/README.md
@@ -23,11 +23,13 @@ CappuccinOS is a small x86-64 operating system written from scratch in rust. Thi
- [ ] x86 CPU support
- [ ] armv8 CPU support
- [ ] File system
- - [ ] Block Device support
- - [X] IDE device support
- - [ ] SATA device support
- - [ ] MMC/Nand device support
- - [ ] M.2 NVME device support
+ - [X] FAT file system (read-only rn)
+ - [ ] Ext2 file system
+- [ ] Block Device support
+ - [X] IDE device support
+ - [ ] SATA device support
+ - [ ] MMC/Nand device support
+ - [ ] M.2 NVME device support
- [ ] Basic shell
- [X] Basic I/O
- [ ] Executing Programs from disk
@@ -112,10 +114,11 @@ Some Resources I used over the creation of CappuccinOS:
- Wikipedia on various random things
- [Squashfs Binary Format](https://dr-emann.github.io/squashfs/squashfs.html)
-And mostly for examples of how people did stuff I used these (projects made by people who actually have a clue what they're doing):
+And mostly for examples of how people did stuff I used these (projects made by people who might actually have a clue what they're doing):
- [MOROS](https://github.com/vinc/moros)
- [Felix](https://github.com/mrgian/felix)
- [mOS](https://github.com/Moldytzu/mOS)
+- [rust_os](https://github.com/thepowersgang/rust_os/tree/master)
## License
CappuccinOS is license under the MIT License. Feel free to modify and distribute in accordance with the license.
\ No newline at end of file
diff --git a/scripts/README.md b/scripts/README.md
index 4aac067..a7f873a 100644
--- a/scripts/README.md
+++ b/scripts/README.md
@@ -2,4 +2,10 @@
This folder is responsible for holding all the scripts that are necessary for building CappuccinOS
- **demangle-symbols.py**
- This file takes in a symbols file generated by the `nm` program and outputs a symbol file with the symbol names demangled, it uses my library, [rustc_demangle.py](https://github.com/juls0730/rustc_demangle.py) which is a python port of the Rust symbol demangling library [rustc-demangle](https://github.com/rust-lang/rustc-demangle).
\ No newline at end of file
+ This file takes in a symbols file generated by the `nm` program and outputs a symbol file with the symbol names demangled, it uses my library, [rustc_demangle.py](https://github.com/juls0730/rustc_demangle.py) which is a python port of the Rust symbol demangling library [rustc-demangle](https://github.com/rust-lang/rustc-demangle).
+
+- **font.py**
+ This file takes an array of u8 numbers and exports a PC Screen Font file (2.0)
+
+- **initramfs-test.py**
+ This file generates tons of files in the initramfs directory from huge to small files nested in directories, etc. It's intended to test the squashfs driver
\ No newline at end of file
diff --git a/scripts/font.py b/scripts/font.py
index 5aabc28..afe7519 100644
--- a/scripts/font.py
+++ b/scripts/font.py
@@ -20,7 +20,264 @@ def create_psf2_file(font_data, psf2_file_path):
psf2_file.write(psf2_file_content)
if __name__ == "__main__":
- font_data = [[0x00, 0x00, 0x7E, 0x81, 0x99, 0xA5, 0x85, 0x89, 0x89, 0x81, 0x89, 0x7E, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x7E, 0x81, 0xA5, 0x81, 0x81, 0xBD, 0x99, 0x81, 0x81, 0x7E, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x7E, 0xFF, 0xDB, 0xFF, 0xFF, 0xC3, 0xE7, 0xFF, 0xFF, 0x7E, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x00, 0x6C, 0xFE, 0xFE, 0xFE, 0xFE, 0x7C, 0x38, 0x10, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7C, 0xFE, 0x7C, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x18, 0x3C, 0x3C, 0xE7, 0xE7, 0xE7, 0x99, 0x18, 0x3C, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x18, 0x3C, 0x7E, 0xFF, 0xFF, 0x7E, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3C, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,0x00],[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0xC3, 0xC3, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF],[0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x66, 0x42, 0x42, 0x66, 0x3C, 0x00, 0x00, 0x00, 0x00,0x00],[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC3, 0x99, 0xBD, 0xBD, 0x99, 0xC3, 0xFF, 0xFF, 0xFF, 0xFF,0xFF],[0x00, 0x00, 0x1E, 0x0E, 0x1A, 0x32, 0x78, 0xCC, 0xCC, 0xCC, 0xCC, 0x78, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x3C, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x3F, 0x33, 0x3F, 0x30, 0x30, 0x30, 0x30, 0x70, 0xF0, 0xE0, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x7F, 0x63, 0x7F, 0x63, 0x63, 0x63, 0x63, 0x67, 0xE7, 0xE6, 0xC0, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x18, 0x18, 0xDB, 0x3C, 0xE7, 0x3C, 0xDB, 0x18, 0x18, 0x00, 0x00, 0x00,0x00],[0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFE, 0xF8, 0xF0, 0xE0, 0xC0, 0x80, 0x00, 0x00, 0x00,0x00],[0x00, 0x02, 0x06, 0x0E, 0x1E, 0x3E, 0xFE, 0x3E, 0x1E, 0x0E, 0x06, 0x02, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x7F, 0xDB, 0xDB, 0xDB, 0x7B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x00, 0x00, 0x00,0x00],[0x00, 0x7C, 0xC6, 0x60, 0x38, 0x6C, 0xC6, 0xC6, 0x6C, 0x38, 0x0C, 0xC6, 0x7C, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0xFE, 0xFE, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x7E, 0x00, 0x00,0x00],[0x00, 0x00, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0C, 0xFE, 0x0C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xFE, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xC0, 0xC0, 0xC0, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x6C, 0xFE, 0x6C, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7C, 0x7C, 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0x7C, 0x7C, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x18, 0x3C, 0x3C, 0x3C, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00,0x00],[0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x6C, 0x6C, 0xFE, 0x6C, 0x6C, 0x6C, 0xFE, 0x6C, 0x6C, 0x00, 0x00, 0x00,0x00],[0x18, 0x18, 0x7C, 0xC6, 0xC2, 0xC0, 0x7C, 0x06, 0x86, 0xC6, 0x7C, 0x18, 0x18, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x00, 0xC2, 0xC6, 0x0C, 0x18, 0x30, 0x60, 0xC6, 0x86, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x38, 0x6C, 0x6C, 0x38, 0x76, 0xDC, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00,0x00],[0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x0C, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0C, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x18, 0x30, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0x80, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xCE, 0xD6, 0xD6, 0xE6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x7C, 0xC6, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0xC6, 0xFE, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x7C, 0xC6, 0x06, 0x06, 0x3C, 0x06, 0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x0C, 0x1C, 0x3C, 0x6C, 0xCC, 0xFE, 0x0C, 0x0C, 0x0C, 0x1E, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0xFE, 0xC0, 0xC0, 0xC0, 0xFC, 0x0E, 0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x38, 0x60, 0xC0, 0xC0, 0xFC, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0xFE, 0xC6, 0x06, 0x06, 0x0C, 0x18, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0x06, 0x0C, 0x78, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x7C, 0xC6, 0xC6, 0x0C, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xDE, 0xDE, 0xDE, 0xDC, 0xC0, 0x7C, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x10, 0x38, 0x6C, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0xFC, 0x66, 0x66, 0x66, 0x7C, 0x66, 0x66, 0x66, 0x66, 0xFC, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x3C, 0x66, 0xC2, 0xC0, 0xC0, 0xC0, 0xC0, 0xC2, 0x66, 0x3C, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0xF8, 0x6C, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6C, 0xF8, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0xFE, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xFE, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0xFE, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x3C, 0x66, 0xC2, 0xC0, 0xC0, 0xDE, 0xC6, 0xC6, 0x66, 0x3A, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x1E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0xCC, 0xCC, 0xCC, 0x78, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0xE6, 0x66, 0x6C, 0x6C, 0x78, 0x78, 0x6C, 0x66, 0x66, 0xE6, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0xF0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x66, 0xFE, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0xC6, 0xEE, 0xFE, 0xFE, 0xD6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0xC6, 0xE6, 0xF6, 0xFE, 0xDE, 0xCE, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x38, 0x6C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x6C, 0x38, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0xFC, 0x66, 0x66, 0x66, 0x7C, 0x60, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xD6, 0xDE, 0x7C, 0x0C, 0x0E, 0x00,0x00],[0x00, 0x00, 0xFC, 0x66, 0x66, 0x66, 0x7C, 0x6C, 0x66, 0x66, 0x66, 0xE6, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x7C, 0xC6, 0xC6, 0x60, 0x38, 0x0C, 0x06, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x7E, 0x7E, 0x5A, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x6C, 0x38, 0x10, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xD6, 0xD6, 0xFE, 0x6C, 0x6C, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0xC6, 0xC6, 0x6C, 0x6C, 0x38, 0x38, 0x6C, 0x6C, 0xC6, 0xC6, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0xFE, 0xC6, 0x86, 0x0C, 0x18, 0x30, 0x60, 0xC2, 0xC6, 0xFE, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x3C, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3C, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0x70, 0x38, 0x1C, 0x0E, 0x06, 0x02, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x3C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x3C, 0x00, 0x00, 0x00,0x00],[0x10, 0x38, 0x6C, 0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00,0x00],[0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0xE0, 0x60, 0x60, 0x78, 0x6C, 0x66, 0x66, 0x66, 0x66, 0xDC, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC0, 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x1C, 0x0C, 0x0C, 0x3C, 0x6C, 0xCC, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xFE, 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x38, 0x6C, 0x64, 0x60, 0xF0, 0x60, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x7C, 0x0C, 0xCC, 0x78,0x00],[0x00, 0x00, 0xE0, 0x60, 0x60, 0x6C, 0x76, 0x66, 0x66, 0x66, 0x66, 0xE6, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x06, 0x06, 0x00, 0x0E, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3C,0x00],[0x00, 0x00, 0xE0, 0x60, 0x60, 0x66, 0x6C, 0x78, 0x78, 0x6C, 0x66, 0xE6, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x00, 0x00, 0xEC, 0xFE, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x60, 0x60, 0xF0,0x00],[0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x7C, 0x0C, 0x0C, 0x1E,0x00],[0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x76, 0x62, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0x60, 0x38, 0x0C, 0xC6, 0x7C, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x10, 0x30, 0x30, 0xFC, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1C, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xD6, 0xD6, 0xFE, 0x6C, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0x6C, 0x38, 0x38, 0x38, 0x6C, 0xC6, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x0C, 0xF8,0x00],[0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xCC, 0x18, 0x30, 0x60, 0xC6, 0xFE, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x0E, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x18, 0x0E, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x70, 0x18, 0x18, 0x18, 0x0E, 0x18, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x76, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6C, 0xC6, 0xC6, 0xC6, 0xFE, 0x00, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x3C, 0x66, 0xC2, 0xC0, 0xC0, 0xC0, 0xC2, 0x66, 0x3C, 0x0C, 0x06, 0x7C, 0x00,0x00],[0x00, 0x00, 0xCC, 0xCC, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00,0x00],[0x00, 0x0C, 0x18, 0x30, 0x00, 0x7C, 0xC6, 0xFE, 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00,0x00],[0x00, 0x10, 0x38, 0x6C, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0xCC, 0xCC, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00,0x00],[0x00, 0x60, 0x30, 0x18, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00,0x00],[0x00, 0x38, 0x6C, 0x38, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x00, 0x3C, 0x66, 0x60, 0x60, 0x66, 0x3C, 0x0C, 0x06, 0x3C, 0x00, 0x00,0x00],[0x00, 0x10, 0x38, 0x6C, 0x00, 0x7C, 0xC6, 0xFE, 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0xC6, 0xC6, 0x00, 0x7C, 0xC6, 0xFE, 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00,0x00],[0x00, 0x60, 0x30, 0x18, 0x00, 0x7C, 0xC6, 0xFE, 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x66, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00,0x00],[0x00, 0x18, 0x3C, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00,0x00],[0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00,0x00],[0x00, 0xC6, 0xC6, 0x10, 0x38, 0x6C, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00,0x00],[0x38, 0x6C, 0x38, 0x00, 0x38, 0x6C, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00,0x00],[0x18, 0x30, 0x60, 0x00, 0xFE, 0x66, 0x60, 0x7C, 0x60, 0x60, 0x66, 0xFE, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x00, 0x00, 0xCC, 0x76, 0x36, 0x7E, 0xD8, 0xD8, 0x6E, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x3E, 0x6C, 0xCC, 0xCC, 0xFE, 0xCC, 0xCC, 0xCC, 0xCC, 0xCE, 0x00, 0x00, 0x00,0x00],[0x00, 0x10, 0x38, 0x6C, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0xC6, 0xC6, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00,0x00],[0x00, 0x60, 0x30, 0x18, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00,0x00],[0x00, 0x30, 0x78, 0xCC, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00,0x00],[0x00, 0x60, 0x30, 0x18, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0xC6, 0xC6, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x0C, 0x78,0x00],[0x00, 0xC6, 0xC6, 0x00, 0x38, 0x6C, 0xC6, 0xC6, 0xC6, 0xC6, 0x6C, 0x38, 0x00, 0x00, 0x00,0x00],[0x00, 0xC6, 0xC6, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00,0x00],[0x00, 0x18, 0x18, 0x3C, 0x66, 0x60, 0x60, 0x60, 0x66, 0x3C, 0x18, 0x18, 0x00, 0x00, 0x00,0x00],[0x00, 0x38, 0x6C, 0x64, 0x60, 0xF0, 0x60, 0x60, 0x60, 0x60, 0xE6, 0xFC, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x66, 0x66, 0x3C, 0x18, 0x7E, 0x18, 0x7E, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00,0x00],[0x00, 0xF8, 0xCC, 0xCC, 0xF8, 0xC4, 0xCC, 0xDE, 0xCC, 0xCC, 0xCC, 0xC6, 0x00, 0x00, 0x00,0x00],[0x00, 0x0E, 0x1B, 0x18, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, 0xD8, 0x70, 0x00,0x00],[0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00,0x00],[0x00, 0x0C, 0x18, 0x30, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00,0x00],[0x00, 0x18, 0x30, 0x60, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00,0x00],[0x00, 0x18, 0x30, 0x60, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x76, 0xDC, 0x00, 0xDC, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00,0x00],[0x76, 0xDC, 0x00, 0xC6, 0xE6, 0xF6, 0xFE, 0xDE, 0xCE, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00,0x00],[0x00, 0x3C, 0x6C, 0x6C, 0x3E, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00],[0x00, 0x38, 0x6C, 0x6C, 0x38, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, 0xC0, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00,0x00],[0x00, 0xC0, 0xC0, 0xC2, 0xC6, 0xCC, 0x18, 0x30, 0x60, 0xCE, 0x93, 0x06, 0x0C, 0x1F, 0x00,0x00],[0x00, 0xC0, 0xC0, 0xC2, 0xC6, 0xCC, 0x18, 0x30, 0x66, 0xCE, 0x9A, 0x3F, 0x06, 0x0F, 0x00,0x00],[0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x3C, 0x3C, 0x3C, 0x18, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x66, 0xCC, 0x66, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x00, 0x00, 0xCC, 0x66, 0x33, 0x66, 0xCC, 0x00, 0x00, 0x00, 0x00, 0x00,0x00],[0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11,0x44],[0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55,0xAA],[0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD,0x77],[0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,0x18],[0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xF8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,0x18],[0x18, 0x18, 0x18, 0x18, 0x18, 0xF8, 0x18, 0xF8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,0x18],[0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xF6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,0x36],[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,0x36],[0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x18, 0xF8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,0x18],[0x36, 0x36, 0x36, 0x36, 0x36, 0xF6, 0x06, 0xF6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,0x36],[0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,0x36],[0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x06, 0xF6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,0x36],[0x36, 0x36, 0x36, 0x36, 0x36, 0xF6, 0x06, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00],[0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00],[0x18, 0x18, 0x18, 0x18, 0x18, 0xF8, 0x18, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,0x18],[0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00],[0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,0x18],[0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,0x18],[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00],[0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,0x18],[0x18, 0x18, 0x18, 0x18, 0x18, 0x1F, 0x18, 0x1F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,0x18],[0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,0x36],[0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,0x36],[0x36, 0x36, 0x36, 0x36, 0x36, 0xF7, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xF7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,0x36],[0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,0x36],[0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00],[0x36, 0x36, 0x36, 0x36, 0x36, 0xF7, 0x00, 0xF7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,0x36],[0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00],[0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,0x18],[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,0x36],[0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00],[0x18, 0x18, 0x18, 0x18, 0x18, 0x1F, 0x18, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x18, 0x1F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,0x18],[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,0x36],[0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xFF, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,0x36],[0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0x18, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,0x18],[0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,0x18],[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF],[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF],[0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,0xF0],[0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,0x0F],[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xDC, 0xD8, 0xD8, 0xD8, 0xDC, 0x76, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xC6, 0xFC, 0xC6, 0xC6, 0xFC, 0xC0, 0xC0, 0xC0, 0x00,0x00],[0x00, 0x00, 0xFE, 0xC6, 0xC6, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x00, 0x80, 0xFE, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0xFE, 0xC6, 0x60, 0x30, 0x18, 0x30, 0x60, 0xC6, 0xFE, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0x70, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x60, 0x60, 0xC0, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x00, 0x76, 0xDC, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x7E, 0x18, 0x3C, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x7E, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x38, 0x6C, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0x6C, 0x38, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x38, 0x6C, 0xC6, 0xC6, 0xC6, 0x6C, 0x6C, 0x6C, 0x6C, 0xEE, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x1E, 0x30, 0x18, 0x0C, 0x3E, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0xDB, 0xDB, 0xDB, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x03, 0x06, 0x7E, 0xCF, 0xDB, 0xF3, 0x7E, 0x60, 0xC0, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x1C, 0x30, 0x60, 0x60, 0x7C, 0x60, 0x60, 0x60, 0x30, 0x1C, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x30, 0x18, 0x0C, 0x06, 0x0C, 0x18, 0x30, 0x00, 0x7E, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x0C, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0C, 0x00, 0x7E, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x0E, 0x1B, 0x1B, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,0x18],[0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xD8, 0xD8, 0xD8, 0x70, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7E, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xDC, 0x00, 0x76, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00,0x00],[0x00, 0x38, 0x6C, 0x6C, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00],[0x00, 0x0F, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0xEC, 0x6C, 0x6C, 0x3C, 0x1C, 0x00, 0x00, 0x00,0x00],[0x00, 0xD8, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00],[0x00, 0x70, 0x98, 0x30, 0x60, 0xC8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x00, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C, 0x00, 0x00, 0x00, 0x00,0x00],[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00]]
+ font_data = [
+ [0x00, 0x00, 0x7E, 0x81, 0x99, 0xA5, 0x85, 0x89, 0x89, 0x81, 0x89, 0x7E, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x7E, 0x81, 0xA5, 0x81, 0x81, 0xBD, 0x99, 0x81, 0x81, 0x7E, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x7E, 0xFF, 0xDB, 0xFF, 0xFF, 0xC3, 0xE7, 0xFF, 0xFF, 0x7E, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0x6C, 0xFE, 0xFE, 0xFE, 0xFE, 0x7C, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7C, 0xFE, 0x7C, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x18, 0x3C, 0x3C, 0xE7, 0xE7, 0xE7, 0x99, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x18, 0x3C, 0x7E, 0xFF, 0xFF, 0x7E, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3C, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
+ [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0xC3, 0xC3, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF],
+ [0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x66, 0x42, 0x42, 0x66, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00],
+ [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC3, 0x99, 0xBD, 0xBD, 0x99, 0xC3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF],
+ [0x00, 0x00, 0x1E, 0x0E, 0x1A, 0x32, 0x78, 0xCC, 0xCC, 0xCC, 0xCC, 0x78, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x3C, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x3F, 0x33, 0x3F, 0x30, 0x30, 0x30, 0x30, 0x70, 0xF0, 0xE0, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x7F, 0x63, 0x7F, 0x63, 0x63, 0x63, 0x63, 0x67, 0xE7, 0xE6, 0xC0, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x18, 0x18, 0xDB, 0x3C, 0xE7, 0x3C, 0xDB, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFE, 0xF8, 0xF0, 0xE0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x02, 0x06, 0x0E, 0x1E, 0x3E, 0xFE, 0x3E, 0x1E, 0x0E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x7F, 0xDB, 0xDB, 0xDB, 0x7B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x7C, 0xC6, 0x60, 0x38, 0x6C, 0xC6, 0xC6, 0x6C, 0x38, 0x0C, 0xC6, 0x7C, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x7E, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0C, 0xFE, 0x0C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xFE, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xC0, 0xC0, 0xC0, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x6C, 0xFE, 0x6C, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7C, 0x7C, 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0x7C, 0x7C, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x18, 0x3C, 0x3C, 0x3C, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x6C, 0x6C, 0xFE, 0x6C, 0x6C, 0x6C, 0xFE, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00],
+ [0x18, 0x18, 0x7C, 0xC6, 0xC2, 0xC0, 0x7C, 0x06, 0x86, 0xC6, 0x7C, 0x18, 0x18, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0xC2, 0xC6, 0x0C, 0x18, 0x30, 0x60, 0xC6, 0x86, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x38, 0x6C, 0x6C, 0x38, 0x76, 0xDC, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x0C, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0C, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xCE, 0xD6, 0xD6, 0xE6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x7C, 0xC6, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0xC6, 0xFE, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x7C, 0xC6, 0x06, 0x06, 0x3C, 0x06, 0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x0C, 0x1C, 0x3C, 0x6C, 0xCC, 0xFE, 0x0C, 0x0C, 0x0C, 0x1E, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0xFE, 0xC0, 0xC0, 0xC0, 0xFC, 0x0E, 0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x38, 0x60, 0xC0, 0xC0, 0xFC, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0xFE, 0xC6, 0x06, 0x06, 0x0C, 0x18, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0x06, 0x0C, 0x78, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x7C, 0xC6, 0xC6, 0x0C, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xDE, 0xDE, 0xDE, 0xDC, 0xC0, 0x7C, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x10, 0x38, 0x6C, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0xFC, 0x66, 0x66, 0x66, 0x7C, 0x66, 0x66, 0x66, 0x66, 0xFC, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x3C, 0x66, 0xC2, 0xC0, 0xC0, 0xC0, 0xC0, 0xC2, 0x66, 0x3C, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0xF8, 0x6C, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6C, 0xF8, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0xFE, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xFE, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0xFE, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x3C, 0x66, 0xC2, 0xC0, 0xC0, 0xDE, 0xC6, 0xC6, 0x66, 0x3A, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x1E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0xCC, 0xCC, 0xCC, 0x78, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0xE6, 0x66, 0x6C, 0x6C, 0x78, 0x78, 0x6C, 0x66, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0xF0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x66, 0xFE, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0xC6, 0xEE, 0xFE, 0xFE, 0xD6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0xC6, 0xE6, 0xF6, 0xFE, 0xDE, 0xCE, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x38, 0x6C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x6C, 0x38, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0xFC, 0x66, 0x66, 0x66, 0x7C, 0x60, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xD6, 0xDE, 0x7C, 0x0C, 0x0E, 0x00, 0x00],
+ [0x00, 0x00, 0xFC, 0x66, 0x66, 0x66, 0x7C, 0x6C, 0x66, 0x66, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x7C, 0xC6, 0xC6, 0x60, 0x38, 0x0C, 0x06, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x7E, 0x7E, 0x5A, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x6C, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xD6, 0xD6, 0xFE, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0xC6, 0xC6, 0x6C, 0x6C, 0x38, 0x38, 0x6C, 0x6C, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0xFE, 0xC6, 0x86, 0x0C, 0x18, 0x30, 0x60, 0xC2, 0xC6, 0xFE, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x3C, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3C, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0x70, 0x38, 0x1C, 0x0E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x3C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x3C, 0x00, 0x00, 0x00, 0x00],
+ [0x10, 0x38, 0x6C, 0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00],
+ [0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0xE0, 0x60, 0x60, 0x78, 0x6C, 0x66, 0x66, 0x66, 0x66, 0xDC, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC0, 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x1C, 0x0C, 0x0C, 0x3C, 0x6C, 0xCC, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xFE, 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x38, 0x6C, 0x64, 0x60, 0xF0, 0x60, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x7C, 0x0C, 0xCC, 0x78, 0x00],
+ [0x00, 0x00, 0xE0, 0x60, 0x60, 0x6C, 0x76, 0x66, 0x66, 0x66, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x06, 0x06, 0x00, 0x0E, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3C, 0x00],
+ [0x00, 0x00, 0xE0, 0x60, 0x60, 0x66, 0x6C, 0x78, 0x78, 0x6C, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0x00, 0xEC, 0xFE, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x60, 0x60, 0xF0, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x7C, 0x0C, 0x0C, 0x1E, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x76, 0x62, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0x60, 0x38, 0x0C, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x10, 0x30, 0x30, 0xFC, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1C, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xD6, 0xD6, 0xFE, 0x6C, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0x6C, 0x38, 0x38, 0x38, 0x6C, 0xC6, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x0C, 0xF8, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xCC, 0x18, 0x30, 0x60, 0xC6, 0xFE, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x0E, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x18, 0x0E, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x70, 0x18, 0x18, 0x18, 0x0E, 0x18, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x76, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6C, 0xC6, 0xC6, 0xC6, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x3C, 0x66, 0xC2, 0xC0, 0xC0, 0xC0, 0xC2, 0x66, 0x3C, 0x0C, 0x06, 0x7C, 0x00, 0x00],
+ [0x00, 0x00, 0xCC, 0xCC, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x0C, 0x18, 0x30, 0x00, 0x7C, 0xC6, 0xFE, 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x10, 0x38, 0x6C, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0xCC, 0xCC, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x60, 0x30, 0x18, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x38, 0x6C, 0x38, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0x3C, 0x66, 0x60, 0x60, 0x66, 0x3C, 0x0C, 0x06, 0x3C, 0x00, 0x00, 0x00],
+ [0x00, 0x10, 0x38, 0x6C, 0x00, 0x7C, 0xC6, 0xFE, 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0xC6, 0xC6, 0x00, 0x7C, 0xC6, 0xFE, 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x60, 0x30, 0x18, 0x00, 0x7C, 0xC6, 0xFE, 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x66, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x18, 0x3C, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0xC6, 0xC6, 0x10, 0x38, 0x6C, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00],
+ [0x38, 0x6C, 0x38, 0x00, 0x38, 0x6C, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00],
+ [0x18, 0x30, 0x60, 0x00, 0xFE, 0x66, 0x60, 0x7C, 0x60, 0x60, 0x66, 0xFE, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0x00, 0xCC, 0x76, 0x36, 0x7E, 0xD8, 0xD8, 0x6E, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x3E, 0x6C, 0xCC, 0xCC, 0xFE, 0xCC, 0xCC, 0xCC, 0xCC, 0xCE, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x10, 0x38, 0x6C, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0xC6, 0xC6, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x60, 0x30, 0x18, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x30, 0x78, 0xCC, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x60, 0x30, 0x18, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0xC6, 0xC6, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x0C, 0x78, 0x00],
+ [0x00, 0xC6, 0xC6, 0x00, 0x38, 0x6C, 0xC6, 0xC6, 0xC6, 0xC6, 0x6C, 0x38, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0xC6, 0xC6, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x18, 0x18, 0x3C, 0x66, 0x60, 0x60, 0x60, 0x66, 0x3C, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x38, 0x6C, 0x64, 0x60, 0xF0, 0x60, 0x60, 0x60, 0x60, 0xE6, 0xFC, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x66, 0x66, 0x3C, 0x18, 0x7E, 0x18, 0x7E, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0xF8, 0xCC, 0xCC, 0xF8, 0xC4, 0xCC, 0xDE, 0xCC, 0xCC, 0xCC, 0xC6, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x0E, 0x1B, 0x18, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, 0xD8, 0x70, 0x00, 0x00],
+ [0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x0C, 0x18, 0x30, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x18, 0x30, 0x60, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x18, 0x30, 0x60, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x76, 0xDC, 0x00, 0xDC, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00],
+ [0x76, 0xDC, 0x00, 0xC6, 0xE6, 0xF6, 0xFE, 0xDE, 0xCE, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x3C, 0x6C, 0x6C, 0x3E, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x38, 0x6C, 0x6C, 0x38, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, 0xC0, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0xC0, 0xC0, 0xC2, 0xC6, 0xCC, 0x18, 0x30, 0x60, 0xCE, 0x93, 0x06, 0x0C, 0x1F, 0x00, 0x00],
+ [0x00, 0xC0, 0xC0, 0xC2, 0xC6, 0xCC, 0x18, 0x30, 0x66, 0xCE, 0x9A, 0x3F, 0x06, 0x0F, 0x00, 0x00],
+ [0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x3C, 0x3C, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x66, 0xCC, 0x66, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0x00, 0xCC, 0x66, 0x33, 0x66, 0xCC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
+ [0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44],
+ [0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA],
+ [0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77],
+ [0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18],
+ [0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xF8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18],
+ [0x18, 0x18, 0x18, 0x18, 0x18, 0xF8, 0x18, 0xF8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18],
+ [0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xF6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36],
+ [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36],
+ [0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x18, 0xF8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18],
+ [0x36, 0x36, 0x36, 0x36, 0x36, 0xF6, 0x06, 0xF6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36],
+ [0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36],
+ [0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x06, 0xF6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36],
+ [0x36, 0x36, 0x36, 0x36, 0x36, 0xF6, 0x06, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
+ [0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
+ [0x18, 0x18, 0x18, 0x18, 0x18, 0xF8, 0x18, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18],
+ [0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
+ [0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18],
+ [0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18],
+ [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
+ [0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18],
+ [0x18, 0x18, 0x18, 0x18, 0x18, 0x1F, 0x18, 0x1F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18],
+ [0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36],
+ [0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36],
+ [0x36, 0x36, 0x36, 0x36, 0x36, 0xF7, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xF7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36],
+ [0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36],
+ [0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
+ [0x36, 0x36, 0x36, 0x36, 0x36, 0xF7, 0x00, 0xF7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36],
+ [0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
+ [0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18],
+ [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36],
+ [0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
+ [0x18, 0x18, 0x18, 0x18, 0x18, 0x1F, 0x18, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x18, 0x1F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18],
+ [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36],
+ [0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xFF, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36],
+ [0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0x18, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18],
+ [0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18],
+ [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF],
+ [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF],
+ [0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0],
+ [0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F],
+ [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xDC, 0xD8, 0xD8, 0xD8, 0xDC, 0x76, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xC6, 0xFC, 0xC6, 0xC6, 0xFC, 0xC0, 0xC0, 0xC0, 0x00, 0x00],
+ [0x00, 0x00, 0xFE, 0xC6, 0xC6, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0x80, 0xFE, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0xFE, 0xC6, 0x60, 0x30, 0x18, 0x30, 0x60, 0xC6, 0xFE, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0x70, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x60, 0x60, 0xC0, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0x76, 0xDC, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x7E, 0x18, 0x3C, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x7E, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x38, 0x6C, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0x6C, 0x38, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x38, 0x6C, 0xC6, 0xC6, 0xC6, 0x6C, 0x6C, 0x6C, 0x6C, 0xEE, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x1E, 0x30, 0x18, 0x0C, 0x3E, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0xDB, 0xDB, 0xDB, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x03, 0x06, 0x7E, 0xCF, 0xDB, 0xF3, 0x7E, 0x60, 0xC0, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x1C, 0x30, 0x60, 0x60, 0x7C, 0x60, 0x60, 0x60, 0x30, 0x1C, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x30, 0x18, 0x0C, 0x06, 0x0C, 0x18, 0x30, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x0C, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0C, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x0E, 0x1B, 0x1B, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18],
+ [0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xD8, 0xD8, 0xD8, 0x70, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7E, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xDC, 0x00, 0x76, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x38, 0x6C, 0x6C, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x0F, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0xEC, 0x6C, 0x6C, 0x3C, 0x1C, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0xD8, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x70, 0x98, 0x30, 0x60, 0xC8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00],
+ [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
+ ]
psf2_file_path = "scripts/font.psf"
diff --git a/scripts/initramfs-test.py b/scripts/initramfs-test.py
new file mode 100644
index 0000000..811cd37
--- /dev/null
+++ b/scripts/initramfs-test.py
@@ -0,0 +1,37 @@
+import os
+import random
+import string
+import sys
+
+def generate_random_string(length: int):
+ return ''.join(random.choices(string.ascii_letters + string.digits, k=length))
+
+def generate_random_data(size: int):
+ return os.urandom(size)
+
+def create_random_structure(output_dir: str, depth: int, max_depth: int):
+ if depth >= max_depth:
+ return
+
+ random_dir = generate_random_string(10)
+ os.makedirs(os.path.join(output_dir, random_dir))
+
+ random_file_name = generate_random_string(8)
+ random_file_path = os.path.join(output_dir, random_dir, random_file_name)
+
+ with open(random_file_path, 'wb') as file:
+ pass
+
+ create_random_structure(os.path.join(output_dir, random_dir), depth + 1, max_depth)
+
+if __name__ == "__main__":
+ if len(sys.argv) < 2 or len(sys.argv) > 3:
+ print("Usage: initramfs-test.py [output_dir]")
+ exit(1)
+
+ iterations = int(sys.argv[1])
+ output_dir = sys.argv[2] if len(sys.argv) == 3 else "."
+
+ for i in range(iterations):
+ max_depth = random.randint(0, 3)
+ create_random_structure(output_dir, 0, max_depth)
diff --git a/src/arch/x86_64/mod.rs b/src/arch/x86_64/mod.rs
index 5511259..38f5c21 100644
--- a/src/arch/x86_64/mod.rs
+++ b/src/arch/x86_64/mod.rs
@@ -17,8 +17,8 @@ pub fn push_gprs() {
pub fn pop_gprs() {
unsafe {
core::arch::asm!(
- "pop rax", "pop rbx", "pop rcx", "pop rdx", "pop rsi", "pop rdi", "pop rbp", "pop r8",
- "pop r9", "pop r10", "pop r11", "pop r12", "pop r13", "pop r14", "pop r15",
+ "pop r15", "pop r14", "pop r13", "pop r12", "pop r11", "pop r10", "pop r9", "pop r8",
+ "pop rbp", "pop rdi", "pop rsi", "pop rdx", "pop rcx", "pop rbx", "pop rax"
);
}
}
diff --git a/src/arch/x86_common/stack_trace.rs b/src/arch/x86_common/stack_trace.rs
index f8caf33..180ce4f 100644
--- a/src/arch/x86_common/stack_trace.rs
+++ b/src/arch/x86_common/stack_trace.rs
@@ -20,6 +20,8 @@ pub fn print_stack_trace(max_frames: usize, rbp: u64) {
let instruction_pointer = unsafe { (*stackframe).rip };
+ crate::print!(" {:#X} ", instruction_pointer);
+
let instrcution_info = get_function_name(instruction_pointer);
if let Ok((function_name, function_offset)) = instrcution_info {
diff --git a/src/drivers/acpi.rs b/src/drivers/acpi.rs
index e99bbab..4025b0d 100644
--- a/src/drivers/acpi.rs
+++ b/src/drivers/acpi.rs
@@ -1,260 +1,264 @@
-use crate::{
- libs::{lazy::Lazy, mutex::Mutex},
- log_error, log_info, log_ok,
-};
-use alloc::{sync::Arc, vec::Vec};
-use limine::RsdpRequest;
+// TODO: reduce the need to derive(Clone, Copy) everything
-static RSDP_REQUEST: RsdpRequest = RsdpRequest::new(0);
+use alloc::{sync::Arc, vec::Vec};
+
+use crate::{
+ arch::io::{inw, outb},
+ libs::{lazy::Lazy, mutex::Mutex, oncecell::OnceCell},
+ log_info,
+};
#[repr(C, packed)]
-struct Rsdp {
+#[derive(Clone, Copy, Debug)]
+struct SDTHeader {
+ pub signature: [u8; 4],
+ pub length: u32,
+ pub revision: u8,
+ pub checksum: u8,
+ pub oemid: [u8; 6],
+ pub oem_table_id: [u8; 8],
+ pub oem_revision: u32,
+ pub creator_id: u32,
+ pub creator_revision: u32,
+}
+
+#[repr(C, packed)]
+#[derive(Clone, Copy, Debug)]
+pub struct SDT {
+ pub header: SDTHeader,
+ pub inner: T,
+}
+
+impl SDT {
+ unsafe fn new(pointer: *mut u8) -> Self {
+ let header = *(pointer.cast::());
+ let inner = *(pointer.add(core::mem::size_of::()).cast::());
+
+ return Self { header, inner };
+ }
+}
+
+#[repr(C, packed)]
+#[derive(Debug)]
+struct RSDP {
signature: [u8; 8],
checksum: u8,
oem_id: [u8; 6],
revision: u8,
- rsdt_address: u32,
+ rsdt_addr: u32,
}
#[repr(C, packed)]
-struct Xsdp {
+struct XSDP {
+ rsdp: RSDP,
+
length: u32,
- xsdt_address: u64,
- extended_checksum: u8,
- reserved: [u8; 3],
+ xsdt_addr: u64,
+ ext_checksum: u8,
+ _reserved: [u8; 3],
}
-pub struct Acpi {
- tables: Arc<[*const u8]>,
- entries: usize,
- v2: bool,
+#[repr(C, packed)]
+#[derive(Clone, Copy, Debug)]
+struct RSDT {
+ pointers: u32,
}
-impl Acpi {
- fn has_signature(&self, table_index: usize, signature: &str) -> bool {
- unsafe {
- let sdt_header: &SdtHeader = &*(self.tables[table_index] as *const SdtHeader);
- let st = core::str::from_utf8_unchecked(&sdt_header.signature);
- st == signature
- }
- }
-
- pub fn list_tables(&self) {
- unsafe {
- for i in 0..self.entries {
- let sdt_header: &SdtHeader = &*(self.tables[i] as *const SdtHeader);
- let st = sdt_header.signature;
- log_info!("entry {:02}: {:?}", i + 1, sdt_header);
- }
- }
- }
-
- pub fn get_table(&self, signature: &str) -> Option<*const u8> {
- for i in 0..self.entries {
- if self.has_signature(i, signature) {
- return Some(self.tables[i]);
- }
- }
-
- None
- }
-}
-
-const RSDP_V1_LENGTH: usize = 20;
-const RSDP_V2_EXT_LENGTH: usize = core::mem::size_of::() - RSDP_V1_LENGTH;
-const RSDP_SIG: [u8; 8] = *b"RSD PTR ";
-
-impl Rsdp {
- pub fn is_valid(&self) -> bool {
- if self.signature != RSDP_SIG {
- return false;
- }
-
- let bytes = unsafe { core::slice::from_raw_parts(self as *const Rsdp as *const u8, 20) };
- let sum = bytes.iter().fold(0u8, |sum, &byte| sum.wrapping_add(byte));
-
- if sum & 0xFF != 0 {
- return false;
- }
-
- return true;
- }
-}
-
-impl Xsdp {
- pub fn is_valid(&self) -> bool {
- let bytes = unsafe { core::slice::from_raw_parts(self as *const Xsdp as *const u8, 20) };
- let sum = bytes.iter().fold(0u8, |sum, &byte| sum.wrapping_add(byte));
-
- if sum & 0xFF != 0 {
- return false;
- }
-
- return true;
- }
-}
-
-static ACPI: Lazy> = Lazy::new(|| {
- let acpi = resolve_acpi();
-
- if acpi.is_err() {
- panic!("Failed to resolve ACPI!");
- }
-
- Mutex::new(acpi.unwrap())
-});
-
-pub fn init_acpi() {
- let acpi_lock = ACPI.lock();
- let acpi = acpi_lock.read();
-
- log_ok!("Successfully initialized ACPI with {} tables", acpi.entries);
-
- acpi.list_tables()
-}
-
-#[derive(Debug)]
-enum AcpiRootTable {
- Rsdp(u32),
- Xsdp(u64),
-}
-
-impl AcpiRootTable {
- pub fn get_from_bootloader() -> Result {
- let rsdp_response = RSDP_REQUEST.get_response().get();
-
- if rsdp_response.is_none() {
- log_error!("Failed to initialize ACPI: RSDP not found!");
- return Err(());
- }
-
- let rsdp_address = &rsdp_response.unwrap().address;
-
- let rsdp_table: &Rsdp = unsafe { &*(rsdp_address.as_ptr().unwrap() as *const Rsdp) };
-
- if !rsdp_table.is_valid() {
- log_error!("Failed to initialize ACPI: RSDP was not valid!");
- return Err(());
- }
-
- if rsdp_table.revision == 2 {
- let xsdp_table: &Xsdp = unsafe { &*(rsdp_address.as_ptr().unwrap() as *const Xsdp) };
-
- if !xsdp_table.is_valid() {
- log_error!("Failed to initalize ACPI: XSDP was not valid!");
- return Err(());
- }
-
- return Ok(AcpiRootTable::Xsdp(xsdp_table.xsdt_address));
- }
-
- return Ok(AcpiRootTable::Rsdp(rsdp_table.rsdt_address));
- }
-}
-
-fn resolve_acpi() -> Result {
- let root_table = AcpiRootTable::get_from_bootloader()?;
-
- crate::println!("{:?}", root_table);
-
- let (header_addr, ptr_size, ext_table) = match root_table {
- AcpiRootTable::Rsdp(addr) => (addr as u64, core::mem::size_of::(), false),
- AcpiRootTable::Xsdp(addr) => (addr, core::mem::size_of::(), true),
- };
-
- let root_header: &SdtHeader = unsafe { &*(header_addr as *const SdtHeader) };
-
- unsafe {
- if !ext_table {
- if core::str::from_utf8_unchecked(&root_header.signature) != "RSDT" {
- log_error!("Invalid root table header, expected RSDT.");
- return Err(());
- }
- } else {
- if core::str::from_utf8_unchecked(&root_header.signature) != "XSDT" {
- log_error!("Invalid root table header, expected XSDT.");
- return Err(());
- }
- }
- }
-
- let mut entries = (root_header.length as usize - core::mem::size_of::()) / ptr_size;
- if entries > 48 {
- log_error!("Expected at most 48 ACPI tables, got {entries}!");
- entries = 48;
- }
-
- let mut acpi_tables: Vec<*const u8> = Vec::with_capacity(entries);
-
- for i in 0..entries {
- let address =
- (header_addr + (core::mem::size_of::() + i * ptr_size) as u64) as *const u8;
-
- acpi_tables.push(address);
- }
-
- crate::println!("{:?} {}", acpi_tables, entries);
-
- return Ok(Acpi {
- tables: Arc::from(acpi_tables),
- entries,
- v2: ext_table,
- });
+#[repr(C, packed)]
+#[derive(Clone, Copy, Debug)]
+struct XSDT {
+ pointers: u64,
}
#[derive(Clone, Copy, Debug)]
-#[repr(C)]
-struct SdtHeader {
- signature: [u8; 4],
- length: u32,
- revision: u8,
- checksum: u8,
- oem_id: [u8; 6],
- oem_table_id: [u8; 8],
- oem_revision: u32,
- creator_id: u32,
- creator_revision: u32,
+enum RootSDT {
+ RSDT(SDT),
+ XSDT(SDT),
}
-fn check_rsdt_checksum(table_header: *const SdtHeader) -> bool {
- let mut sum: u8 = 0;
-
- for i in 0..unsafe { (*table_header).length } {
- sum += unsafe { *((table_header as *const u8).add(i as usize)) };
+impl RootSDT {
+ fn header(&self) -> SDTHeader {
+ return match self {
+ &RootSDT::RSDT(RSDT) => RSDT.header,
+ &RootSDT::XSDT(XSDT) => XSDT.header,
+ };
}
- return sum == 0;
+ fn len(&self) -> usize {
+ let ptr_size = match self {
+ &RootSDT::RSDT(_) => 4,
+ &RootSDT::XSDT(_) => 8,
+ };
+
+ return (self.header().length as usize - core::mem::size_of::()) / ptr_size;
+ }
+
+ unsafe fn get(&self, idx: usize) -> *const u8 {
+ let mut offset = 0;
+
+ let root_ptr = match self {
+ &RootSDT::RSDT(RSDT) => {
+ let ptrs = RSDT.inner.pointers as *const u8;
+ assert!(!ptrs.is_null());
+ ptrs.add(offset)
+ }
+ &RootSDT::XSDT(XSDT) => {
+ let ptrs = XSDT.inner.pointers as *const u8;
+ assert!(!ptrs.is_null());
+ ptrs.add(offset)
+ }
+ };
+
+ for _ in 0..idx {
+ let header = *root_ptr.add(offset).cast::();
+ offset += header.length as usize;
+ }
+
+ crate::println!("{offset:X?} {idx}");
+
+ return root_ptr.add(offset);
+ }
+}
+
+#[derive(Clone, Debug)]
+struct ACPI {
+ root_sdt: RootSDT,
+ tables: Vec<[u8; 4]>,
+}
+
+static ACPI: OnceCell = OnceCell::new();
+
+static RSDP_REQ: limine::RsdpRequest = limine::RsdpRequest::new(0);
+
+fn resolve_acpi() {
+ let rsdp_ptr = RSDP_REQ.get_response().get();
+ if rsdp_ptr.is_none() {
+ panic!("RSDP not found!");
+ }
+
+ let rsdp = unsafe { &*rsdp_ptr.unwrap().address.as_ptr().unwrap().cast::() };
+
+ log_info!("RSDP: {rsdp:X?}");
+
+ // TODO: validate RSDT
+ let root_sdt = {
+ if rsdp.revision == 0 {
+ RootSDT::RSDT(unsafe { SDT::new(rsdp.rsdt_addr as *mut u8) })
+ } else {
+ let xsdt = unsafe { &*rsdp_ptr.unwrap().address.as_ptr().unwrap().cast::() };
+ RootSDT::XSDT(unsafe { SDT::new(xsdt.xsdt_addr as *mut u8) })
+ }
+ };
+
+ log_info!("{root_sdt:X?}");
+
+ let tables: Vec<[u8; 4]> = (0..root_sdt.len())
+ .map(|i| {
+ let sdt_ptr = unsafe { root_sdt.get(i) };
+ let signature = unsafe { core::slice::from_raw_parts(sdt_ptr, 4) };
+ let ret = signature.try_into().unwrap();
+ ret
+ })
+ .collect();
+
+ let acpi_table = ACPI { root_sdt, tables };
+
+ ACPI.set(acpi_table);
}
#[repr(C, packed)]
-struct RSDT {
- h: SdtHeader,
- pointer_to_other_sdt: *const u8,
+#[derive(Clone, Copy, Debug)]
+struct GenericAddressStructure {
+ address_space: u8,
+ bit_width: u8,
+ bit_offset: u8,
+ access_size: u8,
+ address: u8,
}
-fn find_fadt(root_sdt: *const RSDT) -> Option {
- // unsafe {
- // let rsdt = root_sdt.as_ref()?;
- // let entries = (rsdt.h.length - core::mem::size_of::() as u32) / 4;
+#[repr(C, packed)]
+#[derive(Clone, Copy, Debug)]
+struct FADT {
+ firmware_ctrl: u32,
+ dsdt: u32,
- // let pointer_to_other_sdt =
+ _reserved: u8,
- // for i in 0..entries {
- // crate::println!("{i}");
+ preferred_power_management_profile: u8,
+ sci_interrupt: u16,
+ smi_cmd_port: u32,
+ acpi_enable: u8,
+ acpi_disable: u8,
+ s4biox_req: u8,
+ pstate_control: u8,
+ pm1a_event_block: u32,
+ pm1b_event_block: u32,
+ pm1a_control_block: u32,
+ pm1b_control_block: u32,
+ pm2_control_block: u32,
+ pm_timer_block: u32,
+ gpe0_block: u32,
+ gpe1_block: u32,
+ pm1_event_length: u8,
+ pm1_control_length: u8,
+ pm2_control_length: u8,
+ pm_timer_length: u8,
+ gpe0_length: u8,
+ gpe1_length: u8,
+ gpe1_base: u8,
+ c_state_control: u8,
+ worst_c2_latency: u16,
+ worst_c3_length: u16,
+ flush_size: u16,
+ flush_stride: u16,
+ duty_offset: u8,
+ duty_width: u8,
+ day_alarm: u8,
+ month_alarm: u8,
+ century: u8,
- // let h_ptr = rsdt.pointer_to_other_sdt[i as usize] as *const AcpiSdtHeader;
- // let h = h_ptr.as_ref()?;
- // let slice = core::slice::from_raw_parts(h.signature.as_ptr(), 4);
+ boot_architecture_flags: u16,
- // let signature = core::str::from_utf8(slice).ok()?;
+ _reserved2: u8,
+ flags: u32,
- // if signature == "FACP" {
- // return Some(*h_ptr);
- // }
- // }
+ reset_reg: GenericAddressStructure,
- // // No FACP found
- // return None;
- // }
- None
+ reset_value: u8,
+ _reserved3: [u8; 3],
+
+ x_firmware_control: u64,
+ x_dstd: u64,
+
+ x_pm1a_event_block: GenericAddressStructure,
+ x_pm1b_event_block: GenericAddressStructure,
+ x_pm1a_control_block: GenericAddressStructure,
+ x_pm1b_control_block: GenericAddressStructure,
+ x_pm2_control_block: GenericAddressStructure,
+ x_pm_timer_block: GenericAddressStructure,
+ x_gpe0_block: GenericAddressStructure,
+ x_gpe1_block: GenericAddressStructure,
+}
+
+pub fn init_acpi() {
+ resolve_acpi();
+
+ let fadt = find_table::("FACP").expect("Failed to find FADT");
+
+ crate::println!("{fadt:X?}");
+}
+
+pub fn find_table(table_name: &str) -> Option> {
+ assert_eq!(table_name.len(), 4);
+
+ for (i, table) in ACPI.tables.iter().enumerate() {
+ if table == table_name.as_bytes() {
+ let ptr = unsafe { ACPI.root_sdt.get(i).cast::>() };
+ crate::println!("Found {table_name} at index {i} {ptr:p}");
+ let table = unsafe { *ptr };
+ return Some(table);
+ }
+ }
+
+ return None;
}
diff --git a/src/drivers/fs/fat.rs b/src/drivers/fs/fat.rs
index 4612d34..d19b4e0 100755
--- a/src/drivers/fs/fat.rs
+++ b/src/drivers/fs/fat.rs
@@ -5,7 +5,7 @@ use alloc::{
vec::Vec,
};
-use crate::drivers::storage::drive::{BlockDevice, GPTPartitionEntry};
+use crate::drivers::storage::{BlockDevice, GPTPartitionEntry};
use super::vfs::{VfsDirectory, VfsFile, VfsFileSystem};
@@ -15,19 +15,23 @@ use super::vfs::{VfsDirectory, VfsFile, VfsFileSystem};
//
// Fat Clusters are either one of these types:
//
-// 0x0FFFFFF8 : End Of cluster Chain
-// 0x0FFFFFF7 : Bad Cluster
-// 0x00000001 - 0x0FFFFFEF : In use Cluster
-// 0x00000000 : Free Cluster
+// | fat12 | fat16 | fat32 | Description |
+// |---------------|-----------------|-------------------------|-------------------------------|
+// | 0xFF8-0xFFF | 0xFFF8-0xFFFF | 0x0FFFFFF8-0x0FFFFFFF | End Of cluster Chain |
+// | 0xFF7 | 0xFFF7 | 0x0FFFFFF7 | Bad Cluster |
+// | 0x002-0xFEF | 0x0002-0xFFEF | 0x00000002-0x0FFFFFEF | In use Cluster |
+// | 0x000 | 0x0000 | 0x00000000 | Free Cluster |
// End Of Chain
-const EOC: u32 = 0x0FFFFFF8;
+const EOC_12: u32 = 0x0FF8;
+const EOC_16: u32 = 0xFFF8;
+const EOC_32: u32 = 0x0FFFFFF8;
#[derive(Clone, Copy, Debug)]
enum FatType {
- Fat12,
- Fat16,
- Fat32,
+ Fat12(Fat16EBPB),
+ Fat16(Fat16EBPB),
+ Fat32(Fat32EBPB),
}
#[repr(C, packed)]
@@ -47,10 +51,24 @@ pub struct BIOSParameterBlock {
pub head_count: u16, // 10 00 (16)
pub hidden_sectors: u32, // 00 00 00 00
pub large_sector_count: u32, // 00 F8 01 00 (129024)
- // pub ebpb: [u8; 54],
- // ---------------------------------
- // - Extended BIOS Parameter Block -
- // ---------------------------------
+ pub ebpb_bytes: [u8; 54],
+}
+
+// Fat 12 and Fat 16 EBPB
+#[repr(C, packed)]
+#[derive(Clone, Copy, Debug)]
+pub struct Fat16EBPB {
+ pub drive_number: u8,
+ _reserved: u8,
+ pub signature: u8,
+ pub volume_id: u32,
+ pub volume_label: [u8; 11],
+ pub system_identifier_string: [u8; 8],
+}
+
+#[repr(C, packed)]
+#[derive(Clone, Copy, Debug)]
+pub struct Fat32EBPB {
pub sectors_per_fat_ext: u32, // E1 03 00 00 (993, wtf)
pub flags: [u8; 2], // 00 00
pub fat_version: u16, // 00 00
@@ -64,15 +82,12 @@ pub struct BIOSParameterBlock {
pub volume_id: u32, // Varies
pub volume_label: [u8; 11], // "NO NAME "
pub system_identifier_string: [u8; 8], // Always "FAT32 " but never trust the contents of this string (for some reason)
- _boot_code: [u8; 420], // ~~code~~
- pub bootable_signature: u16, // 0xAA55
}
#[repr(C, packed)]
#[derive(Debug)]
pub struct FSInfo {
pub lead_signature: u32,
- _reserved: [u8; 480],
pub mid_signature: u32,
pub last_known_free_cluster: u32,
pub look_for_free_clusters: u32,
@@ -83,7 +98,6 @@ pub struct FSInfo {
impl FSInfo {
pub fn from_bytes(bytes: Arc<[u8]>) -> Self {
let lead_signature = u32::from_le_bytes(bytes[0..4].try_into().unwrap());
- let _reserved = bytes[4..484].try_into().unwrap();
let mid_signature = u32::from_le_bytes(bytes[484..488].try_into().unwrap());
let last_known_free_cluster = u32::from_le_bytes(bytes[488..492].try_into().unwrap());
let look_for_free_clusters = u32::from_le_bytes(bytes[492..496].try_into().unwrap());
@@ -92,7 +106,6 @@ impl FSInfo {
return Self {
lead_signature,
- _reserved,
mid_signature,
last_known_free_cluster,
look_for_free_clusters,
@@ -150,7 +163,7 @@ pub struct FatFs<'a> {
drive: &'a dyn BlockDevice,
partition: GPTPartitionEntry,
// FAT info
- fs_info: FSInfo,
+ fs_info: Option,
fat: Option>,
bpb: BIOSParameterBlock,
fat_start: u64,
@@ -165,56 +178,12 @@ impl<'a> FatFs<'a> {
.read(partition.start_sector, 1)
.expect("Failed to read FAT32 BIOS Parameter Block!");
- let bpb = unsafe { *(bpb_bytes.clone().as_ptr() as *const BIOSParameterBlock) };
-
- let system_identifier = core::str::from_utf8(&bpb.system_identifier_string);
-
- if system_identifier.is_err() {
- return Err(());
- }
-
- // We're trusting it
- if let Ok(system_identifier_string) = system_identifier {
- if !system_identifier_string.contains("FAT32") {
- return Err(());
- }
- }
-
- let fsinfo_bytes = drive
- .read(partition.start_sector + bpb.fsinfo_sector as u64, 1)
- .expect("Failed to read FSInfo sector!");
-
- let fs_info = FSInfo::from_bytes(fsinfo_bytes);
-
- let fat_start = partition.start_sector + bpb.reserved_sectors as u64;
-
- let bytes_per_fat = 512 * bpb.sectors_per_fat_ext as usize;
-
- let mut fat: Option> = None;
-
- if crate::KERNEL_FEATURES.fat_in_mem {
- let mut fat_vec: Vec = Vec::with_capacity(bytes_per_fat / 4);
-
- for i in 0..(bpb.sectors_per_fat_ext as usize) {
- let sector = drive
- .read(fat_start + i as u64, 1)
- .expect("Failed to read FAT");
- for j in 0..(512 / 4) {
- fat_vec.push(u32::from_le_bytes(
- sector[j * 4..(j * 4 + 4)].try_into().unwrap(),
- ))
- }
- }
-
- fat = Some(Arc::from(fat_vec));
- } else {
- crate::log_info!(
- "\033[33mWARNING\033[0m: FAT is not being stored in memory, this feature is experimental and file reads are expected to be slower."
- )
- }
+ let bpb = unsafe { *(bpb_bytes.as_ptr().cast::()) };
let (total_sectors, fat_size) = if bpb.total_sectors == 0 {
- (bpb.large_sector_count, bpb.sectors_per_fat_ext)
+ (bpb.large_sector_count, unsafe {
+ (*bpb.ebpb_bytes.as_ptr().cast::()).sectors_per_fat_ext
+ })
} else {
(bpb.total_sectors as u32, bpb.sectors_per_fat as u32)
};
@@ -229,20 +198,104 @@ impl<'a> FatFs<'a> {
let total_clusters = total_data_sectors / bpb.sectors_per_cluster as u32;
let fat_type = if total_clusters < 4085 {
- FatType::Fat12
+ FatType::Fat12(unsafe { *bpb.ebpb_bytes.as_ptr().cast::() })
} else if total_clusters < 65525 {
- FatType::Fat16
+ FatType::Fat16(unsafe { *bpb.ebpb_bytes.as_ptr().cast::() })
} else {
- FatType::Fat32
+ FatType::Fat32(unsafe { *bpb.ebpb_bytes.as_ptr().cast::() })
};
- crate::println!("Found {fat_type:?} FS");
+ let system_ident = match fat_type {
+ FatType::Fat12(ebpb) => ebpb.system_identifier_string,
+ FatType::Fat16(ebpb) => ebpb.system_identifier_string,
+ FatType::Fat32(ebpb) => ebpb.system_identifier_string,
+ };
+
+ let system_identifier = core::str::from_utf8(&system_ident);
+
+ if system_identifier.is_err() {
+ return Err(());
+ }
+
+ if let Ok(system_identifier_string) = system_identifier {
+ match fat_type {
+ FatType::Fat12(_) => {
+ if !system_identifier_string.contains("FAT12") {
+ return Err(());
+ }
+ }
+ FatType::Fat16(_) => {
+ if !system_identifier_string.contains("FAT16") {
+ return Err(());
+ }
+ }
+ FatType::Fat32(_) => {
+ if !system_identifier_string.contains("FAT32") {
+ return Err(());
+ }
+ }
+ }
+ }
+
+ let fs_info = match fat_type {
+ FatType::Fat32(ebpb) => {
+ let fsinfo_bytes = drive
+ .read(partition.start_sector + ebpb.fsinfo_sector as u64, 1)
+ .expect("Failed to read FSInfo sector!");
+
+ Some(FSInfo::from_bytes(fsinfo_bytes))
+ }
+ _ => None,
+ };
+
+ let fat_start = partition.start_sector + bpb.reserved_sectors as u64;
let sectors_per_fat = match fat_type {
- FatType::Fat32 => bpb.sectors_per_fat_ext as usize,
+ FatType::Fat32(ebpb) => ebpb.sectors_per_fat_ext as usize,
_ => bpb.sectors_per_fat as usize,
};
+ let bytes_per_fat = 512 * sectors_per_fat;
+
+ let mut fat: Option> = None;
+
+ if crate::KERNEL_FEATURES.fat_in_mem {
+ let cluster_bytes = match fat_type {
+ FatType::Fat32(_) => 4,
+ _ => 2,
+ };
+
+ let mut fat_vec: Vec = Vec::with_capacity(bytes_per_fat / cluster_bytes);
+
+ for i in 0..sectors_per_fat {
+ let sector = drive
+ .read(fat_start + i as u64, 1)
+ .expect("Failed to read FAT");
+ for j in 0..(512 / cluster_bytes) {
+ match fat_type {
+ FatType::Fat32(_) => fat_vec.push(u32::from_le_bytes(
+ sector[j * cluster_bytes..(j * cluster_bytes + cluster_bytes)]
+ .try_into()
+ .unwrap(),
+ )),
+ _ => fat_vec.push(u16::from_le_bytes(
+ sector[j * cluster_bytes..(j * cluster_bytes + cluster_bytes)]
+ .try_into()
+ .unwrap(),
+ ) as u32),
+ }
+ }
+ }
+
+ fat = Some(Arc::from(fat_vec));
+ } else {
+ crate::log_info!(
+ "\033[33mWARNING\033[0m: FAT is not being stored in memory, this feature is experimental and file reads are expected to be slower."
+ )
+ }
+
+ crate::println!("Found {fat_type:?} FS");
+
let cluster_size = bpb.sectors_per_cluster as usize * 512;
return Ok(Self {
@@ -379,45 +432,66 @@ impl<'a> FatFs<'a> {
+ (self.bpb.fat_count as usize * fat_size)
+ root_dir_sectors as usize;
- return ((cluster - 2) as isize * self.bpb.sectors_per_cluster as isize) as usize
- + first_data_sector;
+ return ((((cluster.wrapping_sub(2)) as isize)
+ .wrapping_mul(self.bpb.sectors_per_cluster as isize)) as usize)
+ .wrapping_add(first_data_sector);
+ }
+
+ fn sector_to_cluster(&self, sector: usize) -> usize {
+ let fat_size = self.sectors_per_fat;
+ let root_dir_sectors = ((self.bpb.root_directory_count * 32)
+ + (self.bpb.bytes_per_sector - 1))
+ / self.bpb.bytes_per_sector;
+
+ let first_data_sector = self.bpb.reserved_sectors as usize
+ + (self.bpb.fat_count as usize * fat_size)
+ + root_dir_sectors as usize;
+
+ return (((sector).wrapping_sub(first_data_sector))
+ .wrapping_div(self.bpb.sectors_per_cluster as usize))
+ .wrapping_add(2);
}
fn get_next_cluster(&self, cluster: usize) -> u32 {
if crate::KERNEL_FEATURES.fat_in_mem {
return match self.fat_type {
- FatType::Fat12 => {
- todo!();
- }
- FatType::Fat16 => {
- todo!();
- }
- FatType::Fat32 => self.fat.as_ref().unwrap()[cluster] & 0x0FFFFFFF,
+ FatType::Fat12(_) => self.fat.as_ref().unwrap()[cluster] & 0x0FFF,
+ FatType::Fat16(_) => self.fat.as_ref().unwrap()[cluster] & 0xFFFF,
+ FatType::Fat32(_) => self.fat.as_ref().unwrap()[cluster] & 0x0FFFFFFF,
};
} else {
let fat_entry_size = match self.fat_type {
- FatType::Fat12 => 1, // 12 bits per entry
- FatType::Fat16 => 2, // 16 bits per entry
- FatType::Fat32 => 4, // "32" bits per entry
+ FatType::Fat12(_) => 2, // 12 bits per entry
+ FatType::Fat16(_) => 2, // 16 bits per entry
+ FatType::Fat32(_) => 4, // 28S bits per entry
};
let entry_offset = cluster * fat_entry_size;
let entry_offset_in_sector = entry_offset % 512;
+ // needs two incase we "straddle a sector"
let sector_data = self
.drive
- .read(self.fat_start + entry_offset as u64 / 512, 1)
+ .read(self.fat_start + entry_offset as u64 / 512, 2)
.expect("Failed to read from FAT!");
match self.fat_type {
- FatType::Fat12 => {
- todo!();
+ FatType::Fat12(_) => {
+ let cluster_entry_bytes: [u8; 2] = sector_data
+ [entry_offset_in_sector..entry_offset_in_sector + 2]
+ .try_into()
+ .unwrap();
+ return (u16::from_le_bytes(cluster_entry_bytes) & 0x0FFF) as u32;
}
- FatType::Fat16 => {
- todo!();
+ FatType::Fat16(_) => {
+ let cluster_entry_bytes: [u8; 2] = sector_data
+ [entry_offset_in_sector..entry_offset_in_sector + 2]
+ .try_into()
+ .unwrap();
+ return (u16::from_le_bytes(cluster_entry_bytes) & 0xFFFF) as u32;
}
- FatType::Fat32 => {
+ FatType::Fat32(_) => {
let cluster_entry_bytes: [u8; 4] = sector_data
- [entry_offset_in_sector..=entry_offset_in_sector + 3]
+ [entry_offset_in_sector..entry_offset_in_sector + 4]
.try_into()
.unwrap();
return u32::from_le_bytes(cluster_entry_bytes) & 0x0FFFFFFF;
@@ -430,7 +504,13 @@ impl<'a> FatFs<'a> {
impl<'a> VfsFileSystem for FatFs<'a> {
fn open(&self, path: &str) -> Result, ()> {
let path_componenets: Vec<&str> = path.trim_start_matches('/').split('/').collect();
- let mut current_cluster = self.bpb.root_dir_cluster as usize;
+ let mut current_cluster = match self.fat_type {
+ FatType::Fat32(ebpb) => ebpb.root_dir_cluster as usize,
+ _ => self.sector_to_cluster(
+ self.bpb.reserved_sectors as usize
+ + (self.bpb.fat_count as usize * self.sectors_per_fat),
+ ),
+ };
for path in path_componenets {
let file_entry: FileEntry = self.find_entry_in_directory(current_cluster, path)?;
@@ -497,8 +577,22 @@ impl<'a> VfsFile for FatFile<'a> {
cluster = self.fat_fs.get_next_cluster(cluster as usize);
- if cluster >= EOC {
- break;
+ match self.fat_fs.fat_type {
+ FatType::Fat12(_) => {
+ if cluster >= EOC_12 {
+ break;
+ }
+ }
+ FatType::Fat16(_) => {
+ if cluster >= EOC_16 {
+ break;
+ }
+ }
+ FatType::Fat32(_) => {
+ if cluster >= EOC_32 {
+ break;
+ }
+ }
}
}
diff --git a/src/drivers/fs/initramfs/compressors/gzip.rs b/src/drivers/fs/initramfs/compressors/gzip.rs
index 9f5c7ba..58b4e44 100644
--- a/src/drivers/fs/initramfs/compressors/gzip.rs
+++ b/src/drivers/fs/initramfs/compressors/gzip.rs
@@ -238,12 +238,13 @@ impl InflateContext {
}
self.ring.data[self.ring.pointer] = byte;
- self.output_buf.push(byte);
self.ring.pointer += 1;
+ self.output_buf.push(byte);
}
fn peek(&mut self, offset: usize) -> u8 {
- self.ring.data[(self.ring.pointer - offset) % 32768]
+ let index = (self.ring.pointer as usize).wrapping_sub(offset as usize) % 32768;
+ self.ring.data[index]
}
fn uncompressed(&mut self) -> Result<(), ()> {
diff --git a/src/drivers/fs/initramfs/mod.rs b/src/drivers/fs/initramfs/mod.rs
index 5beea59..8780c46 100755
--- a/src/drivers/fs/initramfs/mod.rs
+++ b/src/drivers/fs/initramfs/mod.rs
@@ -211,9 +211,7 @@ impl Squashfs<'_> {
&inode_table[inode_offset..],
));
}
- _ => {
- panic!("Unsupported or unknown inode file type {inode_file_type:?}!")
- }
+ _ => panic!("Unsupported or unknown inode file type {inode_file_type:?}!"),
};
}
diff --git a/src/drivers/storage/drive.rs b/src/drivers/storage/drive.rs
deleted file mode 100644
index 688bd49..0000000
--- a/src/drivers/storage/drive.rs
+++ /dev/null
@@ -1,74 +0,0 @@
-use alloc::sync::Arc;
-
-pub trait BlockDevice {
- fn sector_count(&self) -> u64;
- fn read(&self, sector: u64, sector_count: usize) -> Result, ()>;
- fn write(&self, sector: u64, data: &[u8]) -> Result<(), ()>;
-}
-
-#[derive(Clone, Copy, Debug)]
-pub struct GPTPartitionEntry {
- pub partition_type_guid: [u8; 16],
- pub unique_partition_guid: [u8; 16],
- pub start_sector: u64,
- pub end_sector: u64,
- pub attributes: u64,
- pub partition_name: [u8; 72],
-}
-
-#[derive(Debug)]
-pub struct GPTBlock {
- pub header: [u8; 8], // 0x45 0x46 0x49 0x20 0x50 0x41 0x52 0x54
- pub revision: u32,
- pub header_size: u32,
- pub header_checksum: u32, // CRC32
- _reserved: [u8; 4],
- pub header_lba: u64,
- pub header_lba_alt: u64,
- pub first_usable_block: u64,
- pub last_usable_block: u64,
- pub guid: [u8; 16],
- pub guid_lba: u64,
- pub partition_entry_count: u32,
- pub partition_entry_size: u32,
- pub partition_table_crc: u32,
- _reserved2: [u8; 512 - 0x5C],
-}
-
-impl GPTBlock {
- pub fn new(data: &[u8; 512]) -> Self {
- let header = data[0x00..0x08].try_into().unwrap();
- let revision = u32::from_le_bytes(data[0x08..0x0C].try_into().unwrap());
- let header_size = u32::from_le_bytes(data[0x0C..0x10].try_into().unwrap());
- let header_checksum = u32::from_le_bytes(data[0x10..0x14].try_into().unwrap());
- let _reserved = data[0x14..0x18].try_into().unwrap();
- let header_lba = u64::from_le_bytes(data[0x18..0x20].try_into().unwrap());
- let header_lba_alt = u64::from_le_bytes(data[0x20..0x28].try_into().unwrap());
- let first_usable_block = u64::from_le_bytes(data[0x28..0x30].try_into().unwrap());
- let last_usable_block = u64::from_le_bytes(data[0x30..0x38].try_into().unwrap());
- let guid = data[0x38..0x48].try_into().unwrap();
- let guid_lba = u64::from_le_bytes(data[0x48..0x50].try_into().unwrap());
- let partition_entry_count = u32::from_le_bytes(data[0x50..0x54].try_into().unwrap());
- let partition_entry_size = u32::from_le_bytes(data[0x54..0x58].try_into().unwrap());
- let partition_table_crc = u32::from_le_bytes(data[0x58..0x5C].try_into().unwrap());
- let _reserved2 = data[0x5C..512].try_into().unwrap();
-
- GPTBlock {
- header,
- revision,
- header_size,
- header_checksum,
- _reserved,
- header_lba,
- header_lba_alt,
- first_usable_block,
- last_usable_block,
- guid,
- guid_lba,
- partition_entry_count,
- partition_entry_size,
- partition_table_crc,
- _reserved2,
- }
- }
-}
diff --git a/src/drivers/storage/ide.rs b/src/drivers/storage/ide.rs
index b7ef3f7..499df8d 100755
--- a/src/drivers/storage/ide.rs
+++ b/src/drivers/storage/ide.rs
@@ -6,12 +6,12 @@ use crate::{
arch::io::{inb, insw, inw, outb, outsw},
drivers::{
fs::fat,
- storage::drive::{GPTBlock, GPTPartitionEntry},
+ storage::{GPTHeader, GPTPartitionEntry, MBR},
},
- libs::mutex::Mutex,
+ libs::{mutex::Mutex, uuid::Uuid},
};
-use super::drive::BlockDevice;
+use super::BlockDevice;
const ATA_SECTOR_SIZE: usize = 512;
@@ -564,12 +564,16 @@ fn ide_initialize(bar0: u32, bar1: u32, _bar2: u32, _bar3: u32, _bar4: u32) {
(sectors * ATA_SECTOR_SIZE as u64) / 1024 / 1024
);
- let mbr_sector = drive.read(0, 1).expect("Failed to read first sector");
+ let mbr_sector: MBR = (*drive.read(0, 1).expect("Failed to read first sector")).into();
- let signature: [u8; 2] = mbr_sector[510..].try_into().unwrap();
+ if u16::from_le_bytes(mbr_sector.signature) != 0xAA55 {
+ panic!("MBR is corrupted!");
+ }
- if u16::from_le_bytes(signature[0..2].try_into().unwrap()) != 0xAA55 {
- panic!("First sector is not MBR");
+ let mbr_partitions = mbr_sector.partitions();
+
+ if mbr_partitions[0].partition_type != 0xEE {
+ panic!("MBR disks are unsupported")
}
let gpt_sector = drive.read(1, 1).expect("Failed to read sector 2");
@@ -577,14 +581,7 @@ fn ide_initialize(bar0: u32, bar1: u32, _bar2: u32, _bar3: u32, _bar4: u32) {
let mut array = [0u8; 512];
array.copy_from_slice(&gpt_sector[..512]);
- let mut signature = [0u8; 8];
- signature.copy_from_slice(&gpt_sector[0..8]);
-
- if &signature != b"EFI PART" {
- panic!("MBR Disk is unsupported!")
- }
-
- let gpt = GPTBlock::new(&array);
+ let gpt = GPTHeader::new(&array);
let mut partitions: Vec =
Vec::with_capacity(gpt.partition_entry_count as usize);
@@ -607,27 +604,24 @@ fn ide_initialize(bar0: u32, bar1: u32, _bar2: u32, _bar3: u32, _bar4: u32) {
for i in 0..gpt.partition_entry_count {
let entry_offset = (i * gpt.partition_entry_size) as usize;
- let partition_type_guid: [u8; 16] = partition_sector[entry_offset..entry_offset + 16]
+ let partition_type_guid_bytes: [u8; 16] = partition_sector
+ [entry_offset..entry_offset + 16]
.try_into()
.unwrap();
- let mut is_zero = true;
+ let partition_type_guid = Uuid::from(partition_type_guid_bytes);
- for &j in partition_type_guid.iter() {
- if j != 0 {
- is_zero = false;
- }
- }
-
- if is_zero {
+ if partition_type_guid == "00000000-0000-0000-0000-000000000000 " {
continue;
}
- let unique_partition_guid: [u8; 16] = partition_sector
+ let unique_partition_guid_bytes: [u8; 16] = partition_sector
[entry_offset + 16..entry_offset + 32]
.try_into()
.unwrap();
+ let unique_partition_guid = Uuid::from(unique_partition_guid_bytes);
+
let start_sector = u64::from_le_bytes(
partition_sector[entry_offset + 32..entry_offset + 40]
.try_into()
@@ -661,6 +655,10 @@ fn ide_initialize(bar0: u32, bar1: u32, _bar2: u32, _bar3: u32, _bar4: u32) {
}
for &partition in partitions.iter() {
+ if partition.partition_type_guid != "C12A7328-F81F-11D2-BA4B-00A0C93EC93B" {
+ continue;
+ }
+
let fat_fs = fat::FatFs::new(drive, partition);
if fat_fs.is_err() {
@@ -671,7 +669,7 @@ fn ide_initialize(bar0: u32, bar1: u32, _bar2: u32, _bar3: u32, _bar4: u32) {
let vfs = crate::drivers::fs::vfs::Vfs::new(
Box::new(fat_fs),
- &format!("{:?}", partition.partition_type_guid),
+ &format!("{}", partition.partition_type_guid),
);
crate::drivers::fs::vfs::VFS_INSTANCES
@@ -692,6 +690,6 @@ fn ide_initialize(bar0: u32, bar1: u32, _bar2: u32, _bar3: u32, _bar4: u32) {
);
}
- crate::println!("{:?}", partitions);
+ crate::println!("{:X?}", partitions);
}
}
diff --git a/src/drivers/storage/mod.rs b/src/drivers/storage/mod.rs
index 37598e7..7edfc82 100644
--- a/src/drivers/storage/mod.rs
+++ b/src/drivers/storage/mod.rs
@@ -1,2 +1,152 @@
-pub mod drive;
pub mod ide;
+
+use alloc::{sync::Arc, vec::Vec};
+
+use crate::libs::uuid::Uuid;
+
+pub trait BlockDevice {
+ fn sector_count(&self) -> u64;
+ fn read(&self, sector: u64, sector_count: usize) -> Result, ()>;
+ fn write(&self, sector: u64, data: &[u8]) -> Result<(), ()>;
+}
+
+#[derive(Clone, Copy, Debug)]
+pub struct MBR {
+ pub disk_id: [u8; 4],
+ _reserved: [u8; 2],
+ pub first_partition: [u8; 16],
+ pub second_partition: [u8; 16],
+ pub third_partition: [u8; 16],
+ pub fourth_partition: [u8; 16],
+ pub signature: [u8; 2],
+}
+
+impl From<&[u8]> for MBR {
+ fn from(value: &[u8]) -> Self {
+ let mut offset = 0;
+
+ if value.len() >= 512 {
+ offset = 440;
+ }
+
+ return Self {
+ disk_id: value[offset..offset + 4].try_into().unwrap(),
+ _reserved: value[offset + 4..offset + 6].try_into().unwrap(),
+ first_partition: value[offset + 6..offset + 22].try_into().unwrap(),
+ second_partition: value[offset + 22..offset + 38].try_into().unwrap(),
+ third_partition: value[offset + 38..offset + 54].try_into().unwrap(),
+ fourth_partition: value[offset + 54..offset + 70].try_into().unwrap(),
+ signature: value[offset + 70..offset + 72].try_into().unwrap(),
+ };
+ }
+}
+
+impl MBR {
+ pub fn partitions(&self) -> Arc<[MBRPartition]> {
+ let mut partitions = Vec::new();
+
+ let raw_partitions = [
+ self.first_partition,
+ self.second_partition,
+ self.third_partition,
+ self.fourth_partition,
+ ];
+
+ for partition in raw_partitions.iter() {
+ // if partition bytes are empty
+ if partition.iter().filter(|&&x| x > 0).count() == 0 {
+ break;
+ }
+
+ let partition = MBRPartition {
+ boot_indicator: partition[0],
+ partition_start_chs: partition[1..4].try_into().unwrap(),
+ partition_type: partition[4],
+ partition_end_chs: partition[4..7].try_into().unwrap(),
+ partition_start_lba: u32::from_le_bytes(partition[8..12].try_into().unwrap()),
+ partition_sectors: u32::from_le_bytes(partition[12..16].try_into().unwrap()),
+ };
+
+ partitions.push(partition)
+ }
+
+ return Arc::from(partitions);
+ }
+}
+
+#[derive(Clone, Copy, Debug)]
+pub struct MBRPartition {
+ pub boot_indicator: u8,
+ pub partition_start_chs: [u8; 3],
+ pub partition_type: u8,
+ pub partition_end_chs: [u8; 3],
+ pub partition_start_lba: u32,
+ pub partition_sectors: u32,
+}
+
+#[derive(Clone, Copy, Debug)]
+pub struct GPTPartitionEntry {
+ pub partition_type_guid: Uuid,
+ pub unique_partition_guid: Uuid,
+ pub start_sector: u64,
+ pub end_sector: u64,
+ pub attributes: u64,
+ pub partition_name: [u8; 72],
+}
+
+#[derive(Debug)]
+pub struct GPTHeader {
+ pub header: [u8; 8], // 0x45 0x46 0x49 0x20 0x50 0x41 0x52 0x54
+ pub revision: u32,
+ pub header_size: u32,
+ pub header_checksum: u32, // CRC32
+ _reserved: [u8; 4],
+ pub header_lba: u64,
+ pub header_lba_alt: u64,
+ pub first_usable_block: u64,
+ pub last_usable_block: u64,
+ pub guid: Uuid,
+ pub guid_lba: u64,
+ pub partition_entry_count: u32,
+ pub partition_entry_size: u32,
+ pub partition_table_crc: u32,
+}
+
+impl GPTHeader {
+ pub fn new(data: &[u8]) -> Self {
+ assert!(data.len() >= 0x5C);
+
+ let header = data[0x00..0x08].try_into().unwrap();
+ let revision = u32::from_le_bytes(data[0x08..0x0C].try_into().unwrap());
+ let header_size = u32::from_le_bytes(data[0x0C..0x10].try_into().unwrap());
+ let header_checksum = u32::from_le_bytes(data[0x10..0x14].try_into().unwrap());
+ let _reserved = data[0x14..0x18].try_into().unwrap();
+ let header_lba = u64::from_le_bytes(data[0x18..0x20].try_into().unwrap());
+ let header_lba_alt = u64::from_le_bytes(data[0x20..0x28].try_into().unwrap());
+ let first_usable_block = u64::from_le_bytes(data[0x28..0x30].try_into().unwrap());
+ let last_usable_block = u64::from_le_bytes(data[0x30..0x38].try_into().unwrap());
+ let guid_bytes: [u8; 16] = data[0x38..0x48].try_into().unwrap();
+ let guid = guid_bytes.try_into().unwrap();
+ let guid_lba = u64::from_le_bytes(data[0x48..0x50].try_into().unwrap());
+ let partition_entry_count = u32::from_le_bytes(data[0x50..0x54].try_into().unwrap());
+ let partition_entry_size = u32::from_le_bytes(data[0x54..0x58].try_into().unwrap());
+ let partition_table_crc = u32::from_le_bytes(data[0x58..0x5C].try_into().unwrap());
+
+ Self {
+ header,
+ revision,
+ header_size,
+ header_checksum,
+ _reserved,
+ header_lba,
+ header_lba_alt,
+ first_usable_block,
+ last_usable_block,
+ guid,
+ guid_lba,
+ partition_entry_count,
+ partition_entry_size,
+ partition_table_crc,
+ }
+ }
+}
diff --git a/src/drivers/video/font.rs b/src/drivers/video/font.rs
index f2c834e..cebffff 100755
--- a/src/drivers/video/font.rs
+++ b/src/drivers/video/font.rs
@@ -2,7 +2,7 @@ use alloc::vec::Vec;
use crate::{
drivers::fs::{initramfs::INITRAMFS, vfs::VfsFileSystem},
- libs::lazy::Lazy,
+ libs::{lazy::Lazy, mutex::Mutex},
};
#[derive(Debug)]
diff --git a/src/libs/elf.rs b/src/libs/elf.rs
new file mode 100644
index 0000000..ae65ddd
--- /dev/null
+++ b/src/libs/elf.rs
@@ -0,0 +1,15 @@
+#[derive(Clone, Copy, Debug)]
+pub struct Elf;
+
+pub fn load_elf(bytes: &[u8]) -> Result {
+ if &bytes[0..4] != b"\x74ELF" {
+ return Err(());
+ }
+
+ if bytes[5] != 0x02 {
+ // Only support 64-bit ELF files for now
+ return Err(());
+ }
+
+ return Ok(Elf);
+}
diff --git a/src/libs/mod.rs b/src/libs/mod.rs
index 3886c61..763fec1 100644
--- a/src/libs/mod.rs
+++ b/src/libs/mod.rs
@@ -1,5 +1,8 @@
+pub mod elf;
pub mod lazy;
pub mod logging;
pub mod math;
pub mod mutex;
+pub mod oncecell;
pub mod util;
+pub mod uuid;
diff --git a/src/libs/oncecell.rs b/src/libs/oncecell.rs
new file mode 100644
index 0000000..f72b22e
--- /dev/null
+++ b/src/libs/oncecell.rs
@@ -0,0 +1,70 @@
+use core::{cell::UnsafeCell, ops::Deref, sync::atomic::AtomicU8};
+
+pub struct OnceCell {
+ state: AtomicU8,
+ data: UnsafeCell