commit 426ad76676e342291202910ab6295ae63293d8a3 Author: kaguya Date: Tue Apr 14 22:52:24 2026 -0400 Initial Commit diff --git a/GNUmakefile b/GNUmakefile new file mode 100644 index 0000000..600eb54 --- /dev/null +++ b/GNUmakefile @@ -0,0 +1,207 @@ +# Nuke built-in rules. +.SUFFIXES: + +# This is the name that our final executable will have. +# Change as needed. +override OUTPUT := kirkos + +# User controllable toolchain and toolchain prefix. +TOOLCHAIN := +TOOLCHAIN_PREFIX := +ifneq ($(TOOLCHAIN),) + ifeq ($(TOOLCHAIN_PREFIX),) + TOOLCHAIN_PREFIX := $(TOOLCHAIN)- + endif +endif + +# User controllable C compiler command. +ifneq ($(TOOLCHAIN_PREFIX),) + CC := $(TOOLCHAIN_PREFIX)gcc +else + CC := cc +endif + +# User controllable linker command. +LD := $(TOOLCHAIN_PREFIX)ld + +# Defaults overrides for variables if using "llvm" as toolchain. +ifeq ($(TOOLCHAIN),llvm) + CC := clang + LD := ld.lld +endif + +# User controllable C flags. +CFLAGS := -g -O2 -pipe + +# User controllable C preprocessor flags. We set none by default. +CPPFLAGS := + +# User controllable nasm flags. +NASMFLAGS := -g + +ISO_ROOT := iso_root +ISO := image.iso + +EXT2_ROOT := ext2_root +DISK_IMG := disk.img + +# User controllable linker flags. We set none by default. +LDFLAGS := + +# Check if CC is Clang. +override CC_IS_CLANG := $(shell ! $(CC) --version 2>/dev/null | grep -q '^Target: '; echo $$?) + +# If the C compiler is Clang, set the target as needed. +ifeq ($(CC_IS_CLANG),1) + override CC += \ + -target x86_64-unknown-none-elf +endif + +# Internal C flags that should not be changed by the user. +override CFLAGS += \ + -Wall \ + -Wextra \ + -std=gnu11 \ + -ffreestanding \ + -fno-stack-protector \ + -fno-stack-check \ + -fno-lto \ + -fno-PIC \ + -ffunction-sections \ + -fdata-sections \ + -m64 \ + -march=x86-64 \ + -mabi=sysv \ + -mno-80387 \ + -mno-mmx \ + -mno-sse \ + -mno-sse2 \ + -mno-red-zone \ + -mcmodel=kernel + +# Internal C preprocessor flags that should not be changed by the user. +override CPPFLAGS := \ + -I src \ + $(CPPFLAGS) \ + -MMD \ + -MP + +# Internal nasm flags that should not be changed by the user. +override NASMFLAGS := \ + -f elf64 \ + $(patsubst -g,-g -F dwarf,$(NASMFLAGS)) \ + -Wall + +# Internal linker flags that should not be changed by the user. +override LDFLAGS += \ + -m elf_x86_64 \ + -nostdlib \ + -static \ + -z max-page-size=0x1000 \ + --gc-sections \ + -T linker.lds + +# Use "find" to glob all *.c, *.S, and *.asm files in the tree and obtain the +# object and header dependency file names. +override SRCFILES := $(shell find -L src -type f 2>/dev/null | LC_ALL=C sort) +override CFILES := $(filter %.c,$(SRCFILES)) +override ASFILES := $(filter %.S,$(SRCFILES)) +override NASMFILES := $(filter %.asm,$(SRCFILES)) +override OBJ := $(addprefix obj/,$(CFILES:.c=.c.o) $(ASFILES:.S=.S.o) $(NASMFILES:.asm=.asm.o)) +override HEADER_DEPS := $(addprefix obj/,$(CFILES:.c=.c.d) $(ASFILES:.S=.S.d)) + +# Default target. This must come first, before header dependencies. +.PHONY: all run clean-iso iso limine debug +all: bin/$(OUTPUT) + +LIMINE_DIR := limine + +# Include header dependencies. +-include $(HEADER_DEPS) + +# Link rules for the final executable. +bin/$(OUTPUT): GNUmakefile linker.lds $(OBJ) + mkdir -p "$(dir $@)" + $(LD) $(LDFLAGS) $(OBJ) -o $@ + +# Compilation rules for *.c files. +obj/%.c.o: %.c GNUmakefile + mkdir -p "$(dir $@)" + $(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@ + +# Compilation rules for *.S files. +obj/%.S.o: %.S GNUmakefile + mkdir -p "$(dir $@)" + $(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@ + +# Compilation rules for *.asm (nasm) files. +obj/%.asm.o: %.asm GNUmakefile + mkdir -p "$(dir $@)" + nasm $(NASMFLAGS) $< -o $@ + + +$(DISK_IMG): $(EXT2_ROOT) + @echo "Creating ext2 disk image from $(EXT2_ROOT)..." + dd if=/dev/zero of=$(DISK_IMG) bs=1M count=32 + mkfs.ext2 -F -L KIRKOS $(DISK_IMG) + mkdir -p mnt + sudo mount -o loop $(DISK_IMG) mnt + sudo cp -r $(EXT2_ROOT)/* mnt/ + sudo umount mnt + rmdir mnt + @echo "Done: $(DISK_IMG) created" + +# Build ISO directory structure +$(ISO_ROOT): + mkdir -p $(ISO_ROOT)/boot + mkdir -p $(ISO_ROOT)/boot/limine + mkdir -p $(ISO_ROOT)/EFI/BOOT + +# Copy kernel +$(ISO_ROOT)/boot/$(OUTPUT): bin/$(OUTPUT) | $(ISO_ROOT) + cp -v bin/$(OUTPUT) $(ISO_ROOT)/boot/ + + +# Copy limine BIOS/UEFI files +limine-files: | $(ISO_ROOT) + cp -v limine.conf \ + $(LIMINE_DIR)/limine-bios.sys \ + $(LIMINE_DIR)/limine-bios-cd.bin \ + $(LIMINE_DIR)/limine-uefi-cd.bin \ + $(ISO_ROOT)/boot/limine + + cp -v $(LIMINE_DIR)/BOOTX64.EFI $(ISO_ROOT)/EFI/BOOT/ + cp -v $(LIMINE_DIR)/BOOTIA32.EFI $(ISO_ROOT)/EFI/BOOT/ + +# Build ISO +iso: all $(ISO_ROOT)/boot/$(OUTPUT) limine-files + xorriso -as mkisofs -R -r -J \ + -b boot/limine/limine-bios-cd.bin \ + -no-emul-boot -boot-load-size 4 -boot-info-table \ + -hfsplus \ + -apm-block-size 2048 \ + --efi-boot boot/limine/limine-uefi-cd.bin \ + -efi-boot-part --efi-boot-image \ + --protective-msdos-label \ + $(ISO_ROOT) -o $(ISO) + + ./$(LIMINE_DIR)/limine bios-install $(ISO) + +# Run in QEMU +run: $(DISK_IMG) iso + qemu-system-x86_64 -cdrom $(ISO) -hda $(DISK_IMG) -debugcon stdio -m 8G -smp 2 -device ich9-intel-hda -device hda-duplex + + +debug: iso $(DISK_IMG) + qemu-system-x86_64 \ + -cdrom $(ISO) -hda $(DISK_IMG) \ + -s -S -debugcon stdio -d int,cpu_reset -m 8G -smp 2 -device ich9-intel-hda,id=hda -device hda-duplex,id=codec0,bus=hda.0,cad=0 + +# Clean ISO artifacts +clean-iso: + rm -rf $(ISO_ROOT) $(ISO) + +# Remove object files and the final executable. +.PHONY: clean +clean: + rm -rf bin obj $(DISK_IMG) \ No newline at end of file diff --git a/bin/kirkos b/bin/kirkos new file mode 100755 index 0000000..2b1d558 Binary files /dev/null and b/bin/kirkos differ diff --git a/disk.img b/disk.img new file mode 100644 index 0000000..cef4c48 Binary files /dev/null and b/disk.img differ diff --git a/ext2_root/a.txt b/ext2_root/a.txt new file mode 100644 index 0000000..9fde1f1 --- /dev/null +++ b/ext2_root/a.txt @@ -0,0 +1 @@ +hamidashi no monster \ No newline at end of file diff --git a/ext2_root/charlie.tga b/ext2_root/charlie.tga new file mode 100644 index 0000000..be35bd3 Binary files /dev/null and b/ext2_root/charlie.tga differ diff --git a/ext2_root/dogcatman.txt b/ext2_root/dogcatman.txt new file mode 100644 index 0000000..de6c602 --- /dev/null +++ b/ext2_root/dogcatman.txt @@ -0,0 +1 @@ +dogcatman \ No newline at end of file diff --git a/ext2_root/init.elf b/ext2_root/init.elf new file mode 100755 index 0000000..ecfd81f Binary files /dev/null and b/ext2_root/init.elf differ diff --git a/ext2_root/qwerty.txt b/ext2_root/qwerty.txt new file mode 100644 index 0000000..f228909 --- /dev/null +++ b/ext2_root/qwerty.txt @@ -0,0 +1 @@ +qwerty \ No newline at end of file diff --git a/ext2_root/test.txt b/ext2_root/test.txt new file mode 100644 index 0000000..30d74d2 --- /dev/null +++ b/ext2_root/test.txt @@ -0,0 +1 @@ +test \ No newline at end of file diff --git a/image.iso b/image.iso new file mode 100644 index 0000000..b381abe Binary files /dev/null and b/image.iso differ diff --git a/iso_root/EFI/BOOT/BOOTIA32.EFI b/iso_root/EFI/BOOT/BOOTIA32.EFI new file mode 100644 index 0000000..adda6a0 Binary files /dev/null and b/iso_root/EFI/BOOT/BOOTIA32.EFI differ diff --git a/iso_root/EFI/BOOT/BOOTX64.EFI b/iso_root/EFI/BOOT/BOOTX64.EFI new file mode 100644 index 0000000..3537d57 Binary files /dev/null and b/iso_root/EFI/BOOT/BOOTX64.EFI differ diff --git a/iso_root/boot/kirkos b/iso_root/boot/kirkos new file mode 100755 index 0000000..2b1d558 Binary files /dev/null and b/iso_root/boot/kirkos differ diff --git a/iso_root/boot/limine/limine-bios-cd.bin b/iso_root/boot/limine/limine-bios-cd.bin new file mode 100644 index 0000000..f0e60a1 Binary files /dev/null and b/iso_root/boot/limine/limine-bios-cd.bin differ diff --git a/iso_root/boot/limine/limine-bios.sys b/iso_root/boot/limine/limine-bios.sys new file mode 100644 index 0000000..ef5574d Binary files /dev/null and b/iso_root/boot/limine/limine-bios.sys differ diff --git a/iso_root/boot/limine/limine-uefi-cd.bin b/iso_root/boot/limine/limine-uefi-cd.bin new file mode 100644 index 0000000..77c49f5 Binary files /dev/null and b/iso_root/boot/limine/limine-uefi-cd.bin differ diff --git a/iso_root/boot/limine/limine.conf b/iso_root/boot/limine/limine.conf new file mode 100644 index 0000000..72d383a --- /dev/null +++ b/iso_root/boot/limine/limine.conf @@ -0,0 +1,10 @@ +# Timeout in seconds that Limine will use before automatically booting. +timeout: 5 + +# The entry name that will be displayed in the boot menu. +/kirkOS + # We use the Limine boot protocol. + protocol: limine + + # Path to the kernel to boot. boot():/ represents the partition on which limine.conf is located. + path: boot():/boot/kirkos \ No newline at end of file diff --git a/limine.conf b/limine.conf new file mode 100644 index 0000000..72d383a --- /dev/null +++ b/limine.conf @@ -0,0 +1,10 @@ +# Timeout in seconds that Limine will use before automatically booting. +timeout: 5 + +# The entry name that will be displayed in the boot menu. +/kirkOS + # We use the Limine boot protocol. + protocol: limine + + # Path to the kernel to boot. boot():/ represents the partition on which limine.conf is located. + path: boot():/boot/kirkos \ No newline at end of file diff --git a/limine/.gitignore b/limine/.gitignore new file mode 100644 index 0000000..a1492fd --- /dev/null +++ b/limine/.gitignore @@ -0,0 +1,2 @@ +limine +limine.exe diff --git a/limine/BOOTAA64.EFI b/limine/BOOTAA64.EFI new file mode 100644 index 0000000..3d3563f Binary files /dev/null and b/limine/BOOTAA64.EFI differ diff --git a/limine/BOOTIA32.EFI b/limine/BOOTIA32.EFI new file mode 100644 index 0000000..adda6a0 Binary files /dev/null and b/limine/BOOTIA32.EFI differ diff --git a/limine/BOOTLOONGARCH64.EFI b/limine/BOOTLOONGARCH64.EFI new file mode 100644 index 0000000..3a3b326 Binary files /dev/null and b/limine/BOOTLOONGARCH64.EFI differ diff --git a/limine/BOOTRISCV64.EFI b/limine/BOOTRISCV64.EFI new file mode 100644 index 0000000..f176fa3 Binary files /dev/null and b/limine/BOOTRISCV64.EFI differ diff --git a/limine/BOOTX64.EFI b/limine/BOOTX64.EFI new file mode 100644 index 0000000..3537d57 Binary files /dev/null and b/limine/BOOTX64.EFI differ diff --git a/limine/LICENSE b/limine/LICENSE new file mode 100644 index 0000000..a59751f --- /dev/null +++ b/limine/LICENSE @@ -0,0 +1,22 @@ +Copyright (C) 2019-2026 Mintsuki and contributors. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/limine/Makefile b/limine/Makefile new file mode 100644 index 0000000..4962735 --- /dev/null +++ b/limine/Makefile @@ -0,0 +1,19 @@ +.POSIX: + +SHELL=/bin/sh + +CC=cc +CFLAGS=-g -O2 -pipe +CPPFLAGS= +LDFLAGS= +LIBS= + +.PHONY: all +all: limine + +.PHONY: clean +clean: + rm -f limine limine.exe + +limine: limine.c + $(CC) $(CFLAGS) -std=c99 $(CPPFLAGS) $(LDFLAGS) $< $(LIBS) -o $@ diff --git a/limine/limine-bios-cd.bin b/limine/limine-bios-cd.bin new file mode 100644 index 0000000..f0e60a1 Binary files /dev/null and b/limine/limine-bios-cd.bin differ diff --git a/limine/limine-bios-hdd.h b/limine/limine-bios-hdd.h new file mode 100644 index 0000000..a2844a3 --- /dev/null +++ b/limine/limine-bios-hdd.h @@ -0,0 +1,1394 @@ +const uint8_t binary_limine_hdd_bin_data[] = { + 0xeb, 0x3c, 0x90, 0x4c, 0x49, 0x4d, 0x49, 0x4e, 0x45, 0x20, 0x20, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x49, 0x4d, 0x49, 0x4e, + 0x45, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0xfc, + 0xea, 0x45, 0x7c, 0x00, 0x00, 0x31, 0xf6, 0x8e, 0xde, 0x8e, 0xc6, 0x8e, 0xd6, 0xbc, 0x00, 0x7c, + 0xfb, 0x80, 0xfa, 0x80, 0x0f, 0x82, 0x1a, 0x01, 0x80, 0xfa, 0x8f, 0x0f, 0x87, 0x12, 0x01, 0xb4, + 0x41, 0xbb, 0xaa, 0x55, 0xcd, 0x13, 0x0f, 0x82, 0x06, 0x01, 0x81, 0xfb, 0x55, 0xaa, 0x0f, 0x85, + 0xfd, 0x00, 0x68, 0x00, 0x70, 0x07, 0xbf, 0xa4, 0x7d, 0x66, 0x8b, 0x05, 0x66, 0x8b, 0x6d, 0x04, + 0x31, 0xdb, 0x66, 0xb9, 0x00, 0x7e, 0x00, 0x00, 0xe8, 0x55, 0x00, 0x0f, 0x82, 0xdf, 0x00, 0x0f, + 0x01, 0x16, 0x58, 0x7d, 0xfa, 0x66, 0x6a, 0x00, 0x66, 0xbd, 0x10, 0x00, 0x00, 0x00, 0x0f, 0x20, + 0xc0, 0x0f, 0xba, 0xe8, 0x00, 0x0f, 0x22, 0xc0, 0xea, 0x83, 0x7d, 0x08, 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, 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, 0x00, 0x00, + 0x60, 0xbe, 0x00, 0x80, 0x66, 0xc7, 0x04, 0x10, 0x00, 0x01, 0x00, 0x89, 0x5c, 0x04, 0x8c, 0x44, + 0x06, 0x52, 0x56, 0x66, 0x50, 0x66, 0x55, 0xb4, 0x48, 0xbe, 0x10, 0x80, 0xc7, 0x04, 0x1e, 0x00, + 0xcd, 0x13, 0x72, 0x4e, 0x66, 0x0f, 0xb7, 0x6c, 0x18, 0x91, 0x66, 0xc1, 0xe9, 0x10, 0x89, 0xca, + 0x31, 0xc9, 0xf7, 0xf5, 0x85, 0xd2, 0x0f, 0x95, 0xc1, 0x01, 0xc1, 0x66, 0x5a, 0x66, 0x58, 0x5e, + 0x66, 0x50, 0x66, 0x92, 0x66, 0x31, 0xd2, 0x66, 0xf7, 0xf5, 0x66, 0x93, 0x66, 0x58, 0x66, 0xf7, + 0xf5, 0x66, 0x89, 0x44, 0x08, 0x66, 0x89, 0x5c, 0x0c, 0x5a, 0xb4, 0x42, 0xf8, 0xcd, 0x13, 0x72, + 0x15, 0x01, 0x6c, 0x04, 0x66, 0x83, 0x44, 0x08, 0x01, 0x66, 0x83, 0x54, 0x0c, 0x00, 0xe2, 0xea, + 0xeb, 0x04, 0x83, 0xc4, 0x0c, 0xf9, 0x61, 0xc3, 0x17, 0x00, 0x56, 0x7d, 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x9b, 0xcf, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x93, 0xcf, 0x00, 0x46, 0x46, + 0x46, 0x46, 0x81, 0xc6, 0x30, 0x4f, 0x68, 0x00, 0xb8, 0x07, 0x26, 0x89, 0x36, 0x00, 0x00, 0xfb, + 0xf4, 0xeb, 0xfd, 0x8e, 0xdd, 0x8e, 0xc5, 0x8e, 0xe5, 0x8e, 0xed, 0x8e, 0xd5, 0x81, 0xe2, 0xff, + 0x00, 0x00, 0x00, 0x52, 0x68, 0x45, 0x48, 0x00, 0x00, 0x68, 0xb0, 0x0c, 0x07, 0x00, 0xe8, 0x5d, + 0x82, 0x06, 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, 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, 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, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa, + 0xfc, 0x30, 0xc0, 0xbf, 0xab, 0x0c, 0x07, 0x00, 0xb9, 0xab, 0x0c, 0x07, 0x00, 0x81, 0xe9, 0xab, + 0x0c, 0x07, 0x00, 0xf3, 0xaa, 0xe9, 0x00, 0x00, 0x00, 0x00, 0x50, 0x8b, 0x44, 0x24, 0x08, 0x8b, + 0x4c, 0x24, 0x0c, 0x89, 0xe2, 0xc7, 0x02, 0x00, 0x10, 0x06, 0x00, 0x51, 0x50, 0x52, 0x68, 0x00, + 0xf0, 0x00, 0x00, 0xe8, 0x85, 0x00, 0x00, 0x00, 0x83, 0xc4, 0x10, 0x85, 0xc0, 0x74, 0x21, 0xb8, + 0xed, 0xff, 0xff, 0xff, 0x0f, 0xb6, 0x88, 0x93, 0x0b, 0x07, 0x00, 0x81, 0xc9, 0x00, 0x4f, 0x00, + 0x00, 0x66, 0x89, 0x8c, 0x00, 0x26, 0x80, 0x0b, 0x00, 0x40, 0x75, 0xe8, 0xfa, 0xf4, 0xeb, 0xfc, + 0x8b, 0x44, 0x24, 0x14, 0x0f, 0xb6, 0x4c, 0x24, 0x10, 0xbc, 0x00, 0xf0, 0x00, 0x00, 0x31, 0xed, + 0x50, 0x51, 0x6a, 0x00, 0x68, 0x00, 0xf0, 0x00, 0x00, 0xc3, 0x57, 0x56, 0x8b, 0x4c, 0x24, 0x10, + 0x85, 0xc9, 0x74, 0x34, 0x8b, 0x54, 0x24, 0x0c, 0x31, 0xc0, 0x48, 0x0f, 0xb6, 0x32, 0x31, 0xc6, + 0x89, 0xf0, 0x83, 0xe0, 0x0f, 0xc1, 0xee, 0x04, 0x33, 0x34, 0x85, 0x94, 0x0b, 0x07, 0x00, 0x89, + 0xf7, 0x83, 0xe7, 0x0f, 0xc1, 0xee, 0x04, 0x89, 0xf0, 0x33, 0x04, 0xbd, 0x94, 0x0b, 0x07, 0x00, + 0x42, 0x49, 0x75, 0xd7, 0xf7, 0xd0, 0xeb, 0x02, 0x31, 0xc0, 0x5e, 0x5f, 0xc3, 0x55, 0x53, 0x57, + 0x56, 0x8b, 0x7c, 0x24, 0x20, 0x83, 0xff, 0x12, 0x0f, 0x82, 0x03, 0x01, 0x00, 0x00, 0x8b, 0x74, + 0x24, 0x1c, 0x80, 0x3e, 0x1f, 0x0f, 0x85, 0xf6, 0x00, 0x00, 0x00, 0x80, 0x7e, 0x01, 0x8b, 0x0f, + 0x85, 0xec, 0x00, 0x00, 0x00, 0x80, 0x7e, 0x02, 0x08, 0x0f, 0x85, 0xe2, 0x00, 0x00, 0x00, 0x0f, + 0xb6, 0x46, 0x03, 0x83, 0xf8, 0x1f, 0x0f, 0x87, 0xd5, 0x00, 0x00, 0x00, 0x8d, 0x4e, 0x0a, 0xa8, + 0x04, 0x74, 0x12, 0x0f, 0xb7, 0x11, 0x8d, 0x5f, 0xf4, 0x39, 0xd3, 0x0f, 0x82, 0xc0, 0x00, 0x00, + 0x00, 0x8d, 0x4c, 0x11, 0x02, 0xa8, 0x08, 0x75, 0x04, 0x89, 0xca, 0xeb, 0x17, 0x89, 0xcb, 0x29, + 0xf3, 0x39, 0xfb, 0x0f, 0x83, 0xa8, 0x00, 0x00, 0x00, 0x8d, 0x51, 0x01, 0x43, 0x80, 0x39, 0x00, + 0x89, 0xd1, 0x75, 0xed, 0x3c, 0x10, 0x73, 0x04, 0x89, 0xd3, 0xeb, 0x17, 0x89, 0xd1, 0x29, 0xf1, + 0x39, 0xf9, 0x0f, 0x83, 0x89, 0x00, 0x00, 0x00, 0x8d, 0x5a, 0x01, 0x41, 0x80, 0x3a, 0x00, 0x89, + 0xda, 0x75, 0xed, 0xa8, 0x02, 0x75, 0x58, 0x8b, 0x4c, 0x24, 0x18, 0x8b, 0x6c, 0x3e, 0xfc, 0xb8, + 0xfb, 0xff, 0xff, 0xff, 0x3b, 0x29, 0x77, 0x6e, 0x01, 0xfe, 0x89, 0xf0, 0x29, 0xd8, 0x83, 0xf8, + 0x08, 0x7c, 0x5e, 0x8b, 0x7c, 0x24, 0x14, 0x8b, 0x76, 0xf8, 0x83, 0xc0, 0xf8, 0x50, 0x53, 0x51, + 0x57, 0x89, 0xcb, 0xe8, 0x53, 0x00, 0x00, 0x00, 0x83, 0xc4, 0x10, 0x85, 0xc0, 0x75, 0x42, 0x39, + 0x2b, 0xb8, 0xfd, 0xff, 0xff, 0xff, 0x75, 0x3e, 0x55, 0x57, 0xe8, 0xdb, 0xfe, 0xff, 0xff, 0x83, + 0xc4, 0x08, 0x31, 0xc9, 0x39, 0xc6, 0x0f, 0x94, 0xc1, 0x8d, 0x44, 0x49, 0xfd, 0xeb, 0x27, 0x89, + 0xd8, 0x29, 0xf0, 0x8d, 0x4f, 0xfe, 0x39, 0xc8, 0x77, 0x17, 0x0f, 0xb7, 0x2b, 0x50, 0x56, 0xe8, + 0xb6, 0xfe, 0xff, 0xff, 0x83, 0xc4, 0x08, 0x66, 0x39, 0xc5, 0x75, 0x05, 0x83, 0xc3, 0x02, 0xeb, + 0x86, 0xb8, 0xfd, 0xff, 0xff, 0xff, 0x5e, 0x5f, 0x5b, 0x5d, 0xc3, 0x55, 0x53, 0x57, 0x56, 0x81, + 0xec, 0x3c, 0x06, 0x00, 0x00, 0x8b, 0x94, 0x24, 0x54, 0x06, 0x00, 0x00, 0x8b, 0x84, 0x24, 0x50, + 0x06, 0x00, 0x00, 0x8b, 0x8c, 0x24, 0x58, 0x06, 0x00, 0x00, 0x8d, 0x74, 0x24, 0x34, 0x89, 0x4e, + 0xe0, 0x03, 0x8c, 0x24, 0x5c, 0x06, 0x00, 0x00, 0x89, 0x4e, 0xe4, 0x31, 0xc9, 0x89, 0x4e, 0xe8, + 0x89, 0x4e, 0xec, 0x89, 0x4e, 0xf0, 0x89, 0x46, 0xf8, 0x89, 0x46, 0xf4, 0x03, 0x02, 0x89, 0x46, + 0xfc, 0x8b, 0x54, 0x24, 0x20, 0x85, 0xd2, 0x7e, 0x0a, 0x8b, 0x44, 0x24, 0x1c, 0x89, 0x44, 0x24, + 0x04, 0xeb, 0x4a, 0x8b, 0x74, 0x24, 0x14, 0x8b, 0x44, 0x24, 0x18, 0x8b, 0x4c, 0x24, 0x1c, 0x89, + 0x4c, 0x24, 0x04, 0x89, 0xd1, 0x39, 0xc6, 0x74, 0x1e, 0x8d, 0x56, 0x01, 0x89, 0x54, 0x24, 0x14, + 0x0f, 0xb6, 0x36, 0xd3, 0xe6, 0x8b, 0x7c, 0x24, 0x04, 0x09, 0xf7, 0x89, 0x7c, 0x24, 0x04, 0x89, + 0x7c, 0x24, 0x1c, 0x89, 0xd6, 0xeb, 0x08, 0xc7, 0x44, 0x24, 0x24, 0x01, 0x00, 0x00, 0x00, 0x8d, + 0x51, 0x08, 0x89, 0x54, 0x24, 0x20, 0x83, 0xf9, 0xf9, 0x89, 0xd1, 0x7c, 0xc8, 0x8b, 0x44, 0x24, + 0x04, 0xd1, 0xe8, 0x89, 0xc5, 0x89, 0x44, 0x24, 0x1c, 0x8d, 0x42, 0xff, 0x89, 0x44, 0x24, 0x20, + 0x83, 0xfa, 0x02, 0x77, 0x47, 0x8b, 0x4c, 0x24, 0x14, 0x8b, 0x74, 0x24, 0x18, 0x83, 0xc2, 0xf7, + 0x8d, 0x42, 0x08, 0x39, 0xf1, 0x74, 0x1c, 0x8d, 0x79, 0x01, 0x89, 0x7c, 0x24, 0x14, 0x0f, 0xb6, + 0x19, 0x89, 0xc1, 0xd3, 0xe3, 0x89, 0xe9, 0x09, 0xd9, 0x89, 0xcd, 0x89, 0x4c, 0x24, 0x1c, 0x89, + 0xf9, 0xeb, 0x08, 0xc7, 0x44, 0x24, 0x24, 0x01, 0x00, 0x00, 0x00, 0x83, 0xc2, 0x10, 0x89, 0x54, + 0x24, 0x20, 0x83, 0xf8, 0xfa, 0x89, 0xc2, 0x7c, 0xc7, 0x83, 0xc0, 0x08, 0x89, 0xe9, 0x83, 0xe1, + 0x03, 0xc1, 0xed, 0x02, 0x89, 0x6c, 0x24, 0x1c, 0x8d, 0x50, 0xfe, 0x89, 0x54, 0x24, 0x20, 0xff, + 0x24, 0x8d, 0xd4, 0x0b, 0x07, 0x00, 0x8b, 0x54, 0x24, 0x14, 0x8b, 0x4c, 0x24, 0x18, 0x89, 0xc8, + 0x29, 0xd0, 0x83, 0xf8, 0x04, 0x0f, 0x8c, 0x52, 0x05, 0x00, 0x00, 0x0f, 0xb7, 0x02, 0x0f, 0xb7, + 0x72, 0x02, 0x66, 0x31, 0xc6, 0x66, 0x83, 0xfe, 0xff, 0x0f, 0x85, 0x3e, 0x05, 0x00, 0x00, 0x83, + 0xc2, 0x04, 0x89, 0x54, 0x24, 0x14, 0x29, 0xd1, 0x39, 0xc1, 0x0f, 0x82, 0x2d, 0x05, 0x00, 0x00, + 0x8b, 0x4c, 0x24, 0x30, 0x2b, 0x4c, 0x24, 0x2c, 0x39, 0xc1, 0x0f, 0x82, 0x58, 0x05, 0x00, 0x00, + 0x85, 0xc0, 0x74, 0x1d, 0x8b, 0x4c, 0x24, 0x14, 0x8b, 0x54, 0x24, 0x2c, 0x8d, 0x71, 0x01, 0x8d, + 0x7a, 0x01, 0x48, 0x89, 0x74, 0x24, 0x14, 0x8a, 0x09, 0x89, 0x7c, 0x24, 0x2c, 0x88, 0x0a, 0x75, + 0xe3, 0x31, 0xc0, 0x89, 0x44, 0x24, 0x1c, 0x89, 0x44, 0x24, 0x20, 0xe9, 0xd8, 0x00, 0x00, 0x00, + 0xb8, 0xe0, 0xff, 0xff, 0xff, 0x66, 0xc7, 0x44, 0x04, 0x54, 0x00, 0x00, 0x83, 0xc0, 0x02, 0x75, + 0xf4, 0xc7, 0x44, 0x24, 0x42, 0x18, 0x00, 0x98, 0x00, 0x66, 0xc7, 0x44, 0x24, 0x46, 0x70, 0x00, + 0xb8, 0xe8, 0xff, 0xff, 0xff, 0x8d, 0x88, 0x18, 0x01, 0x00, 0x00, 0x66, 0x89, 0x8c, 0x44, 0x84, + 0x00, 0x00, 0x00, 0x40, 0x75, 0xef, 0x31, 0xc0, 0x66, 0x89, 0x84, 0x44, 0x84, 0x00, 0x00, 0x00, + 0x40, 0x3d, 0x90, 0x00, 0x00, 0x00, 0x75, 0xf0, 0xb8, 0xf8, 0xff, 0xff, 0xff, 0x8d, 0x88, 0x20, + 0x01, 0x00, 0x00, 0x66, 0x89, 0x8c, 0x44, 0xb4, 0x01, 0x00, 0x00, 0x40, 0x75, 0xef, 0xb8, 0x90, + 0xff, 0xff, 0xff, 0x8d, 0x88, 0x00, 0x01, 0x00, 0x00, 0x66, 0x89, 0x8c, 0x44, 0x94, 0x02, 0x00, + 0x00, 0x40, 0x75, 0xef, 0xc7, 0x84, 0x24, 0x94, 0x02, 0x00, 0x00, 0x1d, 0x01, 0x00, 0x00, 0xb8, + 0xe0, 0xff, 0xff, 0xff, 0x66, 0xc7, 0x84, 0x04, 0xb8, 0x02, 0x00, 0x00, 0x00, 0x00, 0x83, 0xc0, + 0x02, 0x75, 0xf1, 0x66, 0xc7, 0x84, 0x24, 0xa2, 0x02, 0x00, 0x00, 0x20, 0x00, 0x31, 0xc0, 0x66, + 0x89, 0x84, 0x44, 0xb8, 0x02, 0x00, 0x00, 0x40, 0x83, 0xf8, 0x20, 0x75, 0xf2, 0xc7, 0x84, 0x24, + 0xf8, 0x04, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x8d, 0x4c, 0x24, 0x14, 0x8d, 0x54, 0x24, 0x34, + 0x8d, 0x84, 0x24, 0x98, 0x02, 0x00, 0x00, 0x50, 0xe8, 0xb9, 0x04, 0x00, 0x00, 0x83, 0xc4, 0x04, + 0x85, 0xc0, 0x0f, 0x85, 0x45, 0x04, 0x00, 0x00, 0xf6, 0x44, 0x24, 0x04, 0x01, 0x0f, 0x84, 0xce, + 0xfd, 0xff, 0xff, 0xe9, 0x0c, 0x04, 0x00, 0x00, 0x83, 0xf8, 0x06, 0x77, 0x43, 0x8b, 0x4c, 0x24, + 0x14, 0x8b, 0x74, 0x24, 0x18, 0x83, 0xc0, 0xf6, 0x8d, 0x50, 0x08, 0x39, 0xf1, 0x74, 0x18, 0x8d, + 0x79, 0x01, 0x89, 0x7c, 0x24, 0x14, 0x0f, 0xb6, 0x19, 0x89, 0xd1, 0xd3, 0xe3, 0x09, 0xdd, 0x89, + 0x6c, 0x24, 0x1c, 0x89, 0xf9, 0xeb, 0x08, 0xc7, 0x44, 0x24, 0x24, 0x01, 0x00, 0x00, 0x00, 0x83, + 0xc0, 0x10, 0x89, 0x44, 0x24, 0x20, 0x83, 0xfa, 0xfd, 0x89, 0xd0, 0x7c, 0xcb, 0x83, 0xc2, 0x08, + 0x89, 0xe9, 0xc1, 0xe9, 0x05, 0x89, 0x4c, 0x24, 0x1c, 0x8d, 0x5a, 0xfb, 0x89, 0x5c, 0x24, 0x20, + 0x83, 0xfa, 0x09, 0x77, 0x53, 0x89, 0x6c, 0x24, 0x0c, 0x89, 0xcd, 0x8b, 0x4c, 0x24, 0x14, 0x8b, + 0x74, 0x24, 0x18, 0x83, 0xc2, 0xf3, 0x8d, 0x5a, 0x08, 0x39, 0xf1, 0x74, 0x1c, 0x8d, 0x41, 0x01, + 0x89, 0x44, 0x24, 0x14, 0x0f, 0xb6, 0x39, 0x89, 0xd9, 0xd3, 0xe7, 0x89, 0xe9, 0x09, 0xf9, 0x89, + 0xcd, 0x89, 0x4c, 0x24, 0x1c, 0x89, 0xc1, 0xeb, 0x08, 0xc7, 0x44, 0x24, 0x24, 0x01, 0x00, 0x00, + 0x00, 0x83, 0xc2, 0x10, 0x89, 0x54, 0x24, 0x20, 0x83, 0xfb, 0xfd, 0x89, 0xda, 0x7c, 0xc7, 0x83, + 0xc3, 0x08, 0x89, 0xe9, 0x8b, 0x6c, 0x24, 0x0c, 0x89, 0xc8, 0xc1, 0xe8, 0x05, 0x89, 0x04, 0x24, + 0x89, 0x44, 0x24, 0x1c, 0x8d, 0x43, 0xfb, 0x89, 0x44, 0x24, 0x20, 0x83, 0xfb, 0x08, 0x77, 0x51, + 0x89, 0x4c, 0x24, 0x08, 0x8b, 0x7c, 0x24, 0x14, 0x8b, 0x74, 0x24, 0x18, 0x83, 0xc3, 0xf3, 0x8d, + 0x43, 0x08, 0x39, 0xf7, 0x74, 0x1e, 0x8d, 0x57, 0x01, 0x89, 0x54, 0x24, 0x14, 0x0f, 0xb6, 0x3f, + 0x89, 0xc1, 0xd3, 0xe7, 0x8b, 0x0c, 0x24, 0x09, 0xf9, 0x89, 0x0c, 0x24, 0x89, 0x4c, 0x24, 0x1c, + 0x89, 0xd7, 0xeb, 0x08, 0xc7, 0x44, 0x24, 0x24, 0x01, 0x00, 0x00, 0x00, 0x83, 0xc3, 0x10, 0x89, + 0x5c, 0x24, 0x20, 0x83, 0xf8, 0xfc, 0x89, 0xc3, 0x7c, 0xc5, 0x83, 0xc0, 0x08, 0x8b, 0x4c, 0x24, + 0x08, 0x83, 0xe5, 0x1f, 0x8b, 0x14, 0x24, 0xc1, 0xea, 0x04, 0x89, 0x54, 0x24, 0x1c, 0x83, 0xc0, + 0xfc, 0x89, 0x44, 0x24, 0x20, 0x83, 0xfd, 0x1d, 0xc7, 0x44, 0x24, 0x10, 0xfd, 0xff, 0xff, 0xff, + 0x0f, 0x87, 0xf3, 0x02, 0x00, 0x00, 0x83, 0xe1, 0x1f, 0x83, 0xf9, 0x1d, 0x0f, 0x87, 0xe7, 0x02, + 0x00, 0x00, 0x81, 0xc5, 0x01, 0x01, 0x00, 0x00, 0x89, 0x6c, 0x24, 0x0c, 0x41, 0x89, 0x4c, 0x24, + 0x08, 0x83, 0x24, 0x24, 0x0f, 0xb9, 0xed, 0xff, 0xff, 0xff, 0xc6, 0x84, 0x0c, 0x0f, 0x05, 0x00, + 0x00, 0x00, 0x41, 0x75, 0xf5, 0x83, 0x04, 0x24, 0x03, 0x8b, 0x5c, 0x24, 0x14, 0x8b, 0x74, 0x24, + 0x18, 0x31, 0xff, 0x83, 0xf8, 0x02, 0x7f, 0x37, 0x89, 0xdd, 0x39, 0xf5, 0x74, 0x19, 0x8d, 0x5d, + 0x01, 0x89, 0x5c, 0x24, 0x14, 0x0f, 0xb6, 0x6d, 0x00, 0x89, 0xc1, 0xd3, 0xe5, 0x09, 0xea, 0x89, + 0x54, 0x24, 0x1c, 0x89, 0xdd, 0xeb, 0x08, 0xc7, 0x44, 0x24, 0x24, 0x01, 0x00, 0x00, 0x00, 0x8d, + 0x48, 0x08, 0x89, 0x4c, 0x24, 0x20, 0x83, 0xf8, 0xfb, 0x89, 0xc8, 0x7c, 0xcd, 0xeb, 0x02, 0x89, + 0xc1, 0x89, 0xd0, 0xc1, 0xe8, 0x03, 0x89, 0x44, 0x24, 0x1c, 0x83, 0xc1, 0xfd, 0x89, 0x4c, 0x24, + 0x20, 0x80, 0xe2, 0x07, 0x0f, 0xb6, 0xaf, 0x98, 0x0c, 0x07, 0x00, 0x88, 0x94, 0x2c, 0xfc, 0x04, + 0x00, 0x00, 0x3b, 0x3c, 0x24, 0x8d, 0x7f, 0x01, 0x89, 0xc2, 0x89, 0xc8, 0x75, 0x95, 0x8d, 0x4c, + 0x24, 0x34, 0x8d, 0x94, 0x24, 0xfc, 0x04, 0x00, 0x00, 0x6a, 0x13, 0xe8, 0x57, 0x04, 0x00, 0x00, + 0x83, 0xc4, 0x04, 0x85, 0xc0, 0x0f, 0x85, 0x2a, 0x02, 0x00, 0x00, 0x83, 0xbc, 0x24, 0x94, 0x02, + 0x00, 0x00, 0xff, 0x0f, 0x84, 0x20, 0x02, 0x00, 0x00, 0x8b, 0x44, 0x24, 0x0c, 0x8b, 0x4c, 0x24, + 0x08, 0x8d, 0x34, 0x01, 0x31, 0xed, 0x8d, 0x4c, 0x24, 0x14, 0x8d, 0x54, 0x24, 0x34, 0xe8, 0xd0, + 0x03, 0x00, 0x00, 0x3b, 0x84, 0x24, 0x94, 0x02, 0x00, 0x00, 0x0f, 0x8f, 0xf9, 0x01, 0x00, 0x00, + 0x83, 0xf8, 0x12, 0x0f, 0x84, 0xb3, 0x00, 0x00, 0x00, 0x83, 0xf8, 0x11, 0x74, 0x61, 0x83, 0xf8, + 0x10, 0x0f, 0x85, 0xee, 0x00, 0x00, 0x00, 0x85, 0xed, 0x0f, 0x84, 0xda, 0x01, 0x00, 0x00, 0x8b, + 0x7c, 0x24, 0x20, 0x83, 0xff, 0x02, 0x0f, 0x8d, 0x18, 0x01, 0x00, 0x00, 0x8b, 0x5c, 0x24, 0x14, + 0x8b, 0x44, 0x24, 0x18, 0x8b, 0x54, 0x24, 0x1c, 0x89, 0xf9, 0x39, 0xc3, 0x74, 0x16, 0x8d, 0x7b, + 0x01, 0x89, 0x7c, 0x24, 0x14, 0x0f, 0xb6, 0x1b, 0xd3, 0xe3, 0x09, 0xda, 0x89, 0x54, 0x24, 0x1c, + 0x89, 0xfb, 0xeb, 0x08, 0xc7, 0x44, 0x24, 0x24, 0x01, 0x00, 0x00, 0x00, 0x8d, 0x79, 0x08, 0x89, + 0x7c, 0x24, 0x20, 0x83, 0xf9, 0xfa, 0x89, 0xf9, 0x7c, 0xd0, 0xe9, 0xd9, 0x00, 0x00, 0x00, 0x8b, + 0x7c, 0x24, 0x20, 0x83, 0xff, 0x03, 0x0f, 0x8d, 0x8e, 0x00, 0x00, 0x00, 0x8b, 0x5c, 0x24, 0x14, + 0x8b, 0x54, 0x24, 0x18, 0x8b, 0x44, 0x24, 0x1c, 0x89, 0xf9, 0x39, 0xd3, 0x74, 0x16, 0x8d, 0x7b, + 0x01, 0x89, 0x7c, 0x24, 0x14, 0x0f, 0xb6, 0x1b, 0xd3, 0xe3, 0x09, 0xd8, 0x89, 0x44, 0x24, 0x1c, + 0x89, 0xfb, 0xeb, 0x08, 0xc7, 0x44, 0x24, 0x24, 0x01, 0x00, 0x00, 0x00, 0x8d, 0x79, 0x08, 0x89, + 0x7c, 0x24, 0x20, 0x83, 0xf9, 0xfb, 0x89, 0xf9, 0x7c, 0xd0, 0xeb, 0x52, 0x8b, 0x7c, 0x24, 0x20, + 0x83, 0xff, 0x07, 0x7d, 0x61, 0x8b, 0x5c, 0x24, 0x14, 0x8b, 0x54, 0x24, 0x18, 0x8b, 0x44, 0x24, + 0x1c, 0x89, 0xf9, 0x39, 0xd3, 0x74, 0x16, 0x8d, 0x7b, 0x01, 0x89, 0x7c, 0x24, 0x14, 0x0f, 0xb6, + 0x1b, 0xd3, 0xe3, 0x09, 0xd8, 0x89, 0x44, 0x24, 0x1c, 0x89, 0xfb, 0xeb, 0x08, 0xc7, 0x44, 0x24, + 0x24, 0x01, 0x00, 0x00, 0x00, 0x8d, 0x79, 0x08, 0x89, 0x7c, 0x24, 0x20, 0x83, 0xf9, 0xff, 0x89, + 0xf9, 0x7c, 0xd0, 0xeb, 0x25, 0x31, 0xc9, 0x41, 0xeb, 0x5b, 0x8b, 0x44, 0x24, 0x1c, 0x89, 0xc1, + 0x83, 0xe1, 0x07, 0xc1, 0xe8, 0x03, 0x89, 0x44, 0x24, 0x1c, 0x83, 0xc7, 0xfd, 0x89, 0x7c, 0x24, + 0x20, 0x83, 0xc1, 0x03, 0xeb, 0x1a, 0x8b, 0x44, 0x24, 0x1c, 0x89, 0xc1, 0x83, 0xe1, 0x7f, 0xc1, + 0xe8, 0x07, 0x89, 0x44, 0x24, 0x1c, 0x83, 0xc7, 0xf9, 0x89, 0x7c, 0x24, 0x20, 0x83, 0xc1, 0x0b, + 0x31, 0xc0, 0xeb, 0x21, 0x8b, 0x54, 0x24, 0x1c, 0x8a, 0x84, 0x2c, 0xfb, 0x04, 0x00, 0x00, 0x89, + 0xd1, 0x83, 0xe1, 0x03, 0xc1, 0xea, 0x02, 0x89, 0x54, 0x24, 0x1c, 0x83, 0xc7, 0xfe, 0x89, 0x7c, + 0x24, 0x20, 0x83, 0xc1, 0x03, 0x89, 0xf2, 0x29, 0xea, 0x39, 0xd1, 0x0f, 0x87, 0x88, 0x00, 0x00, + 0x00, 0x88, 0x84, 0x2c, 0xfc, 0x04, 0x00, 0x00, 0x45, 0x49, 0x75, 0xf5, 0x39, 0xf5, 0x0f, 0x82, + 0x62, 0xfe, 0xff, 0xff, 0x80, 0xbc, 0x24, 0xfc, 0x05, 0x00, 0x00, 0x00, 0x74, 0x6b, 0x8d, 0x4c, + 0x24, 0x34, 0x8d, 0x94, 0x24, 0xfc, 0x04, 0x00, 0x00, 0x8b, 0x74, 0x24, 0x0c, 0x56, 0xe8, 0x74, + 0x02, 0x00, 0x00, 0x83, 0xc4, 0x04, 0x85, 0xc0, 0x75, 0x4b, 0x8d, 0x94, 0x34, 0xfc, 0x04, 0x00, + 0x00, 0x8d, 0x8c, 0x24, 0x98, 0x02, 0x00, 0x00, 0xff, 0x74, 0x24, 0x08, 0xe8, 0x56, 0x02, 0x00, + 0x00, 0x83, 0xc4, 0x04, 0x85, 0xc0, 0x75, 0x35, 0xe9, 0xcb, 0xfb, 0xff, 0xff, 0xb8, 0xfd, 0xff, + 0xff, 0xff, 0xeb, 0x29, 0x83, 0x7c, 0x24, 0x24, 0x00, 0xb8, 0xfd, 0xff, 0xff, 0xff, 0x75, 0x1d, + 0x8b, 0x44, 0x24, 0x2c, 0x2b, 0x44, 0x24, 0x28, 0x8b, 0x8c, 0x24, 0x54, 0x06, 0x00, 0x00, 0x89, + 0x01, 0x31, 0xc0, 0xeb, 0x08, 0x89, 0x44, 0x24, 0x10, 0x8b, 0x44, 0x24, 0x10, 0x81, 0xc4, 0x3c, + 0x06, 0x00, 0x00, 0x5e, 0x5f, 0x5b, 0x5d, 0xc3, 0xb8, 0xfb, 0xff, 0xff, 0xff, 0xeb, 0xee, 0x55, + 0x53, 0x57, 0x56, 0x89, 0xce, 0x8b, 0x59, 0x0c, 0x39, 0xd3, 0x7d, 0x2d, 0x8b, 0x0e, 0x8b, 0x46, + 0x04, 0x39, 0xc1, 0x74, 0x13, 0x8d, 0x79, 0x01, 0x89, 0x3e, 0x0f, 0xb6, 0x29, 0x89, 0xd9, 0xd3, + 0xe5, 0x09, 0x6e, 0x08, 0x89, 0xf9, 0xeb, 0x07, 0xc7, 0x46, 0x10, 0x01, 0x00, 0x00, 0x00, 0x83, + 0xc3, 0x08, 0x89, 0x5e, 0x0c, 0x39, 0xd3, 0x7c, 0xd8, 0x8b, 0x7e, 0x08, 0x31, 0xc0, 0x48, 0x89, + 0xd1, 0xd3, 0xe0, 0xf7, 0xd0, 0x21, 0xf8, 0xd3, 0xef, 0x89, 0x7e, 0x08, 0x29, 0xd3, 0x89, 0x5e, + 0x0c, 0x5e, 0x5f, 0x5b, 0x5d, 0xc3, 0x55, 0x53, 0x57, 0x56, 0x83, 0xec, 0x08, 0x89, 0xd5, 0x89, + 0xcf, 0xe8, 0x4d, 0x01, 0x00, 0x00, 0xbb, 0xfd, 0xff, 0xff, 0xff, 0x83, 0x7f, 0x10, 0x00, 0x74, + 0x0a, 0x89, 0xd8, 0x83, 0xc4, 0x08, 0x5e, 0x5f, 0x5b, 0x5d, 0xc3, 0x89, 0x2c, 0x24, 0x3d, 0xff, + 0x00, 0x00, 0x00, 0x77, 0x19, 0x8b, 0x4f, 0x18, 0x3b, 0x4f, 0x1c, 0x0f, 0x84, 0x07, 0x01, 0x00, + 0x00, 0x8d, 0x51, 0x01, 0x89, 0x57, 0x18, 0x88, 0x01, 0xe9, 0xe2, 0x00, 0x00, 0x00, 0x3d, 0x00, + 0x01, 0x00, 0x00, 0x0f, 0x84, 0xf9, 0x00, 0x00, 0x00, 0x3b, 0x85, 0x60, 0x02, 0x00, 0x00, 0x7f, + 0xc0, 0x3d, 0x1d, 0x01, 0x00, 0x00, 0x77, 0xb9, 0x8b, 0x4c, 0x24, 0x1c, 0x83, 0xb9, 0x60, 0x02, + 0x00, 0x00, 0xff, 0x74, 0xac, 0x0f, 0xb7, 0x8c, 0x00, 0x00, 0x0a, 0x07, 0x00, 0x89, 0x4c, 0x24, + 0x04, 0x05, 0xff, 0xfe, 0xff, 0xff, 0x31, 0xf6, 0xb9, 0xff, 0x00, 0x00, 0x10, 0x0f, 0xa3, 0xc1, + 0x72, 0x10, 0x0f, 0xb6, 0x90, 0xe4, 0x0b, 0x07, 0x00, 0x89, 0xf9, 0xe8, 0x0f, 0xff, 0xff, 0xff, + 0x89, 0xc6, 0x89, 0xf9, 0x8b, 0x5c, 0x24, 0x1c, 0x89, 0xda, 0xe8, 0xb4, 0x00, 0x00, 0x00, 0x3b, + 0x83, 0x60, 0x02, 0x00, 0x00, 0x0f, 0x8f, 0x9e, 0x00, 0x00, 0x00, 0x89, 0xc1, 0x83, 0xf8, 0x1d, + 0xbb, 0xfd, 0xff, 0xff, 0xff, 0x0f, 0x87, 0x56, 0xff, 0xff, 0xff, 0x0f, 0xb7, 0xac, 0x09, 0x5c, + 0x0c, 0x07, 0x00, 0x31, 0xc0, 0x83, 0xf9, 0x04, 0x72, 0x0e, 0x0f, 0xb6, 0x91, 0x3e, 0x0c, 0x07, + 0x00, 0x89, 0xf9, 0xe8, 0xc7, 0xfe, 0xff, 0xff, 0x01, 0xe8, 0x8b, 0x4f, 0x18, 0x89, 0xca, 0x2b, + 0x57, 0x14, 0x39, 0xd0, 0x0f, 0x8f, 0x27, 0xff, 0xff, 0xff, 0x03, 0x74, 0x24, 0x04, 0x8b, 0x57, + 0x1c, 0x29, 0xca, 0x39, 0xf2, 0x7c, 0x41, 0x85, 0xf6, 0x7e, 0x1d, 0xf7, 0xd8, 0x31, 0xc9, 0x8b, + 0x57, 0x18, 0x8d, 0x2c, 0x0a, 0x8a, 0x1c, 0x28, 0x88, 0x1c, 0x0a, 0x41, 0x39, 0xce, 0x75, 0xef, + 0x8b, 0x4f, 0x18, 0xbb, 0xfd, 0xff, 0xff, 0xff, 0x01, 0xf1, 0x89, 0x4f, 0x18, 0x8b, 0x2c, 0x24, + 0x89, 0xf9, 0x89, 0xea, 0xe8, 0x2a, 0x00, 0x00, 0x00, 0x83, 0x7f, 0x10, 0x00, 0x0f, 0x84, 0xeb, + 0xfe, 0xff, 0xff, 0xe9, 0xd9, 0xfe, 0xff, 0xff, 0xbb, 0xfb, 0xff, 0xff, 0xff, 0xe9, 0xcf, 0xfe, + 0xff, 0xff, 0x31, 0xdb, 0xe9, 0xc8, 0xfe, 0xff, 0xff, 0xbb, 0xfd, 0xff, 0xff, 0xff, 0xe9, 0xbe, + 0xfe, 0xff, 0xff, 0x55, 0x53, 0x57, 0x56, 0x50, 0x89, 0xd5, 0x89, 0xcb, 0x31, 0xd2, 0x42, 0xe8, + 0x3b, 0xfe, 0xff, 0xff, 0x89, 0xc7, 0x0f, 0xb7, 0x45, 0x02, 0x31, 0xf6, 0x39, 0xc7, 0x89, 0x2c, + 0x24, 0x72, 0x21, 0x83, 0xc5, 0x04, 0x31, 0xf6, 0x01, 0xc6, 0x29, 0xc7, 0x89, 0xd9, 0x31, 0xd2, + 0x42, 0xe8, 0x19, 0xfe, 0xff, 0xff, 0x8d, 0x3c, 0x78, 0x0f, 0xb7, 0x45, 0x00, 0x83, 0xc5, 0x02, + 0x39, 0xc7, 0x7d, 0xe4, 0x8b, 0x04, 0x24, 0x8d, 0x04, 0x70, 0x0f, 0xb7, 0x44, 0x78, 0x20, 0x83, + 0xc4, 0x04, 0x5e, 0x5f, 0x5b, 0x5d, 0xc3, 0x55, 0x53, 0x57, 0x56, 0x83, 0xec, 0x24, 0x8b, 0x7c, + 0x24, 0x38, 0xb8, 0xe0, 0xff, 0xff, 0xff, 0x66, 0xc7, 0x44, 0x01, 0x20, 0x00, 0x00, 0x83, 0xc0, + 0x02, 0x75, 0xf4, 0xc7, 0x81, 0x60, 0x02, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x85, 0xff, 0x74, + 0x1b, 0x31, 0xc0, 0x80, 0x3c, 0x02, 0x00, 0x74, 0x0e, 0x89, 0x81, 0x60, 0x02, 0x00, 0x00, 0x0f, + 0xb6, 0x34, 0x02, 0x66, 0xff, 0x04, 0x71, 0x40, 0x39, 0xc7, 0x75, 0xe7, 0x31, 0xff, 0x31, 0xdb, + 0x43, 0xbd, 0xe0, 0xff, 0xff, 0xff, 0xb8, 0xfd, 0xff, 0xff, 0xff, 0x0f, 0xb7, 0x74, 0x29, 0x20, + 0x29, 0xf3, 0x72, 0x72, 0x01, 0xdb, 0x66, 0x89, 0x7c, 0x2c, 0x24, 0x01, 0xf7, 0x83, 0xc5, 0x02, + 0x75, 0xe9, 0x83, 0xff, 0x02, 0x0f, 0x93, 0x44, 0x24, 0x03, 0x85, 0xdb, 0x0f, 0x95, 0xc3, 0x84, + 0x5c, 0x24, 0x03, 0x75, 0x51, 0x83, 0xff, 0x01, 0x75, 0x07, 0x66, 0x83, 0x79, 0x02, 0x01, 0x75, + 0x45, 0x8b, 0x5c, 0x24, 0x38, 0x85, 0xdb, 0x74, 0x25, 0x31, 0xc0, 0x0f, 0xb6, 0x34, 0x02, 0x85, + 0xf6, 0x74, 0x16, 0x0f, 0xb7, 0x5c, 0x74, 0x04, 0x8d, 0x6b, 0x01, 0x66, 0x89, 0x6c, 0x74, 0x04, + 0x66, 0x89, 0x44, 0x59, 0x20, 0x8b, 0x5c, 0x24, 0x38, 0x40, 0x39, 0xc3, 0x75, 0xdd, 0x31, 0xc0, + 0x83, 0xff, 0x01, 0x75, 0x11, 0x66, 0xc7, 0x41, 0x02, 0x02, 0x00, 0x8b, 0x91, 0x60, 0x02, 0x00, + 0x00, 0x42, 0x66, 0x89, 0x51, 0x22, 0x83, 0xc4, 0x24, 0x5e, 0x5f, 0x5b, 0x5d, 0xc3, 0x00, 0x00, + 0x4c, 0x69, 0x6d, 0x69, 0x6e, 0x65, 0x20, 0x64, 0x65, 0x63, 0x6f, 0x6d, 0x70, 0x20, 0x65, 0x72, + 0x72, 0x6f, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x10, 0xb7, 0x1d, 0xc8, 0x20, 0x6e, 0x3b, + 0xac, 0x30, 0xd9, 0x26, 0x90, 0x41, 0xdc, 0x76, 0xf4, 0x51, 0x6b, 0x6b, 0x58, 0x61, 0xb2, 0x4d, + 0x3c, 0x71, 0x05, 0x50, 0x20, 0x83, 0xb8, 0xed, 0x44, 0x93, 0x0f, 0xf0, 0xe8, 0xa3, 0xd6, 0xd6, + 0x8c, 0xb3, 0x61, 0xcb, 0xb0, 0xc2, 0x64, 0x9b, 0xd4, 0xd2, 0xd3, 0x86, 0x78, 0xe2, 0x0a, 0xa0, + 0x1c, 0xf2, 0xbd, 0xbd, 0xf6, 0x02, 0x07, 0x00, 0x70, 0x03, 0x07, 0x00, 0x58, 0x04, 0x07, 0x00, + 0x5d, 0x08, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, + 0x00, 0x7f, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08, 0x00, 0x09, 0x00, + 0x0a, 0x00, 0x0b, 0x00, 0x0d, 0x00, 0x0f, 0x00, 0x11, 0x00, 0x13, 0x00, 0x17, 0x00, 0x1b, 0x00, + 0x1f, 0x00, 0x23, 0x00, 0x2b, 0x00, 0x33, 0x00, 0x3b, 0x00, 0x43, 0x00, 0x53, 0x00, 0x63, 0x00, + 0x73, 0x00, 0x83, 0x00, 0xa3, 0x00, 0xc3, 0x00, 0xe3, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03, 0x04, 0x04, 0x05, 0x05, 0x06, 0x06, 0x07, 0x07, + 0x08, 0x08, 0x09, 0x09, 0x0a, 0x0a, 0x0b, 0x0b, 0x0c, 0x0c, 0x0d, 0x0d, 0x01, 0x00, 0x02, 0x00, + 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x07, 0x00, 0x09, 0x00, 0x0d, 0x00, 0x11, 0x00, 0x19, 0x00, + 0x21, 0x00, 0x31, 0x00, 0x41, 0x00, 0x61, 0x00, 0x81, 0x00, 0xc1, 0x00, 0x01, 0x01, 0x81, 0x01, + 0x01, 0x02, 0x01, 0x03, 0x01, 0x04, 0x01, 0x06, 0x01, 0x08, 0x01, 0x0c, 0x01, 0x10, 0x01, 0x18, + 0x01, 0x20, 0x01, 0x30, 0x01, 0x40, 0x01, 0x60, 0x10, 0x11, 0x12, 0x00, 0x08, 0x07, 0x09, 0x06, + 0x0a, 0x05, 0x0b, 0x04, 0x0c, 0x03, 0x0d, 0x02, 0x0e, 0x01, 0x0f, 0x90, 0x90, 0x90, 0x90, 0x90, + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x95, 0x7d, 0x0b, 0x78, 0x53, 0x55, + 0xb6, 0xf0, 0x39, 0x6d, 0x0a, 0x69, 0x09, 0x9c, 0x54, 0x0a, 0xb6, 0x52, 0x21, 0x20, 0x38, 0x30, + 0x20, 0x34, 0x3c, 0xb4, 0x01, 0x2a, 0x7d, 0x9d, 0xf2, 0x32, 0x25, 0x6d, 0x49, 0xea, 0x8c, 0x96, + 0x5a, 0x68, 0x62, 0x5a, 0x81, 0x76, 0xd2, 0x1c, 0x1e, 0x6a, 0x9c, 0x96, 0xd3, 0x5c, 0xbb, 0x7b, + 0x26, 0x5e, 0x7f, 0x95, 0x7b, 0xfd, 0x67, 0x74, 0x46, 0x47, 0xbd, 0xd7, 0x99, 0x3b, 0x8e, 0x38, + 0x33, 0xf2, 0x12, 0x21, 0x69, 0x99, 0xb6, 0x14, 0x84, 0xf2, 0x10, 0xca, 0x63, 0xa0, 0x68, 0xc7, + 0x39, 0x35, 0xbd, 0x63, 0xda, 0x32, 0x7d, 0x81, 0xcd, 0xbf, 0xd6, 0x3e, 0x49, 0x1f, 0x38, 0x33, + 0xf7, 0xbf, 0x7c, 0xa6, 0x39, 0x7b, 0xef, 0xb5, 0xf7, 0x5e, 0x7b, 0xbd, 0xf6, 0x5a, 0x7b, 0xaf, + 0x13, 0xef, 0x24, 0x79, 0x8f, 0xed, 0xfa, 0xb3, 0x8a, 0x39, 0xb4, 0xa6, 0x2a, 0x8a, 0xa9, 0xea, + 0xc0, 0xc7, 0x9e, 0x5f, 0x73, 0xec, 0x94, 0xff, 0x0a, 0x30, 0xcc, 0xd7, 0x0f, 0xc0, 0x9f, 0x78, + 0xe6, 0xa0, 0x8e, 0x61, 0x98, 0x97, 0x5a, 0x5f, 0xf2, 0xbe, 0xd4, 0xf6, 0x92, 0xfc, 0x52, 0x4b, + 0xc7, 0x7f, 0x6b, 0x18, 0xe6, 0x54, 0xf8, 0x9f, 0x99, 0xfc, 0xd9, 0x22, 0x76, 0x8e, 0x23, 0x17, + 0x6d, 0x8d, 0x7c, 0x6f, 0x30, 0xb2, 0x91, 0xef, 0x07, 0x60, 0xc6, 0xc3, 0xf7, 0x92, 0xe6, 0xc1, + 0x3b, 0x47, 0x98, 0xe7, 0x19, 0xe6, 0x18, 0xfe, 0x39, 0xc4, 0x44, 0x30, 0x4c, 0xcf, 0xbb, 0x1c, + 0x1b, 0x5f, 0xaa, 0xb6, 0xef, 0x86, 0x61, 0x4f, 0x1e, 0xd4, 0x8e, 0x1a, 0x93, 0xd3, 0x79, 0x67, + 0x0f, 0x71, 0xb3, 0xbc, 0xb6, 0x83, 0xaf, 0x43, 0x5b, 0x29, 0x63, 0x3a, 0xa9, 0xf7, 0x8e, 0xb4, + 0xde, 0x2e, 0x65, 0xec, 0xcc, 0xf3, 0x27, 0x57, 0x33, 0xf2, 0x26, 0x16, 0x47, 0x67, 0x82, 0xcc, + 0x82, 0xca, 0x28, 0x05, 0x07, 0x8e, 0xbd, 0x7f, 0x10, 0x51, 0x3d, 0x0d, 0x7f, 0xd4, 0xcc, 0xdd, + 0x83, 0x72, 0x87, 0x03, 0x0c, 0x0c, 0xfb, 0xf5, 0xd7, 0xd0, 0x3a, 0x66, 0xc4, 0x5b, 0xfe, 0x6f, + 0x83, 0x91, 0x38, 0x54, 0x6d, 0xe6, 0x6c, 0xd5, 0x2f, 0xc5, 0x2e, 0x86, 0x91, 0x32, 0x67, 0xab, + 0xdf, 0xb9, 0xa5, 0x3c, 0x68, 0xde, 0xe9, 0x87, 0x07, 0x8e, 0x8d, 0xba, 0x43, 0xbf, 0x26, 0xaa, + 0xba, 0xf1, 0xeb, 0x7e, 0x0d, 0x7c, 0xe5, 0x59, 0xf2, 0xcd, 0x5f, 0xaf, 0xe8, 0xfa, 0x7b, 0x93, + 0xd1, 0x15, 0x7c, 0x6d, 0xee, 0xa2, 0x53, 0xb5, 0x3c, 0x6c, 0x23, 0x0f, 0x06, 0xba, 0x1e, 0xb6, + 0x49, 0x0f, 0xf6, 0x77, 0x71, 0xbf, 0xe2, 0xde, 0x1e, 0x3f, 0xc3, 0xf6, 0xa6, 0xad, 0xc0, 0x56, + 0x68, 0xdb, 0x64, 0xfb, 0xa1, 0xed, 0x07, 0xb6, 0x27, 0x6c, 0x8f, 0x63, 0x5b, 0xa0, 0xeb, 0xf6, + 0x67, 0xcc, 0xe0, 0x08, 0xec, 0xad, 0xae, 0xa7, 0x6d, 0x9e, 0xe2, 0xd9, 0x73, 0x6d, 0x26, 0x5b, + 0x9e, 0x2d, 0xc7, 0x96, 0x6b, 0xb3, 0xd8, 0xf2, 0x6d, 0x66, 0xdb, 0x1b, 0xd3, 0xc7, 0x71, 0x6f, + 0x71, 0xef, 0x2b, 0x3d, 0x1e, 0xb6, 0x71, 0xec, 0xd4, 0x3b, 0xf4, 0x6b, 0xba, 0xaa, 0x1b, 0x26, + 0xd6, 0xb0, 0x38, 0xf1, 0xe9, 0xae, 0x78, 0xc6, 0x06, 0xbc, 0x1a, 0xc1, 0xa9, 0xa0, 0x70, 0xd3, + 0x13, 0xf5, 0x2f, 0x8f, 0xfd, 0xc7, 0xfc, 0x93, 0x7f, 0x0a, 0x45, 0xc2, 0xff, 0xde, 0x58, 0x68, + 0x0b, 0x8e, 0xbb, 0xa7, 0xfb, 0xcd, 0x85, 0xc1, 0x85, 0x53, 0xbb, 0xa5, 0x29, 0x28, 0x04, 0x64, + 0xca, 0x54, 0x20, 0x41, 0x63, 0x14, 0x3e, 0xdf, 0x07, 0x4f, 0xd2, 0xc6, 0xd9, 0xaa, 0xc6, 0xa8, + 0x7b, 0xba, 0x95, 0x0e, 0x40, 0xaf, 0xe4, 0x1e, 0x4a, 0xaf, 0x54, 0xfa, 0x75, 0xff, 0x9a, 0x9e, + 0x10, 0xbd, 0x9e, 0xe9, 0xfe, 0xc7, 0xf4, 0x72, 0x77, 0xdf, 0xc5, 0x9a, 0x86, 0x71, 0xd9, 0x3d, + 0x4c, 0xc3, 0xb8, 0x5c, 0xfc, 0x63, 0xe9, 0x61, 0x6c, 0x86, 0xa9, 0xf7, 0x74, 0x3b, 0x17, 0x22, + 0x31, 0xfe, 0xc0, 0x26, 0x79, 0x3f, 0x9b, 0x8a, 0xe4, 0x73, 0x76, 0xe8, 0xe1, 0xe9, 0x97, 0xb9, + 0x3d, 0x35, 0x0f, 0x5a, 0x7a, 0x0e, 0x32, 0x11, 0x9f, 0x4d, 0x7d, 0x5f, 0xe5, 0x8c, 0xc1, 0x9e, + 0xaa, 0x4a, 0xe8, 0xf9, 0xd4, 0x20, 0xa5, 0x51, 0x72, 0x0f, 0xa5, 0x51, 0x6a, 0x0f, 0xa7, 0xab, + 0xaf, 0x3c, 0x09, 0x44, 0xaa, 0xff, 0xba, 0xa7, 0x1b, 0x88, 0xf4, 0x09, 0x10, 0xe9, 0xea, 0x4b, + 0xf5, 0x2f, 0x7d, 0xf9, 0x92, 0xff, 0xa5, 0xf3, 0x48, 0x24, 0x89, 0xae, 0x8b, 0xd0, 0x35, 0x56, + 0xa6, 0xc0, 0xa4, 0x0c, 0xe3, 0x9c, 0x16, 0x5c, 0x06, 0x78, 0x30, 0xc1, 0x65, 0xb9, 0xf4, 0x2f, + 0x56, 0xca, 0xdf, 0x24, 0xb0, 0x8c, 0x78, 0x5c, 0x53, 0xaf, 0xf7, 0xd6, 0xff, 0x73, 0xda, 0xe1, + 0x3f, 0x45, 0x3f, 0x40, 0x9a, 0x54, 0xef, 0x30, 0xb7, 0x18, 0xa6, 0x1e, 0xc8, 0xa3, 0xba, 0x45, + 0xc9, 0xa3, 0xa1, 0x5f, 0xf7, 0xc7, 0xdd, 0x52, 0xc8, 0xe3, 0xd9, 0x3a, 0x3b, 0xee, 0xeb, 0x97, + 0x7a, 0xfe, 0x31, 0x89, 0xde, 0xef, 0x51, 0x44, 0x2a, 0xdc, 0x74, 0x3b, 0xb8, 0x43, 0x15, 0xdc, + 0xa1, 0x0e, 0xee, 0x60, 0x82, 0xd3, 0x99, 0x5b, 0xe2, 0xf1, 0x71, 0x83, 0x0b, 0x71, 0xb9, 0xaa, + 0x5b, 0xf8, 0x35, 0x5d, 0x73, 0x6b, 0x64, 0xb9, 0x5f, 0xf4, 0xdc, 0xbd, 0xdc, 0x39, 0xc1, 0x20, + 0xc3, 0x8c, 0x12, 0x8c, 0x7f, 0x2c, 0x07, 0xa0, 0xd9, 0x79, 0xf9, 0xa0, 0xdb, 0x1a, 0x49, 0x88, + 0xe3, 0x3e, 0xe5, 0xb5, 0x87, 0x56, 0x21, 0x8f, 0x33, 0x7d, 0x62, 0x60, 0x86, 0xe8, 0xd5, 0x71, + 0x9f, 0x5e, 0x14, 0xbb, 0x67, 0xb8, 0x7b, 0xb9, 0xcc, 0x16, 0xd2, 0x22, 0x99, 0xd5, 0xe4, 0x3c, + 0xf7, 0xe9, 0x39, 0x2e, 0xf3, 0x2c, 0x54, 0x8a, 0x75, 0x3a, 0x49, 0xd0, 0x70, 0x9f, 0x9e, 0x16, + 0xbb, 0x28, 0x40, 0x33, 0xa9, 0x23, 0xc6, 0xce, 0x79, 0xcd, 0xfa, 0x13, 0xe2, 0xe0, 0xaa, 0x63, + 0x54, 0x52, 0x5e, 0xfc, 0x39, 0xfc, 0x15, 0xc6, 0x93, 0xcb, 0x1d, 0xaf, 0xa2, 0x58, 0x9d, 0x1d, + 0xf2, 0x91, 0x1b, 0xdc, 0x07, 0x7d, 0xc4, 0x1c, 0x20, 0xdd, 0xe7, 0xbf, 0xee, 0xf5, 0xe9, 0x38, + 0x7e, 0xf0, 0x10, 0x85, 0xe4, 0xcf, 0x7e, 0xb4, 0xea, 0xfb, 0xc6, 0x00, 0xf7, 0xde, 0xf5, 0xf3, + 0x5f, 0x42, 0x3d, 0xb9, 0xcc, 0xf1, 0x3d, 0x8d, 0x7c, 0x00, 0xdb, 0x3e, 0x51, 0x00, 0x4e, 0xf6, + 0xb5, 0x44, 0xf2, 0x9d, 0x84, 0x97, 0xf5, 0x57, 0xb9, 0x77, 0x07, 0x59, 0xee, 0xdd, 0x3e, 0xf8, + 0x9c, 0x66, 0x27, 0x08, 0x01, 0x8f, 0x66, 0x3d, 0x4c, 0x4c, 0xce, 0xf6, 0x9d, 0x25, 0xb7, 0xfb, + 0xce, 0x4b, 0xbc, 0x96, 0xad, 0x97, 0xf8, 0xb8, 0x58, 0x1f, 0x39, 0xe9, 0xf3, 0xcf, 0xf0, 0x0d, + 0xcc, 0x20, 0x4d, 0x0f, 0xf0, 0x71, 0x0f, 0x18, 0xb5, 0xf3, 0xce, 0x48, 0xc6, 0xce, 0x84, 0xba, + 0x20, 0x2f, 0x0b, 0x9f, 0x62, 0x57, 0xec, 0xd7, 0x47, 0x9a, 0xc8, 0x20, 0xf0, 0x7a, 0x53, 0xe1, + 0x13, 0x05, 0xf5, 0x61, 0x52, 0x68, 0x25, 0x33, 0x90, 0xc2, 0xa8, 0x3d, 0xa8, 0x90, 0xa2, 0x09, + 0x16, 0x28, 0x02, 0xae, 0x9f, 0x5e, 0x11, 0x7b, 0x66, 0xb8, 0x61, 0xf5, 0x97, 0xa1, 0x51, 0x3d, + 0x5c, 0x4f, 0x89, 0x30, 0x24, 0xf6, 0x51, 0x22, 0x0c, 0x90, 0xcb, 0xf3, 0x06, 0xc4, 0x81, 0x55, + 0x3b, 0x62, 0x24, 0x5e, 0x4d, 0xba, 0x3b, 0xfe, 0x83, 0x41, 0x9e, 0x42, 0xc5, 0x61, 0xba, 0x8a, + 0xea, 0x7f, 0x43, 0x3a, 0x14, 0x04, 0xc8, 0x49, 0x20, 0x85, 0x4b, 0x96, 0x5c, 0x6a, 0xd2, 0xcf, + 0x7d, 0x30, 0x42, 0x8d, 0xba, 0x11, 0x6a, 0xcc, 0xbd, 0xcc, 0xbd, 0x37, 0x74, 0xfe, 0x2f, 0x50, + 0x2d, 0x01, 0x5d, 0xf8, 0xbe, 0x46, 0xbe, 0x7d, 0x14, 0x35, 0x6e, 0x13, 0x57, 0x67, 0xdf, 0xd9, + 0x48, 0x23, 0x50, 0x83, 0x40, 0xf3, 0xbb, 0x75, 0x40, 0x8c, 0x00, 0x0b, 0xeb, 0x53, 0x68, 0xd2, + 0x3e, 0x8a, 0x26, 0xf5, 0x40, 0x13, 0x97, 0x96, 0xbd, 0x2d, 0xb9, 0xe2, 0x62, 0x07, 0x86, 0x69, + 0x72, 0xe6, 0x01, 0x17, 0xa5, 0x49, 0x13, 0x8c, 0x9e, 0x30, 0x98, 0x26, 0x1c, 0x12, 0x8f, 0x6b, + 0xc7, 0x10, 0x21, 0x59, 0x72, 0xc5, 0xc3, 0x1a, 0xa4, 0xd4, 0x38, 0xee, 0xc3, 0xc6, 0x14, 0xb6, + 0x12, 0x66, 0x15, 0x0f, 0xc2, 0xdc, 0x40, 0x1b, 0xa9, 0x40, 0xfb, 0x36, 0xee, 0x20, 0x6e, 0xaf, + 0x10, 0x8f, 0x36, 0x1b, 0xda, 0xc8, 0x45, 0xd9, 0xb0, 0x12, 0xbe, 0xba, 0xc5, 0xe3, 0xea, 0x77, + 0xb0, 0xcd, 0x23, 0xb4, 0xdb, 0x1a, 0xc7, 0x69, 0x19, 0x1b, 0x79, 0x21, 0x82, 0xf8, 0x7c, 0x1d, + 0x2a, 0x1b, 0xc9, 0x1e, 0x27, 0xb6, 0x71, 0x36, 0x92, 0xa5, 0x22, 0x9b, 0xd4, 0xc4, 0xa2, 0xf1, + 0x14, 0x1c, 0x29, 0x9d, 0x5d, 0xca, 0xe4, 0xc9, 0x4b, 0x1e, 0x60, 0x50, 0xdd, 0x1a, 0x33, 0x66, + 0x33, 0xe9, 0x30, 0x3e, 0xcc, 0xc9, 0x90, 0x8c, 0x78, 0x12, 0x10, 0xdb, 0x34, 0x24, 0x23, 0xce, + 0xf7, 0x57, 0xe8, 0x5a, 0x31, 0x2e, 0x2f, 0xaf, 0x74, 0xb2, 0xfc, 0xf0, 0x60, 0x30, 0x08, 0x90, + 0x47, 0x61, 0x93, 0x61, 0x7a, 0x33, 0xd4, 0xac, 0xa0, 0x93, 0x78, 0x8d, 0xbe, 0xd7, 0xed, 0x75, + 0xde, 0x2b, 0x01, 0x47, 0x3e, 0xdc, 0x1d, 0x97, 0x1f, 0x5c, 0x86, 0xb3, 0x9b, 0xe4, 0x4f, 0x66, + 0xd1, 0x41, 0x61, 0x94, 0xe3, 0xc9, 0x74, 0x5d, 0xf6, 0xe5, 0xf9, 0x2c, 0x6c, 0x39, 0xf2, 0xe3, + 0x0f, 0x86, 0x65, 0xbe, 0xaa, 0x93, 0x81, 0x7d, 0xe6, 0xa0, 0xa0, 0x82, 0xed, 0x81, 0xf1, 0x78, + 0xa6, 0x07, 0x83, 0x41, 0x72, 0xc6, 0xf7, 0x8d, 0x4a, 0xbc, 0x39, 0x89, 0x18, 0xdf, 0xf5, 0x18, + 0x4f, 0x91, 0x66, 0xf1, 0x0b, 0x0d, 0x31, 0xef, 0x03, 0xec, 0x89, 0xf1, 0x37, 0x1e, 0xcf, 0x4a, + 0x84, 0x50, 0xea, 0xde, 0xa0, 0x75, 0x6f, 0x71, 0xfb, 0xbd, 0x84, 0xf7, 0xea, 0xbd, 0xa9, 0x9f, + 0x54, 0x22, 0x63, 0xf9, 0xe3, 0x84, 0x6f, 0x6a, 0xe4, 0xdb, 0x90, 0x47, 0x64, 0x88, 0xb8, 0xde, + 0xc7, 0x05, 0x7a, 0x3e, 0xed, 0x1d, 0x0a, 0x06, 0xf3, 0xe5, 0xc7, 0x14, 0x8c, 0x1a, 0xdd, 0xf7, + 0xc1, 0x30, 0xcc, 0x1a, 0x94, 0x83, 0x6b, 0xe4, 0xcd, 0x49, 0x50, 0xb0, 0x91, 0x8f, 0xef, 0x00, + 0x88, 0xc4, 0xbf, 0x4b, 0xdc, 0x31, 0x58, 0x6e, 0x74, 0x23, 0x32, 0xd3, 0x99, 0xfc, 0x7c, 0x58, + 0x74, 0xda, 0x00, 0x5d, 0x74, 0xaf, 0x7b, 0x08, 0x60, 0x58, 0xce, 0xbd, 0x3c, 0x0a, 0x58, 0x71, + 0xc0, 0xad, 0x03, 0x08, 0xb1, 0x4d, 0x85, 0xb4, 0x8d, 0x00, 0x11, 0x68, 0xe4, 0x3b, 0x71, 0x56, + 0x9b, 0xf8, 0x29, 0xed, 0x4a, 0xc5, 0xc4, 0xb1, 0x95, 0x3b, 0xe0, 0x59, 0x0e, 0x45, 0xee, 0xc0, + 0xde, 0x64, 0xc4, 0xfd, 0xb4, 0x2d, 0xfa, 0xa2, 0x33, 0x9f, 0x3b, 0x70, 0x8e, 0x9c, 0x9e, 0x79, + 0xb1, 0x6a, 0x08, 0x6d, 0x84, 0x73, 0x8d, 0xcd, 0xed, 0xe5, 0xf6, 0xf2, 0xb2, 0xef, 0xa6, 0xca, + 0xb3, 0x34, 0x96, 0xdb, 0xff, 0x58, 0x6c, 0xa4, 0xef, 0xa6, 0xba, 0x6a, 0x80, 0x79, 0x0b, 0xa6, + 0x79, 0xcd, 0x27, 0xf1, 0x01, 0x58, 0xe4, 0x61, 0x96, 0x4a, 0x5d, 0x5d, 0x8c, 0x51, 0x26, 0x42, + 0xa7, 0x10, 0xcb, 0x1d, 0xc8, 0x8a, 0x79, 0x5f, 0x27, 0x8c, 0xf7, 0xca, 0xe3, 0x66, 0xb3, 0xfe, + 0x88, 0x7d, 0x2c, 0xe1, 0x03, 0x79, 0xa5, 0xe5, 0x72, 0x46, 0x06, 0xae, 0x51, 0x4d, 0x1a, 0x24, + 0xfe, 0x1a, 0x19, 0x47, 0x36, 0x69, 0xc9, 0xa6, 0xa5, 0x64, 0x53, 0x52, 0x63, 0x56, 0x22, 0x4c, + 0x1f, 0x94, 0x52, 0xa8, 0xd4, 0x04, 0x85, 0xa9, 0x21, 0xa9, 0x91, 0xa3, 0x96, 0x2b, 0xf0, 0x8d, + 0x54, 0x66, 0x1a, 0xf9, 0x53, 0x5a, 0x60, 0x09, 0xe9, 0xf7, 0xc9, 0xc0, 0x73, 0xfe, 0x1c, 0xe9, + 0xa7, 0x02, 0xc3, 0xb7, 0x90, 0x82, 0x56, 0x52, 0x70, 0xa1, 0x74, 0x76, 0x9e, 0xe7, 0xcd, 0x62, + 0x18, 0x27, 0x4f, 0x66, 0x66, 0x2a, 0xb4, 0xe4, 0x6b, 0xa8, 0xc8, 0x8c, 0x23, 0xee, 0xe7, 0x71, + 0x7c, 0x7e, 0x1f, 0x71, 0xef, 0xa2, 0x0f, 0xbf, 0xb1, 0x11, 0x77, 0x29, 0x3c, 0x95, 0xce, 0xcd, + 0xf3, 0xb8, 0x91, 0x6f, 0x26, 0xf9, 0x57, 0x3a, 0xda, 0x47, 0xe2, 0x5b, 0x09, 0xff, 0xba, 0xc4, + 0x5f, 0x20, 0xfc, 0x6b, 0x12, 0x7f, 0x4a, 0x32, 0xb6, 0x10, 0xe3, 0xcb, 0x84, 0xff, 0x09, 0x45, + 0x48, 0xef, 0x35, 0xe5, 0xcb, 0xef, 0x28, 0x80, 0x54, 0xe2, 0x8e, 0xf7, 0x85, 0x88, 0xbf, 0x35, + 0x48, 0x89, 0xff, 0x41, 0x24, 0xaa, 0x20, 0x40, 0x2a, 0x6b, 0xa9, 0x7c, 0x7e, 0x46, 0x90, 0x11, + 0xa2, 0xd6, 0x0b, 0xbd, 0xfa, 0xab, 0xa5, 0x73, 0x43, 0x33, 0x79, 0xdc, 0xc5, 0x74, 0xc2, 0xe4, + 0xf0, 0x84, 0x3f, 0x91, 0x70, 0x86, 0x53, 0xc4, 0xd8, 0x22, 0xf1, 0xaf, 0x11, 0xfe, 0x82, 0xc4, + 0xbf, 0x4e, 0xf8, 0x56, 0x3a, 0xa1, 0x1d, 0x58, 0xc0, 0xe4, 0xcb, 0x49, 0x0a, 0x68, 0xa8, 0xa7, + 0x09, 0x26, 0x5e, 0x7f, 0xd7, 0xc4, 0x4b, 0x61, 0xe2, 0x83, 0xa3, 0x27, 0x1e, 0x1f, 0x0c, 0x0a, + 0xdc, 0x1a, 0xa1, 0x97, 0x6c, 0x8a, 0x73, 0x5f, 0x15, 0x26, 0x76, 0x4c, 0x06, 0x00, 0x43, 0x3d, + 0xb7, 0xba, 0x9e, 0x64, 0xc5, 0x49, 0xee, 0x85, 0x48, 0x85, 0x37, 0x17, 0x23, 0xd3, 0x7d, 0xa2, + 0x8f, 0x25, 0x57, 0xc4, 0x73, 0x8c, 0x38, 0x10, 0x21, 0x5e, 0x61, 0x0e, 0x05, 0xa9, 0x14, 0x3b, + 0xe6, 0x4b, 0x96, 0x38, 0x4f, 0x6d, 0x10, 0x18, 0x0b, 0x26, 0x6d, 0x6d, 0x33, 0x69, 0xf6, 0x0d, + 0x46, 0x13, 0x73, 0x3b, 0xd8, 0x06, 0xee, 0xc3, 0xa6, 0x3e, 0x6b, 0x3b, 0xdb, 0xcc, 0x7d, 0x58, + 0xd0, 0xce, 0x9e, 0x07, 0xab, 0x7e, 0x99, 0x58, 0x92, 0x49, 0xf6, 0x4a, 0xb0, 0x2e, 0xee, 0x13, + 0x54, 0xb0, 0x24, 0x73, 0xc0, 0xa9, 0xde, 0xc7, 0xf6, 0xa6, 0xc5, 0xa4, 0x0a, 0x13, 0xab, 0x5e, + 0x88, 0x83, 0x2d, 0x8d, 0xe1, 0xf6, 0xd7, 0x71, 0x7c, 0x7d, 0x4d, 0x96, 0xa6, 0xca, 0x75, 0xed, + 0x17, 0x08, 0x63, 0x6c, 0x13, 0xb8, 0x50, 0x9b, 0x30, 0xae, 0x21, 0x4b, 0xc3, 0xfa, 0x27, 0x55, + 0x9f, 0x73, 0x8e, 0xab, 0xf6, 0x0a, 0xe3, 0xfc, 0xb3, 0xaa, 0xbd, 0xce, 0x09, 0x92, 0xf1, 0x38, + 0x69, 0x4a, 0x23, 0xc6, 0xe3, 0xfe, 0x44, 0x89, 0xf7, 0x1a, 0x7c, 0x82, 0x9a, 0xf0, 0x6d, 0x1d, + 0xeb, 0x41, 0xb9, 0xa1, 0xb2, 0x4d, 0x32, 0x36, 0xd1, 0xd6, 0x26, 0x92, 0xa5, 0x06, 0x91, 0x89, + 0x0b, 0x8b, 0xcc, 0xb9, 0x47, 0xa8, 0xc8, 0x50, 0x81, 0xd1, 0x9f, 0xd3, 0x9f, 0x48, 0xd3, 0x7b, + 0xd7, 0x80, 0xf4, 0x11, 0xd8, 0x1b, 0x04, 0x59, 0x5a, 0xb9, 0xf7, 0x29, 0x23, 0xcb, 0x48, 0x59, + 0xd4, 0x68, 0x21, 0x3c, 0xf7, 0xe2, 0x24, 0x58, 0x22, 0x31, 0xff, 0x81, 0x18, 0xc1, 0x20, 0x51, + 0x06, 0xa1, 0x51, 0xfa, 0xf4, 0x51, 0x78, 0xa0, 0x46, 0x2c, 0x64, 0x9c, 0x3c, 0xe9, 0x54, 0x9f, + 0x40, 0xdc, 0xdc, 0xa9, 0xf0, 0x04, 0x66, 0xf5, 0xcd, 0x35, 0x48, 0xa8, 0x37, 0x33, 0x51, 0x7f, + 0xf4, 0x84, 0x3f, 0xd8, 0x77, 0x85, 0x98, 0xa9, 0xc5, 0xf2, 0x7c, 0x8c, 0x5c, 0xb2, 0xc8, 0xcf, + 0x4d, 0x1f, 0x23, 0x84, 0xbc, 0x0c, 0x76, 0x2b, 0x24, 0x87, 0x6f, 0x84, 0xe5, 0xf0, 0xad, 0x90, + 0x1c, 0x5a, 0x2c, 0xc0, 0xd3, 0x9d, 0x7f, 0x1b, 0xcd, 0x53, 0xe1, 0x87, 0xec, 0xa7, 0x38, 0xb8, + 0xb8, 0x17, 0x27, 0x62, 0xd8, 0xdb, 0xe2, 0xed, 0x54, 0xc7, 0x2f, 0x38, 0xbd, 0x24, 0x1c, 0xec, + 0xbb, 0x2e, 0x15, 0x1c, 0x11, 0xaf, 0x32, 0x6c, 0x43, 0xec, 0x79, 0xb0, 0xcf, 0x86, 0xd3, 0xa4, + 0x55, 0x32, 0x77, 0x26, 0xb4, 0x70, 0xe9, 0xe7, 0x89, 0xb9, 0x93, 0x4b, 0x3f, 0x0d, 0x0a, 0x2f, + 0x19, 0xdb, 0xb9, 0xf4, 0x33, 0x92, 0xf9, 0x0f, 0xe9, 0xe2, 0x60, 0xb4, 0xc2, 0x15, 0x41, 0xe6, + 0xdc, 0x83, 0xa0, 0xd5, 0xfe, 0xe9, 0xdc, 0x7e, 0x9e, 0x40, 0x31, 0xf8, 0xb0, 0xc9, 0xfe, 0xc1, + 0x06, 0x96, 0x91, 0x17, 0x2f, 0xa2, 0xa8, 0x1e, 0x52, 0xe3, 0x76, 0x74, 0x95, 0x64, 0xab, 0xc0, + 0x2e, 0x7a, 0x33, 0x2d, 0x26, 0xf9, 0xd2, 0x6c, 0x4a, 0x4d, 0x60, 0x87, 0xaa, 0x21, 0x2b, 0x95, + 0x7d, 0x7b, 0xcd, 0xd4, 0x28, 0xc6, 0xa3, 0x71, 0x83, 0x49, 0x64, 0x7c, 0x6d, 0x11, 0x79, 0x39, + 0x79, 0xa6, 0xe0, 0xb2, 0x4c, 0xa8, 0x93, 0xff, 0xf6, 0x28, 0x02, 0xc6, 0xbd, 0x83, 0x05, 0x69, + 0x22, 0x05, 0xcb, 0x61, 0xc9, 0x14, 0x7c, 0x20, 0x4b, 0x6b, 0x50, 0xf7, 0x57, 0xaf, 0x0a, 0xe9, + 0x72, 0x1e, 0x8c, 0x1b, 0xf3, 0x3d, 0x45, 0xa0, 0xd7, 0x44, 0x82, 0xd4, 0x39, 0x76, 0xe9, 0xaf, + 0x66, 0x88, 0xfd, 0x41, 0xe7, 0xaa, 0xbb, 0xc6, 0xd7, 0x9f, 0xcb, 0xcd, 0xc9, 0x0d, 0xcf, 0xf0, + 0xea, 0x3f, 0x99, 0x61, 0x65, 0x4d, 0x30, 0x2b, 0xd1, 0x3f, 0xb1, 0x94, 0x29, 0x2d, 0xcf, 0x97, + 0x55, 0x14, 0x50, 0x83, 0x05, 0xf9, 0xdc, 0xa3, 0xa3, 0x26, 0xdd, 0xfb, 0xa0, 0x62, 0xf3, 0x41, + 0xe2, 0x23, 0x33, 0xc4, 0x01, 0x76, 0xa7, 0x44, 0x86, 0x10, 0xca, 0x22, 0x9f, 0x4d, 0x51, 0x54, + 0x51, 0x78, 0x5f, 0x2a, 0xb8, 0x96, 0x51, 0x75, 0x1b, 0x1d, 0x0b, 0xce, 0xbd, 0x09, 0xb6, 0x93, + 0xaa, 0xe3, 0xb8, 0x09, 0x8c, 0xd9, 0xf9, 0xe2, 0xe4, 0xd7, 0xd6, 0x33, 0x4c, 0xb5, 0x97, 0xab, + 0x6e, 0x04, 0x30, 0xf9, 0xc4, 0x63, 0x00, 0xab, 0x07, 0x93, 0x36, 0x31, 0xd1, 0x0e, 0x98, 0xdd, + 0x1f, 0x0f, 0x7f, 0x43, 0xae, 0x09, 0x69, 0x8d, 0x6e, 0xa2, 0x9e, 0x8e, 0xb3, 0x22, 0x27, 0x2f, + 0x17, 0xe4, 0xcf, 0x02, 0x8c, 0x01, 0x25, 0x92, 0xff, 0xb3, 0x17, 0x39, 0xad, 0x25, 0x0d, 0xe4, + 0xec, 0xe1, 0xd4, 0x74, 0x8e, 0xe9, 0xfb, 0x02, 0xe4, 0xb3, 0xc4, 0x87, 0x8f, 0x6c, 0x0b, 0x48, + 0x39, 0xe9, 0xe3, 0x3e, 0x74, 0x05, 0x48, 0xa0, 0xef, 0x4b, 0x76, 0x90, 0xfb, 0xf0, 0x24, 0x7b, + 0x56, 0x32, 0xcb, 0xf3, 0xea, 0x24, 0xbe, 0x3d, 0xa1, 0xa9, 0xa4, 0x09, 0xa1, 0x48, 0x4b, 0xa8, + 0x1f, 0xdb, 0x1c, 0x14, 0x02, 0x79, 0xb9, 0x26, 0x79, 0x63, 0x68, 0xc8, 0x4b, 0xd4, 0x0b, 0x0a, + 0x4c, 0x76, 0xb5, 0xc9, 0x2f, 0x03, 0x66, 0xf2, 0x8b, 0x60, 0x42, 0xe5, 0x0c, 0x23, 0xfc, 0x79, + 0x70, 0x00, 0x25, 0x4e, 0xf3, 0xab, 0x6f, 0x41, 0x9c, 0x84, 0x04, 0x10, 0x01, 0xb5, 0x49, 0x9e, + 0xf4, 0x10, 0x2e, 0x5c, 0xe5, 0x4f, 0xb0, 0x27, 0x81, 0x1c, 0x74, 0xec, 0x07, 0x5c, 0xc5, 0x7e, + 0x56, 0x88, 0x95, 0xd5, 0x3c, 0xf4, 0xf8, 0x6b, 0x26, 0xc3, 0xbc, 0x53, 0x03, 0x4a, 0xe0, 0x8f, + 0x7a, 0xbb, 0x46, 0xd9, 0xd0, 0x63, 0xec, 0xd5, 0x39, 0x00, 0xe8, 0xc1, 0xd5, 0xb9, 0x3a, 0x2b, + 0x77, 0x4d, 0x64, 0x9c, 0xd1, 0xc4, 0x27, 0x57, 0x43, 0xd9, 0xbf, 0x02, 0x88, 0x90, 0x1a, 0x0f, + 0x40, 0x7d, 0xe2, 0x0b, 0x89, 0xc1, 0xe7, 0x17, 0xe8, 0xaf, 0xae, 0xd7, 0x07, 0xb9, 0xfd, 0x59, + 0x9a, 0x7c, 0x70, 0x53, 0x4d, 0xf2, 0xe6, 0x05, 0x94, 0xc8, 0xb0, 0x1b, 0x03, 0x0b, 0xe4, 0x5c, + 0x06, 0x69, 0x28, 0x8c, 0xcf, 0x58, 0xbd, 0x62, 0x53, 0xe2, 0x0b, 0x97, 0x2b, 0x53, 0x7e, 0x02, + 0x13, 0x30, 0xc2, 0x44, 0xfb, 0x0f, 0xf3, 0x40, 0x20, 0xdf, 0xa6, 0xb0, 0xaa, 0xca, 0x14, 0x37, + 0xd6, 0x4a, 0x42, 0x40, 0x72, 0x75, 0x3a, 0xa7, 0xca, 0xcb, 0x2e, 0x81, 0xf9, 0x4f, 0x59, 0x89, + 0x2c, 0x5f, 0x96, 0x8c, 0x42, 0x91, 0x79, 0x0a, 0x6c, 0x64, 0x9d, 0x89, 0xee, 0xdc, 0x3f, 0x9f, + 0x1e, 0xde, 0xb9, 0xc9, 0x99, 0xda, 0xfb, 0x3d, 0xd0, 0xb1, 0x21, 0x0a, 0xff, 0xb2, 0xf6, 0x68, + 0x33, 0xcb, 0xe4, 0xc8, 0x27, 0x26, 0x52, 0x59, 0x00, 0xfc, 0x96, 0xdb, 0xaf, 0x40, 0x97, 0x7c, + 0xf9, 0xc0, 0x70, 0xcd, 0x5c, 0xbb, 0x75, 0x23, 0xd6, 0xbc, 0x37, 0x5c, 0x33, 0xd5, 0xae, 0xa2, + 0x35, 0xaf, 0x86, 0x6b, 0xb8, 0xea, 0x7f, 0xc1, 0x45, 0x37, 0xd4, 0x84, 0x86, 0x46, 0x7c, 0x59, + 0x29, 0x35, 0x51, 0xca, 0xd6, 0x1d, 0x76, 0xfe, 0x2d, 0x92, 0xd1, 0xd7, 0x45, 0x37, 0x0b, 0xab, + 0x3d, 0x53, 0x92, 0xca, 0x18, 0x66, 0x5e, 0x8b, 0x78, 0x99, 0x39, 0x96, 0x54, 0x08, 0xd3, 0x9a, + 0x4a, 0x99, 0xdc, 0x7c, 0x8b, 0xbc, 0x72, 0x12, 0x0e, 0x13, 0x6f, 0x91, 0xff, 0x4c, 0xc7, 0x53, + 0x95, 0xc6, 0xd9, 0x9d, 0x07, 0x55, 0x8c, 0x3d, 0xf0, 0x38, 0xac, 0xf6, 0xa3, 0xfb, 0xc2, 0x94, + 0x99, 0x66, 0x7f, 0x10, 0x70, 0xf5, 0x47, 0xd9, 0x03, 0x80, 0xa0, 0xfc, 0xb3, 0xf9, 0x14, 0x56, + 0xef, 0xa5, 0xf2, 0xd7, 0x10, 0x85, 0xc4, 0x60, 0xf7, 0xb1, 0xfe, 0x80, 0x82, 0x83, 0xff, 0x2b, + 0x58, 0xae, 0xd8, 0xb9, 0x14, 0xfc, 0x6e, 0xf0, 0x46, 0x64, 0x2d, 0xa2, 0xe7, 0xd3, 0x7b, 0xdd, + 0x27, 0x84, 0x48, 0xd8, 0xbf, 0xc4, 0xe3, 0x4b, 0xc3, 0x32, 0x5b, 0xd5, 0xf9, 0x38, 0x58, 0x4d, + 0x72, 0x86, 0xc4, 0xea, 0xbd, 0x1e, 0xcf, 0x1b, 0x20, 0x00, 0xfa, 0xde, 0x2c, 0x93, 0x1d, 0x83, + 0x71, 0x93, 0x29, 0x27, 0x57, 0x7e, 0x84, 0x5a, 0xaa, 0x78, 0x14, 0x69, 0x1e, 0xea, 0x3c, 0xee, + 0x73, 0x00, 0x52, 0x1a, 0x69, 0x9f, 0x00, 0xac, 0x30, 0xc9, 0xf9, 0xf1, 0x61, 0xec, 0x92, 0x3d, + 0xee, 0xbf, 0x8e, 0x6e, 0x49, 0x19, 0x6e, 0x99, 0xee, 0x71, 0xff, 0x02, 0x5b, 0xa2, 0xec, 0x7b, + 0x4d, 0xd8, 0xf2, 0x40, 0xb8, 0x85, 0x73, 0xf7, 0x80, 0xfe, 0xd4, 0x7a, 0x50, 0xea, 0xb8, 0xfd, + 0x67, 0x0f, 0xf6, 0x83, 0xf0, 0x2d, 0xaf, 0x79, 0x1f, 0x7c, 0x2d, 0x67, 0x74, 0x2a, 0x57, 0x7d, + 0x11, 0x1a, 0xfd, 0xdf, 0x80, 0xc3, 0xcf, 0x1d, 0x78, 0xf3, 0x3f, 0x11, 0xe4, 0xc0, 0x79, 0x0a, + 0x62, 0x5b, 0xf1, 0xfa, 0x5b, 0x08, 0x33, 0x41, 0xf4, 0x46, 0x70, 0xd5, 0xfb, 0x10, 0xaa, 0xb3, + 0xf6, 0x83, 0xdf, 0x00, 0x44, 0x8d, 0xac, 0xba, 0xbd, 0xf2, 0x0e, 0xb7, 0xe7, 0x0d, 0x96, 0xba, + 0x39, 0xbf, 0x86, 0x2a, 0x50, 0x18, 0x64, 0x4f, 0xad, 0x52, 0xf3, 0x01, 0xad, 0x39, 0xe5, 0x6b, + 0x8b, 0x82, 0x4d, 0xd4, 0x93, 0x19, 0x11, 0x24, 0x66, 0xf9, 0xff, 0xf6, 0xb9, 0x64, 0x70, 0xc4, + 0xa0, 0xf5, 0x43, 0xda, 0xda, 0x0e, 0x0c, 0x8e, 0x96, 0xdc, 0x47, 0x94, 0x02, 0x54, 0xff, 0x0e, + 0x9e, 0xdc, 0x5e, 0x69, 0xaf, 0x97, 0xd6, 0x74, 0x12, 0xf3, 0x05, 0x2e, 0xb3, 0x8e, 0xdb, 0xff, + 0x39, 0x31, 0xb7, 0xa0, 0x6e, 0x36, 0x11, 0xf3, 0x71, 0xee, 0x00, 0xe8, 0x25, 0x7f, 0x4d, 0xef, + 0x95, 0xcc, 0xde, 0x48, 0xf3, 0x35, 0xee, 0x15, 0xf8, 0xdb, 0x34, 0x99, 0x3f, 0xbe, 0xc2, 0xdc, + 0x2e, 0xb6, 0x82, 0xf3, 0x3b, 0x81, 0x45, 0x23, 0xdf, 0x3e, 0xaf, 0x45, 0x7f, 0xae, 0x4f, 0x08, + 0xa4, 0xdc, 0xe2, 0x18, 0x66, 0xe7, 0x94, 0xc6, 0xd5, 0x2a, 0x0d, 0xb0, 0x65, 0x1f, 0x1b, 0xb2, + 0x08, 0x92, 0xb9, 0xcd, 0x9f, 0x94, 0x72, 0x2b, 0x48, 0x9f, 0x76, 0xde, 0x03, 0xcd, 0xda, 0xd1, + 0xcd, 0xfe, 0x38, 0xa8, 0xd1, 0xd1, 0x1a, 0xd0, 0x61, 0xea, 0x84, 0x74, 0xea, 0xbd, 0x36, 0x52, + 0xa8, 0xa9, 0xd9, 0x30, 0xc9, 0x46, 0xf2, 0xb5, 0x35, 0x65, 0xf7, 0x48, 0x9e, 0x83, 0x88, 0xe4, + 0x86, 0x38, 0xd8, 0x6f, 0xc9, 0x86, 0x78, 0xf7, 0x09, 0xae, 0x1a, 0xc3, 0x37, 0xe9, 0xcd, 0x26, + 0xac, 0x2e, 0x9c, 0x4d, 0xf2, 0x13, 0x25, 0xe3, 0x29, 0x1b, 0xd9, 0x30, 0xd7, 0x06, 0x6d, 0xaf, + 0xf9, 0xaa, 0x9b, 0x84, 0x0a, 0x89, 0xef, 0xec, 0xb3, 0xb6, 0x10, 0x5f, 0xa4, 0xf1, 0x1a, 0x6c, + 0xf4, 0xc2, 0x16, 0xd8, 0x8c, 0xd6, 0x90, 0x3a, 0xdf, 0xe0, 0x8c, 0x48, 0xbe, 0x15, 0x77, 0xfe, + 0x2f, 0x58, 0xd8, 0xbd, 0x36, 0x2c, 0xd8, 0xb5, 0x0e, 0x71, 0x97, 0xc9, 0xea, 0xa4, 0x4a, 0x57, + 0x80, 0x71, 0x4e, 0x26, 0x1b, 0x74, 0x1e, 0xf3, 0x1b, 0x36, 0xf2, 0xc3, 0xfb, 0x7c, 0x7e, 0x2d, + 0x7c, 0xc5, 0xf9, 0xa3, 0x59, 0x9f, 0x63, 0x0e, 0x54, 0xc3, 0xce, 0xda, 0xeb, 0xe1, 0x8f, 0x90, + 0x01, 0x30, 0xab, 0x13, 0x22, 0x42, 0x1a, 0x82, 0xee, 0x3f, 0x83, 0xb2, 0x77, 0x84, 0xac, 0x56, + 0x93, 0x40, 0xd5, 0x71, 0x94, 0xba, 0x51, 0xa6, 0xb3, 0xaa, 0xb3, 0x1a, 0x69, 0x84, 0xd2, 0xfa, + 0xba, 0xbc, 0x19, 0xa5, 0xf0, 0x04, 0x88, 0xce, 0x44, 0xd2, 0x54, 0x75, 0xbc, 0x3a, 0x6c, 0x64, + 0x25, 0x17, 0x38, 0xec, 0xd9, 0x95, 0xcf, 0x3f, 0xc2, 0x2e, 0xf2, 0xec, 0x60, 0x9d, 0xbd, 0x92, + 0xf9, 0x0d, 0x0c, 0x18, 0x75, 0x42, 0x1c, 0x0c, 0xeb, 0xf1, 0xec, 0xa2, 0xee, 0x70, 0xda, 0x7d, + 0x3e, 0x19, 0xf0, 0x49, 0x8b, 0x83, 0x18, 0x46, 0x7f, 0x02, 0x36, 0xac, 0x56, 0x36, 0xe0, 0x38, + 0xc8, 0xed, 0x57, 0x8d, 0x47, 0x39, 0xa8, 0xa1, 0x46, 0x6c, 0x91, 0x73, 0x02, 0x18, 0x72, 0x15, + 0x8c, 0x2b, 0xb4, 0xf9, 0xdf, 0x00, 0x09, 0xf3, 0xa8, 0x1e, 0xc9, 0x03, 0xdf, 0xab, 0x62, 0x08, + 0x7d, 0xaf, 0x23, 0x53, 0xa9, 0x7c, 0x36, 0x54, 0xdf, 0x8f, 0x65, 0x26, 0x83, 0xbd, 0xce, 0xed, + 0x59, 0x09, 0xb0, 0x80, 0x19, 0xec, 0xa4, 0x21, 0x28, 0x0f, 0x7f, 0xca, 0x24, 0x3f, 0xc4, 0x86, + 0xf5, 0xdf, 0x3d, 0x0d, 0x1e, 0x7b, 0xf9, 0x4b, 0x5a, 0x25, 0x08, 0xab, 0xc6, 0xcd, 0xb9, 0x54, + 0x87, 0x40, 0x9e, 0x37, 0x77, 0x51, 0xb7, 0xd3, 0xa6, 0x8c, 0x4a, 0x0a, 0x3a, 0xc1, 0x03, 0xea, + 0xd8, 0x8c, 0xfe, 0x81, 0x39, 0xc0, 0xf6, 0xe5, 0xe5, 0x7b, 0x3e, 0xc6, 0x01, 0x2d, 0x32, 0x3f, + 0x76, 0x5a, 0x65, 0x36, 0x0b, 0x9d, 0xe7, 0x8f, 0xb8, 0xf5, 0x9e, 0x08, 0xcd, 0xd4, 0x31, 0x84, + 0x2a, 0x6a, 0x29, 0x4d, 0x92, 0x63, 0x93, 0x95, 0x0d, 0xac, 0xde, 0x52, 0x9a, 0x29, 0xab, 0x94, + 0x82, 0xe8, 0x0a, 0xe8, 0x3c, 0xc2, 0xeb, 0x87, 0x26, 0xa2, 0xc2, 0x37, 0xf6, 0xbc, 0x47, 0x1a, + 0xb9, 0x03, 0xe6, 0xaf, 0x88, 0x69, 0x29, 0x44, 0x9a, 0x20, 0xa4, 0xbe, 0x36, 0x6d, 0x74, 0x1d, + 0xc9, 0x5f, 0x2a, 0x09, 0x6a, 0xe0, 0x33, 0x59, 0x9d, 0x0c, 0x7e, 0xb2, 0x37, 0xb5, 0x71, 0x75, + 0x2a, 0x3d, 0x92, 0x33, 0xbe, 0x6e, 0x92, 0xbf, 0x56, 0x51, 0xbb, 0x42, 0x56, 0xaf, 0x04, 0xfa, + 0xcf, 0x05, 0xff, 0xed, 0x39, 0x6d, 0x63, 0x46, 0xdc, 0xe7, 0xd1, 0x2c, 0xd3, 0x98, 0x11, 0x3f, + 0x31, 0x06, 0x1c, 0x24, 0xe8, 0x94, 0x91, 0xd8, 0x98, 0xa1, 0xa3, 0xbb, 0x58, 0x85, 0xaa, 0xe3, + 0x71, 0x40, 0x48, 0xfc, 0x71, 0x32, 0xe3, 0x3c, 0x87, 0x68, 0x65, 0xe6, 0xcb, 0xbf, 0x78, 0x98, + 0xae, 0x04, 0x50, 0xcc, 0x93, 0x5f, 0x55, 0x9e, 0xf5, 0x27, 0x3a, 0xf4, 0x00, 0x16, 0xe6, 0x75, + 0x32, 0xfa, 0x55, 0x97, 0xc8, 0x69, 0x6e, 0x7f, 0xda, 0x24, 0xee, 0xc0, 0x0f, 0x34, 0xdc, 0x87, + 0xad, 0x1e, 0xf7, 0x11, 0x00, 0xb0, 0x47, 0xb1, 0xf4, 0x70, 0x4f, 0xfe, 0xe1, 0x14, 0xc5, 0x48, + 0x04, 0x9d, 0xe9, 0xdc, 0x81, 0xfc, 0xfb, 0xc4, 0x17, 0x54, 0x3a, 0x21, 0x9a, 0x3b, 0xb0, 0x3a, + 0x8e, 0xae, 0xc0, 0x03, 0x8e, 0x78, 0x97, 0x49, 0x7e, 0x54, 0xc1, 0x15, 0x19, 0xeb, 0x8a, 0xc4, + 0xf5, 0x4a, 0xc6, 0x56, 0x08, 0xca, 0x0b, 0x3a, 0xfb, 0xbe, 0xfc, 0xd1, 0x4c, 0xdf, 0xcd, 0x88, + 0x52, 0x26, 0xa7, 0xe3, 0x89, 0x48, 0xd4, 0xfc, 0xec, 0xb9, 0xbe, 0x9b, 0x51, 0x9e, 0x8c, 0x20, + 0xdb, 0x54, 0x31, 0x0b, 0xec, 0x5b, 0x47, 0x0e, 0x82, 0xd7, 0x83, 0x5f, 0x97, 0x02, 0xf3, 0x69, + 0x1d, 0xbb, 0x41, 0x39, 0xc1, 0xa7, 0x80, 0x89, 0x3b, 0xe6, 0x63, 0xcb, 0x65, 0x90, 0xf5, 0x1e, + 0x6c, 0xef, 0xec, 0xbb, 0x09, 0x14, 0x7c, 0xd9, 0x5b, 0x85, 0xce, 0xae, 0x96, 0x7b, 0xd5, 0xa7, + 0xf6, 0x55, 0x9f, 0x20, 0x05, 0xed, 0x10, 0x55, 0x70, 0xee, 0xe8, 0xc8, 0x90, 0xd7, 0x5f, 0xf3, + 0xb0, 0xc2, 0x08, 0x88, 0x77, 0x0e, 0x64, 0x69, 0xfa, 0x6c, 0x0b, 0x42, 0x13, 0xea, 0xaf, 0xe6, + 0x49, 0x05, 0x01, 0x70, 0x53, 0xf2, 0x82, 0x0f, 0xcb, 0x7f, 0x8d, 0x1f, 0x36, 0xa4, 0x6d, 0x68, + 0x71, 0x5b, 0x25, 0xa1, 0xdd, 0x9f, 0x09, 0xfd, 0xf3, 0xe4, 0x35, 0xa1, 0xfe, 0x5d, 0x64, 0x10, + 0x48, 0x98, 0x67, 0xb1, 0xc0, 0x48, 0x26, 0x68, 0xb6, 0xc8, 0x9f, 0xaa, 0x86, 0x3b, 0x3d, 0x8f, + 0xd6, 0x57, 0xf5, 0x31, 0x52, 0x1d, 0xf0, 0xcc, 0x97, 0x0d, 0xcb, 0x42, 0x21, 0x42, 0x80, 0xf4, + 0x49, 0x05, 0x9d, 0xdc, 0x87, 0xb7, 0x7d, 0xdf, 0x44, 0x71, 0xd5, 0xa9, 0x08, 0xb6, 0x86, 0x85, + 0x80, 0xc1, 0xb3, 0x06, 0x62, 0xd1, 0x0b, 0x8d, 0xfc, 0x35, 0x86, 0x8a, 0x0f, 0x90, 0x05, 0x7d, + 0x5d, 0xa1, 0x9d, 0x40, 0x20, 0x76, 0xda, 0xf7, 0x55, 0x14, 0xb7, 0x5f, 0x93, 0x84, 0x16, 0x62, + 0x12, 0xf4, 0x60, 0x1b, 0x44, 0x97, 0x86, 0xa9, 0xcd, 0x9a, 0xe0, 0xcc, 0x5b, 0xc9, 0x71, 0xee, + 0xb9, 0xc8, 0x1f, 0x88, 0x56, 0x67, 0xf4, 0xfa, 0x52, 0x21, 0x1c, 0x73, 0xce, 0x50, 0xf8, 0xa2, + 0x53, 0x98, 0x64, 0x22, 0xe7, 0xe5, 0xc3, 0x93, 0x01, 0xe2, 0x0a, 0xcc, 0x8b, 0x32, 0xdd, 0xe2, + 0x3e, 0xe7, 0x5c, 0x68, 0x00, 0x1f, 0x04, 0x3c, 0x4b, 0x59, 0x88, 0x12, 0x07, 0xe3, 0x76, 0xcc, + 0x0f, 0xcd, 0xdb, 0xe1, 0x81, 0x8e, 0x2b, 0xd5, 0x4a, 0x13, 0x57, 0xdd, 0x09, 0xa5, 0x8e, 0x67, + 0xe1, 0x4f, 0xb8, 0xd9, 0x8e, 0x8a, 0x95, 0x0e, 0x76, 0xf5, 0x9a, 0x47, 0x95, 0x4b, 0xcc, 0xa7, + 0x3c, 0xaa, 0x3d, 0x60, 0xb2, 0x3d, 0x3f, 0x89, 0xc2, 0x89, 0x0e, 0xdf, 0xa6, 0x8e, 0x70, 0x4b, + 0xed, 0x93, 0xa6, 0x98, 0x9a, 0x27, 0x63, 0xfb, 0xd3, 0x85, 0xbf, 0xe9, 0xcf, 0x81, 0xe5, 0xab, + 0x4d, 0x34, 0xd1, 0xa2, 0x38, 0x38, 0x4e, 0xe8, 0x09, 0x1a, 0xdb, 0xc0, 0xe2, 0x5c, 0xad, 0xcd, + 0xb4, 0x24, 0xd6, 0x64, 0xc6, 0x0e, 0xf5, 0xd6, 0xb3, 0xc2, 0x3d, 0x91, 0xe6, 0xb6, 0xdf, 0xb3, + 0x55, 0x83, 0x88, 0x34, 0x0d, 0x3f, 0x1d, 0x37, 0x45, 0xd7, 0x29, 0x88, 0x84, 0xfa, 0xe0, 0xf9, + 0x60, 0x24, 0x1a, 0x9a, 0x82, 0xce, 0xca, 0x23, 0x74, 0x0e, 0x9d, 0xa0, 0x16, 0xbd, 0x41, 0x47, + 0x17, 0x84, 0x02, 0x0d, 0xd5, 0x51, 0x9f, 0xa2, 0xea, 0x55, 0xa6, 0xe0, 0x0e, 0xca, 0x1c, 0xfc, + 0xf4, 0x5e, 0x96, 0x39, 0xd4, 0x03, 0x7f, 0x38, 0xde, 0x17, 0x14, 0x34, 0x1e, 0x0f, 0xc2, 0xe7, + 0x04, 0x5b, 0x42, 0x5b, 0xbe, 0x03, 0x37, 0xaf, 0x2c, 0x08, 0x45, 0xe4, 0xf7, 0xd5, 0x9c, 0xfb, + 0xdf, 0x71, 0x68, 0x70, 0xd2, 0x83, 0x0d, 0x99, 0x51, 0xa7, 0x74, 0xa9, 0x42, 0x3f, 0xb8, 0x53, + 0xb5, 0xe0, 0xc5, 0x38, 0x37, 0xe9, 0x83, 0xa1, 0xb0, 0x1e, 0x3c, 0xd9, 0x95, 0x0b, 0x9d, 0x7a, + 0x31, 0xa8, 0xe6, 0x5e, 0xf1, 0x89, 0xc1, 0x98, 0x9d, 0x4f, 0xc5, 0x18, 0xdb, 0x7a, 0x7d, 0xac, + 0xf3, 0x71, 0xee, 0xa8, 0x17, 0x6c, 0xa5, 0x96, 0x4a, 0x73, 0x4d, 0x66, 0x8a, 0x6f, 0x35, 0x76, + 0x56, 0xc5, 0x67, 0x80, 0x13, 0xf4, 0x99, 0xff, 0xfe, 0x5e, 0xbe, 0x8d, 0x45, 0xc2, 0x6e, 0x51, + 0x6a, 0x8f, 0xa1, 0x27, 0xfe, 0x11, 0x70, 0xb8, 0x0d, 0x9a, 0x3f, 0x28, 0x9d, 0xe0, 0xe1, 0x7d, + 0x26, 0x8b, 0xfc, 0x99, 0x36, 0xbc, 0xab, 0x56, 0x1f, 0x45, 0x93, 0x8f, 0xa1, 0x6a, 0x3b, 0x2c, + 0x13, 0x3a, 0x02, 0xf1, 0xfd, 0xd1, 0xf8, 0x48, 0x99, 0x90, 0x06, 0x82, 0x85, 0x3e, 0x24, 0x8a, + 0x8b, 0xc8, 0xb7, 0xe8, 0x44, 0xfe, 0x82, 0xce, 0x30, 0xc0, 0xed, 0xf9, 0x02, 0x8c, 0xae, 0x3f, + 0x0a, 0xc0, 0xfc, 0x67, 0xc0, 0xca, 0x42, 0x00, 0xd7, 0x5a, 0xca, 0xe4, 0x99, 0xe4, 0x73, 0x8b, + 0xe9, 0xb8, 0xfe, 0x59, 0x28, 0xa9, 0xe0, 0x4f, 0xca, 0x3e, 0xa5, 0xc2, 0xf7, 0x55, 0x04, 0xd4, + 0x58, 0xf2, 0xe5, 0x8f, 0x94, 0x32, 0xf4, 0x41, 0xb3, 0x9e, 0x1c, 0x36, 0xd6, 0xa5, 0x4c, 0x7e, + 0x9e, 0xff, 0x0b, 0x70, 0xa1, 0x35, 0x72, 0xc9, 0x92, 0x90, 0xa3, 0x5d, 0x3a, 0x01, 0xb6, 0x84, + 0x82, 0x58, 0x0a, 0x7f, 0x70, 0x02, 0x9e, 0xa4, 0x42, 0x28, 0x0a, 0x0c, 0x68, 0xc8, 0x1c, 0x1f, + 0x64, 0xd6, 0x08, 0x5d, 0x78, 0xee, 0x95, 0xac, 0xef, 0xf5, 0x4f, 0x2e, 0xd5, 0x59, 0x82, 0x82, + 0x5a, 0x5e, 0x1c, 0x1b, 0x1a, 0x5a, 0x41, 0xbe, 0xe3, 0x69, 0x14, 0x07, 0x58, 0x81, 0x61, 0xa0, + 0x22, 0x0d, 0xd4, 0x8b, 0x9e, 0x2f, 0xa8, 0x80, 0x17, 0x47, 0x31, 0x2e, 0x75, 0xfe, 0x29, 0xe5, + 0xcf, 0xe8, 0x4e, 0x5f, 0x84, 0x6a, 0xd6, 0x57, 0xb9, 0x7b, 0x02, 0xc7, 0x55, 0x3f, 0x4c, 0xcd, + 0x70, 0x0e, 0x8e, 0xf5, 0x95, 0x16, 0x89, 0x12, 0xa0, 0xc3, 0x75, 0xe0, 0x39, 0x07, 0x20, 0xec, + 0xff, 0xf5, 0xf0, 0xb1, 0x1d, 0x28, 0x85, 0xf4, 0x23, 0xf0, 0xa6, 0xc4, 0x21, 0xcd, 0xa1, 0x6f, + 0x38, 0x3c, 0xb0, 0x68, 0x12, 0x87, 0xb4, 0x9f, 0x7c, 0x13, 0xc4, 0xc7, 0xd6, 0xe8, 0x93, 0xe2, + 0x90, 0xee, 0xd8, 0x37, 0xe0, 0x83, 0x70, 0xfc, 0x6d, 0x71, 0x30, 0x82, 0xdb, 0xf3, 0x07, 0x98, + 0xca, 0x30, 0xc8, 0xbd, 0xf8, 0x1b, 0x7a, 0x48, 0x47, 0x06, 0xd6, 0x62, 0x70, 0x55, 0x8d, 0x67, + 0x96, 0xb8, 0xd3, 0xb1, 0x06, 0x1f, 0x97, 0xee, 0xeb, 0x03, 0x16, 0x04, 0xc0, 0xda, 0x7c, 0x82, + 0x21, 0x0b, 0xb8, 0xf6, 0x80, 0xba, 0x87, 0xef, 0x34, 0xc9, 0x41, 0x36, 0x64, 0xb6, 0x84, 0x32, + 0x30, 0xf1, 0x30, 0x9c, 0x63, 0xaa, 0x61, 0x70, 0xe7, 0x3d, 0x62, 0xbd, 0x0a, 0x10, 0xf4, 0x64, + 0x26, 0xb1, 0x59, 0xe8, 0x67, 0x9f, 0xf5, 0xe7, 0xe8, 0x83, 0xf9, 0xa5, 0x2a, 0x70, 0x10, 0x0b, + 0x29, 0x89, 0xb5, 0x74, 0xdb, 0x6f, 0x87, 0x6d, 0x1f, 0x7a, 0xa1, 0xda, 0xc7, 0x1d, 0x0c, 0x8f, + 0xf8, 0xc1, 0xf0, 0x88, 0xdc, 0x6a, 0xc3, 0x90, 0x70, 0x03, 0x09, 0x99, 0x84, 0x6c, 0xd7, 0x02, + 0x0f, 0x91, 0x69, 0x1a, 0xbd, 0x42, 0x49, 0xef, 0xa8, 0xa3, 0x3a, 0x3c, 0x2d, 0x5b, 0xa3, 0x95, + 0x72, 0x56, 0x06, 0x85, 0xc4, 0xa0, 0x10, 0x0f, 0x71, 0x72, 0x50, 0xd0, 0x82, 0x9c, 0x07, 0x7f, + 0x94, 0x2a, 0xf3, 0x4c, 0xc8, 0xee, 0x38, 0x23, 0x0a, 0xea, 0xed, 0x4f, 0x6c, 0xa0, 0x4e, 0xf4, + 0x0f, 0x26, 0x53, 0x27, 0x3a, 0xdf, 0x82, 0x3d, 0xcb, 0xb5, 0x52, 0x56, 0x2a, 0xc6, 0x61, 0xc1, + 0x7c, 0x53, 0x70, 0xc7, 0x4a, 0xf9, 0xd7, 0x49, 0x74, 0x86, 0xfc, 0xd2, 0x4c, 0x8b, 0xfc, 0x73, + 0xe5, 0x79, 0x53, 0xe1, 0x48, 0x60, 0x34, 0x17, 0xdd, 0xa6, 0xfd, 0x39, 0x60, 0x91, 0xda, 0xb8, + 0x03, 0x69, 0x1a, 0x74, 0x9c, 0xae, 0xc1, 0xf6, 0x7c, 0x6e, 0x85, 0x31, 0x9e, 0xb4, 0x4c, 0xe3, + 0x13, 0xb9, 0x57, 0xf9, 0x1e, 0x4e, 0xbc, 0x82, 0x84, 0x3a, 0x1d, 0x29, 0x40, 0xa8, 0x32, 0xd9, + 0x05, 0x61, 0x7b, 0x50, 0xb8, 0x06, 0x1e, 0xbb, 0xb1, 0x9d, 0x98, 0x5b, 0xe5, 0x7f, 0xed, 0x50, + 0x82, 0x98, 0xb3, 0x2b, 0x78, 0x35, 0x00, 0x72, 0xe2, 0x07, 0xd4, 0x67, 0xba, 0x20, 0xc5, 0xed, + 0xa1, 0x1c, 0xf9, 0x39, 0x25, 0x72, 0x8b, 0x64, 0x8e, 0x9f, 0x6f, 0x86, 0x0e, 0x40, 0xa4, 0xc4, + 0x69, 0xe6, 0x56, 0x70, 0xf0, 0x20, 0x6c, 0xeb, 0xfb, 0x12, 0xbc, 0x3e, 0x1a, 0x2c, 0xcd, 0x17, + 0x4e, 0x25, 0x9c, 0x99, 0xd7, 0x43, 0x8f, 0x54, 0x13, 0x06, 0x0d, 0x28, 0x57, 0x32, 0x06, 0xc7, + 0x60, 0x1c, 0xc1, 0x86, 0xa6, 0x9b, 0x65, 0xec, 0x60, 0x6c, 0x11, 0x7d, 0x43, 0x12, 0xdf, 0xc6, + 0xed, 0x4f, 0x9d, 0x04, 0x1b, 0xc0, 0x59, 0xa9, 0xa0, 0x2d, 0x32, 0x43, 0x27, 0x9e, 0x85, 0x8d, + 0x24, 0x0f, 0xf6, 0xaa, 0x66, 0x0c, 0xad, 0xd8, 0x40, 0xec, 0xa0, 0x64, 0x84, 0xb0, 0xb0, 0x9d, + 0xed, 0x92, 0x5c, 0x72, 0xbe, 0x24, 0x74, 0x5a, 0x72, 0x4d, 0x39, 0xc1, 0x25, 0x72, 0xd4, 0x64, + 0xc4, 0xab, 0x15, 0x82, 0x6c, 0xa0, 0x20, 0xdb, 0x15, 0x3b, 0x08, 0xd6, 0xdb, 0x1d, 0x07, 0x12, + 0x57, 0xcb, 0xf7, 0x88, 0xc7, 0xe7, 0x8e, 0x89, 0x17, 0xe3, 0xc9, 0x79, 0xee, 0xc0, 0x8f, 0x34, + 0x10, 0xcd, 0x15, 0x25, 0x82, 0x84, 0x60, 0x78, 0x07, 0x8f, 0xf1, 0xb0, 0x93, 0xa5, 0xa9, 0xc4, + 0x7e, 0x9d, 0xf3, 0x49, 0xb1, 0x5f, 0xcb, 0xb9, 0xe9, 0xd2, 0x5a, 0x7d, 0xf2, 0x0c, 0xf6, 0x2a, + 0x60, 0x29, 0xd6, 0x47, 0x80, 0x24, 0x88, 0x2d, 0x0c, 0x48, 0xb0, 0xe1, 0x86, 0xe4, 0x52, 0x27, + 0xd4, 0x35, 0x8e, 0xa7, 0x6e, 0xc7, 0x1e, 0x99, 0x6a, 0x7e, 0x5b, 0x24, 0x8a, 0x48, 0xfb, 0x64, + 0x73, 0x00, 0xd4, 0x2f, 0x22, 0xd7, 0x94, 0x1f, 0xd4, 0xcb, 0xe5, 0xf7, 0x84, 0x37, 0x12, 0xf7, + 0x11, 0xb4, 0xbb, 0x47, 0x43, 0x43, 0x4e, 0xf7, 0x7d, 0x19, 0x41, 0xc7, 0x54, 0x8d, 0x1a, 0x33, + 0xa1, 0x8e, 0xdb, 0xf3, 0xe6, 0x77, 0x87, 0x52, 0xe5, 0x9a, 0x60, 0x36, 0x1c, 0x6d, 0x56, 0x78, + 0x34, 0xe7, 0xee, 0xca, 0xa7, 0x23, 0x39, 0xff, 0x56, 0x3c, 0x96, 0xbf, 0x7e, 0xf6, 0xaf, 0xa0, + 0x09, 0x05, 0x9d, 0xe0, 0x2f, 0xbd, 0xe2, 0x25, 0xdd, 0x62, 0x1d, 0xa0, 0x79, 0x0d, 0x86, 0x34, + 0x5c, 0x4a, 0x00, 0xc1, 0x75, 0xa9, 0x15, 0x24, 0x6d, 0x8d, 0xfc, 0xd7, 0x60, 0x90, 0x1f, 0x05, + 0x1f, 0x97, 0xed, 0x06, 0xea, 0x4d, 0x16, 0xae, 0x79, 0xf8, 0xaf, 0x11, 0x51, 0x20, 0x1f, 0x0c, + 0xdd, 0x18, 0x1b, 0x1e, 0x7a, 0x1a, 0x38, 0x2c, 0x5f, 0xd3, 0x23, 0x96, 0x39, 0x41, 0x0e, 0xbd, + 0xab, 0x4e, 0x16, 0x0c, 0x31, 0x19, 0x0f, 0x06, 0x22, 0x92, 0x5a, 0x1b, 0x00, 0x0b, 0x13, 0xb3, + 0xa0, 0x63, 0x62, 0x0f, 0x75, 0x2f, 0xf4, 0xde, 0x30, 0x71, 0xa5, 0x02, 0x4d, 0x9e, 0x6c, 0xd7, + 0x28, 0xde, 0x4c, 0x83, 0xd8, 0x00, 0xbb, 0xbb, 0x45, 0xbe, 0xbe, 0x30, 0x64, 0x8a, 0x2a, 0x57, + 0x2c, 0x72, 0x8e, 0x6b, 0x18, 0xbf, 0x88, 0xf4, 0xa7, 0x82, 0x91, 0xfb, 0x7d, 0x0c, 0xad, 0x06, + 0xb9, 0x86, 0xa8, 0x95, 0x15, 0x1e, 0xc8, 0xb7, 0x6f, 0xd8, 0x80, 0xa1, 0xca, 0x97, 0x0f, 0x0f, + 0x87, 0x37, 0x04, 0x2c, 0x1a, 0x58, 0xbb, 0xfa, 0x87, 0x14, 0x73, 0xf8, 0x70, 0xbe, 0x49, 0xfe, + 0x69, 0xd8, 0xb9, 0x15, 0xb4, 0xf9, 0xd4, 0x5c, 0xd1, 0x33, 0x1a, 0x28, 0x3b, 0x63, 0xc0, 0x77, + 0xd8, 0xa5, 0x26, 0xe5, 0x1a, 0xff, 0x24, 0xda, 0xcb, 0xa3, 0xf4, 0x42, 0x6f, 0x34, 0x8c, 0x31, + 0x20, 0x28, 0xa8, 0x2b, 0x1f, 0x65, 0x85, 0x84, 0xca, 0x17, 0x58, 0x46, 0xb8, 0x2f, 0xb8, 0x43, + 0x17, 0xdc, 0x91, 0x18, 0xdc, 0xa1, 0x95, 0x9f, 0x0a, 0x4d, 0x31, 0xde, 0x12, 0xb4, 0xc4, 0x63, + 0x88, 0x17, 0x84, 0x18, 0x59, 0x03, 0x61, 0xb2, 0x9c, 0xf5, 0x50, 0x48, 0xc7, 0x92, 0x2c, 0xf2, + 0xf2, 0x87, 0xee, 0xd2, 0x31, 0x13, 0x62, 0x9f, 0xcc, 0x0a, 0x2b, 0x24, 0x17, 0xb8, 0xff, 0x5a, + 0xa9, 0x3c, 0x91, 0x40, 0x68, 0xfc, 0xb8, 0x6e, 0xde, 0x69, 0x72, 0x25, 0x61, 0x70, 0x85, 0x31, + 0x90, 0x70, 0xa3, 0x62, 0x9e, 0xe4, 0x8a, 0x37, 0x0c, 0x4d, 0x33, 0x27, 0x3a, 0x66, 0x44, 0xae, + 0xd1, 0xe6, 0x83, 0x61, 0xd4, 0xc8, 0x9f, 0x4d, 0xa0, 0xc6, 0x85, 0xe2, 0x05, 0xb3, 0xe1, 0x77, + 0xf0, 0xa9, 0x38, 0xfb, 0xbb, 0x66, 0xaa, 0xf3, 0x56, 0x8e, 0xea, 0x3c, 0x98, 0x7a, 0x13, 0x9a, + 0x06, 0x58, 0x65, 0x14, 0x35, 0x0d, 0xda, 0x51, 0xd3, 0x82, 0x12, 0x80, 0xdf, 0x19, 0xc7, 0x70, + 0x7b, 0xeb, 0x67, 0x15, 0x68, 0x71, 0x4d, 0x25, 0xb0, 0x26, 0xd6, 0x99, 0x21, 0x59, 0x74, 0x87, + 0x90, 0x75, 0x91, 0xd9, 0x89, 0x10, 0x49, 0x70, 0xaf, 0x34, 0x72, 0xfb, 0xfb, 0x48, 0x5f, 0xdf, + 0x8d, 0xe8, 0x3e, 0xce, 0x9d, 0x03, 0x26, 0xab, 0xea, 0x26, 0x13, 0xa0, 0xce, 0xac, 0xa5, 0x94, + 0xb5, 0x98, 0x72, 0x73, 0x90, 0x24, 0x48, 0x81, 0x55, 0x73, 0x70, 0x8a, 0xd9, 0x0d, 0x59, 0x2c, + 0x2b, 0xed, 0xd0, 0x56, 0x5f, 0xe5, 0xaa, 0x13, 0xd0, 0x21, 0x59, 0xf6, 0x32, 0x1e, 0xf4, 0x46, + 0xbd, 0x86, 0x9b, 0x33, 0xca, 0x30, 0x9e, 0x7f, 0x72, 0xfb, 0x4f, 0xe6, 0xd8, 0x19, 0xb0, 0xed, + 0x26, 0x85, 0x80, 0xf2, 0xef, 0x29, 0x5d, 0xe2, 0x48, 0x43, 0xf5, 0x55, 0xe7, 0x34, 0xe9, 0x51, + 0x29, 0x4b, 0xf5, 0x0e, 0x76, 0x20, 0x29, 0x2f, 0x2b, 0x87, 0x14, 0x8b, 0x8f, 0xe2, 0x83, 0x3f, + 0x82, 0xf4, 0x41, 0xb4, 0x56, 0xa0, 0x0e, 0x56, 0xe8, 0x82, 0x15, 0x89, 0x26, 0x53, 0x7e, 0x5e, + 0x30, 0x2f, 0x0e, 0x04, 0x0a, 0xbe, 0x90, 0xe6, 0xe0, 0xf5, 0xda, 0x1a, 0x23, 0x59, 0xb6, 0xe3, + 0x2d, 0xea, 0x6e, 0xd9, 0xc1, 0xf9, 0x0b, 0x1f, 0x3c, 0xa0, 0x9b, 0x07, 0x71, 0x8a, 0xe4, 0x48, + 0x94, 0xd2, 0x75, 0xa4, 0x2b, 0xda, 0xe7, 0x2c, 0xd4, 0x5f, 0xd5, 0x07, 0xe7, 0x0d, 0x25, 0xb4, + 0x1e, 0x42, 0x30, 0xc3, 0x69, 0x2e, 0xa3, 0x0b, 0xb6, 0x61, 0xbe, 0x0b, 0x58, 0x9f, 0x07, 0x82, + 0x11, 0xc8, 0x05, 0xce, 0x04, 0x4d, 0x38, 0xfa, 0xdb, 0x38, 0x37, 0xdb, 0x2f, 0x4d, 0x44, 0x94, + 0x62, 0x2f, 0xc3, 0x26, 0x17, 0xc8, 0x31, 0x05, 0xcd, 0x71, 0x30, 0x1e, 0x90, 0xf4, 0x20, 0x76, + 0x67, 0x1b, 0xc5, 0xf3, 0x8c, 0x32, 0xb8, 0xa1, 0x8f, 0x5c, 0x4e, 0xf0, 0x39, 0xde, 0x0b, 0xcd, + 0x0f, 0xc0, 0xe4, 0xa2, 0x9c, 0x3e, 0x5f, 0x71, 0xae, 0x15, 0xd9, 0xa0, 0x8b, 0x41, 0x4d, 0x50, + 0x29, 0x17, 0x15, 0xbf, 0xcd, 0xa1, 0x5c, 0xfb, 0x70, 0xe2, 0xc8, 0x45, 0x45, 0x52, 0x34, 0x7a, + 0x1e, 0x1e, 0xa1, 0x21, 0xaf, 0x34, 0x2a, 0xcf, 0x8e, 0x97, 0x31, 0x74, 0x6f, 0x2d, 0x9c, 0x34, + 0xec, 0x59, 0x2e, 0x06, 0x7a, 0x36, 0xf0, 0x27, 0x19, 0x7b, 0xb5, 0x91, 0x05, 0x1d, 0x39, 0x31, + 0x7e, 0x38, 0xaa, 0x89, 0x57, 0xe1, 0xea, 0x4b, 0xe3, 0xe4, 0xff, 0x98, 0x1f, 0x5a, 0x7a, 0x9b, + 0x94, 0xf2, 0x3a, 0x3d, 0x88, 0x77, 0x6a, 0x61, 0x55, 0x86, 0xf1, 0x5c, 0xf5, 0x69, 0x34, 0x14, + 0x3f, 0xd6, 0xf8, 0x3b, 0x01, 0x50, 0x2b, 0xbb, 0x42, 0x80, 0x8d, 0xb8, 0x05, 0x8d, 0x3f, 0x4a, + 0x0f, 0xc6, 0xaf, 0xe6, 0xd9, 0xf1, 0x24, 0x37, 0xcf, 0xe2, 0x71, 0x37, 0xf6, 0x82, 0xfb, 0x88, + 0xd3, 0xb7, 0x4d, 0x1c, 0x9e, 0x7e, 0x9f, 0x0a, 0xd9, 0x48, 0x9b, 0x60, 0xdf, 0x73, 0x3e, 0x90, + 0x42, 0xf9, 0x5a, 0xfd, 0x16, 0x54, 0x57, 0x35, 0x60, 0xc7, 0xaa, 0x21, 0xa6, 0x52, 0xcd, 0x08, + 0x87, 0xec, 0xeb, 0x40, 0x26, 0x3b, 0x5e, 0xc3, 0x43, 0x1f, 0xf7, 0xb6, 0x3e, 0x08, 0xa0, 0x56, + 0xab, 0xf1, 0x44, 0xfa, 0xb6, 0x27, 0x4e, 0x6d, 0x68, 0xe6, 0xfe, 0x85, 0x40, 0x03, 0xc8, 0x92, + 0x49, 0x1e, 0xf8, 0xbe, 0x82, 0xc3, 0x6a, 0x95, 0xe4, 0xb1, 0x22, 0x5c, 0xb3, 0xef, 0x8b, 0x09, + 0xbe, 0x8e, 0x29, 0x96, 0xe0, 0x4e, 0x35, 0x9e, 0x19, 0xc2, 0xf4, 0x45, 0x23, 0xd3, 0xff, 0x00, + 0xba, 0xbd, 0x8d, 0x6b, 0x22, 0xab, 0x35, 0x84, 0x2e, 0x4e, 0x12, 0xc0, 0xab, 0x6e, 0x23, 0xc9, + 0xd9, 0x20, 0xc5, 0x34, 0xd2, 0xec, 0x93, 0x56, 0xab, 0xd0, 0x9b, 0x82, 0xc8, 0x95, 0xbf, 0xf6, + 0x7b, 0x56, 0x7f, 0x22, 0x8d, 0xdb, 0x3f, 0x0e, 0xc2, 0x48, 0x21, 0x32, 0xcb, 0xff, 0x37, 0xf4, + 0xb8, 0x9a, 0xe9, 0x11, 0x0a, 0xd8, 0xac, 0x99, 0xdc, 0xfe, 0x26, 0x71, 0x60, 0x91, 0x33, 0xa1, + 0x2a, 0xa8, 0xac, 0xe2, 0x26, 0xc4, 0x08, 0x35, 0xd5, 0x29, 0x0d, 0xe0, 0x39, 0xd6, 0xaa, 0x1e, + 0x5d, 0xed, 0xbf, 0xda, 0xa0, 0x14, 0x60, 0x87, 0xb8, 0xe6, 0x3e, 0x07, 0x7b, 0x04, 0x7a, 0xe3, + 0x05, 0x17, 0x88, 0xab, 0x85, 0xab, 0xae, 0x8e, 0xa0, 0x47, 0xc1, 0xdc, 0x7e, 0x90, 0x53, 0xa7, + 0x79, 0xe5, 0x4c, 0x6e, 0x8f, 0x03, 0x6a, 0x0c, 0x60, 0x8c, 0x4b, 0x71, 0x7c, 0x1f, 0xb8, 0xc7, + 0x92, 0x19, 0x9a, 0x9f, 0xd5, 0x79, 0x0a, 0x67, 0x42, 0x04, 0x62, 0xa8, 0x27, 0xae, 0x00, 0xf7, + 0xe2, 0x3c, 0xd0, 0x8d, 0x1a, 0xe3, 0x37, 0x64, 0xc0, 0xf3, 0xe4, 0xbd, 0x33, 0x49, 0xdd, 0xbc, + 0x41, 0xcf, 0xb3, 0x37, 0xc0, 0xab, 0x14, 0x1e, 0x73, 0x07, 0x6b, 0x8d, 0xdf, 0x70, 0xd5, 0x10, + 0xba, 0x31, 0x19, 0x62, 0xdd, 0x75, 0x72, 0xc9, 0xbf, 0xb2, 0x6a, 0x90, 0xc5, 0xf3, 0xf6, 0x3d, + 0x09, 0x38, 0xe0, 0xd9, 0x83, 0x4c, 0x7f, 0x30, 0x38, 0xd3, 0x47, 0x5a, 0xe6, 0x04, 0x81, 0xe7, + 0x86, 0xe6, 0xc3, 0x58, 0xf6, 0xc4, 0xc5, 0x72, 0xfc, 0xd9, 0x43, 0xf4, 0x5c, 0x3e, 0xd3, 0x07, + 0x1e, 0x46, 0x47, 0x06, 0x3a, 0xba, 0xc6, 0x6f, 0xc4, 0xa0, 0x8a, 0xdb, 0x73, 0x84, 0xfa, 0x3b, + 0xfa, 0x73, 0x95, 0xcf, 0x45, 0xb2, 0x82, 0x8d, 0xdb, 0xbf, 0x3e, 0xc2, 0x7d, 0xc2, 0xb9, 0xc9, + 0x70, 0xc6, 0xf1, 0xc3, 0xca, 0x15, 0xd9, 0xc2, 0x9a, 0xca, 0x81, 0x28, 0x47, 0x46, 0xe5, 0x73, + 0xac, 0x51, 0x48, 0xf1, 0x64, 0xc6, 0xde, 0x26, 0xe8, 0xcf, 0xc4, 0xde, 0x4e, 0xc1, 0x73, 0x52, + 0x4e, 0xbc, 0x89, 0xf6, 0xd2, 0x77, 0xdb, 0x53, 0x3d, 0x05, 0x79, 0xed, 0xc9, 0x8b, 0x02, 0x66, + 0xc8, 0xd9, 0x54, 0xda, 0x34, 0xbd, 0x19, 0x2a, 0xd6, 0x39, 0x03, 0xc7, 0xdb, 0xc7, 0x42, 0x80, + 0x3c, 0xef, 0x0c, 0x7b, 0x52, 0x0c, 0x46, 0x92, 0xb3, 0x3b, 0xff, 0x0d, 0x54, 0xf5, 0x2c, 0x31, + 0x06, 0xde, 0x67, 0x9d, 0x0b, 0xc0, 0xa3, 0x01, 0x1f, 0x1d, 0x3b, 0x87, 0x7d, 0x74, 0xa9, 0xe0, + 0x82, 0xf0, 0xe3, 0x90, 0x58, 0xc1, 0x17, 0x8d, 0xdf, 0xa3, 0xc1, 0x42, 0xf9, 0x5d, 0x94, 0x90, + 0x6b, 0x74, 0xb5, 0x5a, 0x6e, 0x7f, 0x1d, 0x74, 0x17, 0x7d, 0x33, 0x09, 0x04, 0x87, 0x67, 0xf5, + 0xc1, 0xca, 0x81, 0x59, 0x9e, 0x35, 0x37, 0xb8, 0xf4, 0x33, 0x06, 0xbe, 0x95, 0xcb, 0x32, 0x06, + 0x00, 0xff, 0xc5, 0xfa, 0xa0, 0x54, 0x00, 0xe0, 0x99, 0x2b, 0x66, 0x8a, 0xfd, 0x0b, 0x9d, 0xe3, + 0xc5, 0xfe, 0x15, 0xce, 0xe9, 0xfe, 0x49, 0x9e, 0x7c, 0xd6, 0xd0, 0x5c, 0x31, 0xbe, 0xf2, 0xf9, + 0x15, 0xb3, 0x56, 0x38, 0x27, 0x01, 0x17, 0x71, 0x9a, 0xd5, 0x86, 0x01, 0xe1, 0x73, 0x72, 0xa6, + 0x41, 0x29, 0x21, 0x02, 0x77, 0x4d, 0xef, 0x55, 0x85, 0xd4, 0x47, 0x72, 0xb5, 0x38, 0xef, 0xc7, + 0xa8, 0x67, 0x3f, 0xac, 0xe8, 0xd4, 0xbc, 0x3a, 0xd6, 0x07, 0xbc, 0x76, 0x9f, 0x03, 0xad, 0x02, + 0xb8, 0x8e, 0x7f, 0xa7, 0xde, 0x8b, 0x2c, 0xa5, 0xc7, 0x00, 0x91, 0x2a, 0x9f, 0x7f, 0x34, 0x08, + 0xc2, 0x82, 0x47, 0xac, 0xd2, 0xb3, 0x11, 0x18, 0xc2, 0x68, 0xa9, 0xf3, 0x13, 0x14, 0xda, 0xe5, + 0x1c, 0xe5, 0x38, 0x9c, 0x4a, 0xba, 0x84, 0x47, 0x15, 0x31, 0x86, 0xa6, 0x1d, 0x3f, 0x8a, 0x14, + 0x5a, 0x40, 0xaf, 0x72, 0xe5, 0x89, 0x73, 0x15, 0x59, 0x1f, 0xf0, 0xdd, 0x9c, 0xe0, 0xfb, 0x66, + 0x0a, 0x3a, 0x7b, 0xf9, 0x39, 0x20, 0xab, 0x54, 0xca, 0x9f, 0x8b, 0xa1, 0xf7, 0x2d, 0x54, 0xd0, + 0x89, 0xf9, 0xda, 0x21, 0x7a, 0x13, 0xe7, 0x4e, 0x05, 0x47, 0x3f, 0x2f, 0x17, 0x87, 0xee, 0x55, + 0x0e, 0xbd, 0xf3, 0x4a, 0xc1, 0xf3, 0x6b, 0x93, 0x65, 0xa5, 0xe4, 0x7f, 0x70, 0xec, 0xfc, 0x67, + 0x1f, 0x0c, 0x1f, 0x99, 0x53, 0xa8, 0xba, 0x07, 0x87, 0xb7, 0xb2, 0xaa, 0xe3, 0x68, 0x5b, 0x94, + 0xa3, 0x19, 0xd0, 0x0e, 0xe3, 0x35, 0xb6, 0x89, 0xf0, 0xad, 0x7a, 0x3c, 0x40, 0x24, 0x2d, 0x10, + 0xf8, 0x56, 0xee, 0x4a, 0x60, 0x76, 0xcf, 0x22, 0x3e, 0x70, 0x86, 0xe4, 0x41, 0x98, 0x1a, 0xa4, + 0x3a, 0x2e, 0x2b, 0xf2, 0xf1, 0x18, 0xf1, 0x12, 0xaa, 0x34, 0xc8, 0x84, 0xf0, 0xa7, 0xa3, 0xf8, + 0x05, 0x9b, 0x4b, 0xa9, 0x1a, 0x42, 0x98, 0x5d, 0x74, 0xa5, 0x5a, 0xc9, 0xd8, 0x46, 0xd2, 0xb4, + 0x04, 0xbc, 0xa2, 0xdd, 0x6a, 0xf2, 0x03, 0x15, 0x38, 0x44, 0xd4, 0x8f, 0xbe, 0x9a, 0x01, 0x6e, + 0x96, 0xb4, 0x3a, 0x02, 0x1c, 0x07, 0x69, 0x9d, 0x96, 0x64, 0x5e, 0xee, 0x97, 0x56, 0xc7, 0x28, + 0x4f, 0x77, 0x0c, 0x3d, 0x15, 0xb1, 0x64, 0x00, 0xe7, 0x79, 0x85, 0xde, 0xa5, 0xca, 0x78, 0x76, + 0x44, 0x9d, 0xe9, 0x78, 0x36, 0x03, 0x9d, 0xe9, 0xe3, 0xbd, 0xfc, 0x85, 0xd1, 0x8b, 0xba, 0x33, + 0x27, 0xbc, 0xa8, 0x24, 0xb9, 0xf9, 0xc1, 0xd0, 0x31, 0x0a, 0x4e, 0xbc, 0x46, 0xdb, 0x98, 0x1a, + 0xf7, 0xc7, 0x29, 0x2c, 0xd3, 0x98, 0x1a, 0xff, 0x30, 0x84, 0x7e, 0xe0, 0x87, 0x49, 0x6b, 0xd5, + 0x24, 0x23, 0x91, 0xac, 0xd7, 0xa1, 0x49, 0xcb, 0x50, 0x75, 0x44, 0x02, 0x27, 0xec, 0x17, 0x73, + 0x59, 0xc6, 0xaf, 0xb1, 0xff, 0xda, 0x42, 0x4f, 0x64, 0x57, 0x29, 0xf7, 0xc3, 0xc9, 0xa0, 0x33, + 0xf6, 0xfb, 0xb1, 0xaa, 0xdb, 0xfe, 0x47, 0x70, 0x20, 0xfc, 0x7e, 0xfb, 0xcf, 0x4c, 0xf0, 0xd5, + 0x8e, 0xb6, 0xd8, 0x02, 0x72, 0x00, 0x68, 0xc5, 0xb3, 0x3e, 0xbd, 0xd7, 0x70, 0xb6, 0xa2, 0xb4, + 0x36, 0x01, 0x76, 0xa8, 0xe5, 0x7a, 0x6f, 0xe5, 0xed, 0x99, 0x5c, 0x86, 0xcf, 0xff, 0xc3, 0x34, + 0xbd, 0xb7, 0xca, 0x87, 0x7a, 0x88, 0xde, 0x53, 0x43, 0xdf, 0x75, 0x7d, 0x03, 0xec, 0xa7, 0xb0, + 0x43, 0x82, 0x4a, 0x1a, 0xce, 0x72, 0xaf, 0xd6, 0xe9, 0xbd, 0xea, 0x2b, 0xc2, 0x52, 0x80, 0x37, + 0x60, 0x3c, 0xea, 0xff, 0x7e, 0x9a, 0xfe, 0x6a, 0x18, 0xbe, 0x9e, 0x5c, 0x07, 0xf8, 0xeb, 0x63, + 0xe1, 0x01, 0x7a, 0x1c, 0xce, 0x21, 0xbc, 0xb1, 0x69, 0x94, 0xc3, 0xb9, 0x14, 0xdc, 0x62, 0xc9, + 0xa8, 0xdc, 0xce, 0x6b, 0xd1, 0xa6, 0xa5, 0x6a, 0x28, 0xb9, 0xb8, 0xd7, 0xbc, 0xc4, 0xd8, 0x19, + 0x7d, 0x96, 0xdb, 0x0b, 0x41, 0xd5, 0x6b, 0x3e, 0xb5, 0x8f, 0x73, 0x27, 0xd0, 0x43, 0xcb, 0x38, + 0xbc, 0x74, 0x04, 0x77, 0x82, 0x07, 0xb8, 0xb6, 0x46, 0xbe, 0x35, 0x14, 0xc8, 0x86, 0x8f, 0x15, + 0x82, 0xe0, 0xf2, 0x99, 0x61, 0x3f, 0x6c, 0x97, 0x72, 0xb5, 0xa4, 0xe0, 0x14, 0x31, 0x1f, 0x97, + 0x9c, 0x57, 0xee, 0xb0, 0x7d, 0xe0, 0xf7, 0x11, 0x97, 0xd7, 0x30, 0x00, 0xfa, 0x01, 0xee, 0x47, + 0x1d, 0x69, 0x24, 0xc6, 0x16, 0x4e, 0x54, 0xae, 0x06, 0x9a, 0xf4, 0x60, 0x92, 0xe7, 0x83, 0x6f, + 0x7e, 0x79, 0x9a, 0xf1, 0x1a, 0xbd, 0x7e, 0xa2, 0xa7, 0x83, 0x0e, 0x15, 0x39, 0x49, 0x5a, 0x48, + 0x81, 0x3c, 0xaf, 0x21, 0xe1, 0x06, 0x84, 0x38, 0x86, 0x6e, 0x90, 0x21, 0xd8, 0x01, 0x07, 0xb8, + 0xf4, 0xdb, 0xf4, 0xea, 0xaa, 0x5b, 0x32, 0x82, 0x01, 0x3c, 0x2e, 0x6d, 0x6c, 0xee, 0x27, 0x67, + 0xc1, 0x9e, 0x83, 0x55, 0x67, 0xeb, 0x26, 0x63, 0x7c, 0xdb, 0x2e, 0x31, 0xf9, 0x96, 0x9c, 0x5c, + 0xf0, 0xd3, 0xf3, 0x82, 0x49, 0x72, 0xf5, 0xf8, 0xb0, 0x0b, 0xf9, 0x34, 0xdb, 0x43, 0x0a, 0xda, + 0x58, 0xa1, 0x25, 0xd6, 0x05, 0x8b, 0xe8, 0x9c, 0xd7, 0x05, 0xda, 0x90, 0x30, 0x88, 0xf0, 0xe5, + 0x1a, 0xc9, 0xd5, 0x04, 0x51, 0x31, 0xe0, 0x6e, 0xec, 0x94, 0x04, 0x99, 0x34, 0x45, 0xb7, 0x70, + 0x7b, 0xc1, 0x23, 0x38, 0x65, 0xe8, 0xa9, 0xe1, 0x03, 0x15, 0x33, 0x88, 0x20, 0x67, 0x60, 0x1a, + 0x04, 0xd4, 0x93, 0x7e, 0xc9, 0xe5, 0x25, 0x2e, 0x90, 0xc2, 0x6b, 0x10, 0x1a, 0x70, 0xee, 0x09, + 0x20, 0x00, 0x78, 0x08, 0x2a, 0xc0, 0x96, 0xbe, 0x54, 0xd9, 0x77, 0x77, 0x59, 0xa8, 0x00, 0x3c, + 0x32, 0x0e, 0x04, 0x20, 0x36, 0x07, 0x05, 0x60, 0x4c, 0xa0, 0xa4, 0xf1, 0xb5, 0x45, 0x2a, 0x81, + 0x92, 0x56, 0xae, 0x7a, 0x20, 0xe4, 0xc4, 0xc5, 0x59, 0x64, 0xe1, 0x81, 0xd1, 0x4e, 0x1c, 0x40, + 0x8b, 0xde, 0x36, 0xb1, 0xbf, 0x10, 0x24, 0x40, 0xa9, 0x30, 0xaa, 0x3d, 0x39, 0xbf, 0xf0, 0xa4, + 0xb5, 0x89, 0x83, 0xf7, 0x81, 0x8c, 0x84, 0xeb, 0x48, 0x53, 0x5f, 0x2b, 0xb7, 0x46, 0x29, 0xe6, + 0x61, 0x0c, 0xc2, 0xab, 0x6b, 0x13, 0xf4, 0xe7, 0x40, 0x9c, 0x62, 0x6a, 0x12, 0xb5, 0xb5, 0x4f, + 0xc6, 0xb2, 0xe9, 0xfe, 0xee, 0x06, 0x95, 0x96, 0x51, 0xf8, 0x6e, 0x41, 0x10, 0xb3, 0xba, 0x36, + 0xa2, 0x76, 0x66, 0x72, 0x9b, 0x70, 0x0f, 0x68, 0x27, 0x50, 0x26, 0xbe, 0x56, 0xb5, 0xb8, 0x76, + 0xb6, 0x3e, 0x2b, 0xb9, 0xcd, 0xd9, 0xa5, 0x3f, 0x91, 0xdc, 0xc6, 0xbd, 0xea, 0xf3, 0x64, 0x46, + 0x07, 0xfd, 0x10, 0xd4, 0x6f, 0x1a, 0xf6, 0xa0, 0xe9, 0xd0, 0xb0, 0x1d, 0x91, 0xfa, 0xca, 0xfa, + 0x63, 0xe0, 0x43, 0x9f, 0xd6, 0x55, 0xde, 0xbe, 0x8f, 0xdb, 0x1f, 0xcb, 0x65, 0x04, 0xc8, 0xd9, + 0x4a, 0xdf, 0x31, 0x72, 0x49, 0x3c, 0xa3, 0xab, 0x1c, 0x00, 0xdc, 0x06, 0x21, 0xea, 0x5c, 0xae, + 0x8c, 0x9c, 0x4a, 0xfb, 0xa8, 0x92, 0xa0, 0x37, 0xb7, 0x3f, 0x4e, 0x4f, 0x7c, 0x08, 0xd8, 0x18, + 0x06, 0xec, 0x57, 0x3a, 0x9e, 0x17, 0x4f, 0x2a, 0xe5, 0x2b, 0x59, 0x86, 0x1b, 0xce, 0x13, 0x80, + 0x41, 0xcb, 0x68, 0x0c, 0x46, 0x42, 0x24, 0x10, 0x3d, 0x30, 0xd0, 0x3a, 0xc9, 0x8c, 0x4e, 0xe6, + 0x5a, 0x7d, 0xb0, 0x36, 0xf1, 0xd1, 0xe5, 0x89, 0xcb, 0x85, 0xc9, 0x7a, 0x2f, 0x2c, 0xf7, 0x5e, + 0xc3, 0x80, 0xe7, 0xc7, 0xac, 0xe0, 0xf7, 0x4f, 0xd2, 0x7b, 0xfd, 0x31, 0xdc, 0xab, 0x5e, 0x6e, + 0xbf, 0xd7, 0x93, 0xc9, 0x04, 0x47, 0xf5, 0x37, 0x29, 0x03, 0xac, 0x83, 0xae, 0x78, 0xf1, 0x89, + 0xa8, 0x69, 0x92, 0x41, 0x98, 0x01, 0xc3, 0x64, 0xd2, 0x5c, 0x59, 0x77, 0x8c, 0x9c, 0x44, 0x54, + 0x90, 0xbe, 0x97, 0x49, 0x1d, 0x69, 0x80, 0x1a, 0xb1, 0x49, 0x29, 0x37, 0x18, 0xea, 0x85, 0xa9, + 0x30, 0xcf, 0x09, 0xb4, 0xe2, 0x01, 0x65, 0xaa, 0xa3, 0xfe, 0x58, 0x98, 0x6a, 0x22, 0xe9, 0xd6, + 0x7b, 0x93, 0x41, 0xc9, 0xe8, 0x6c, 0x61, 0xe7, 0x8b, 0xba, 0xc9, 0x6b, 0x80, 0x3f, 0x95, 0xcf, + 0xb3, 0x2c, 0xe3, 0x49, 0x65, 0x85, 0xde, 0x11, 0xbd, 0x53, 0x43, 0xfd, 0xb1, 0x3b, 0x20, 0x38, + 0x1e, 0xf0, 0xe2, 0x4e, 0x96, 0xc6, 0x58, 0x72, 0xe4, 0x27, 0x58, 0xe5, 0x00, 0x0f, 0xc6, 0x3e, + 0xe9, 0x5c, 0x25, 0x82, 0x83, 0x90, 0xe0, 0x54, 0x57, 0xde, 0x5e, 0x28, 0x2c, 0x49, 0xf3, 0xab, + 0x40, 0x6f, 0x17, 0x7c, 0x82, 0x2e, 0x84, 0xa1, 0x9e, 0x6a, 0x48, 0xc2, 0x79, 0x47, 0x62, 0x4d, + 0x66, 0x4a, 0x60, 0xb5, 0xe0, 0x83, 0x88, 0xbf, 0x54, 0x85, 0xde, 0xb8, 0x7c, 0x0f, 0x13, 0x8a, + 0xea, 0x21, 0x20, 0xf2, 0xae, 0x01, 0x1b, 0x36, 0xbc, 0x70, 0x0b, 0x55, 0x59, 0x35, 0xac, 0x5c, + 0x0b, 0xa4, 0xd3, 0xf7, 0xd6, 0x26, 0x2e, 0xae, 0x49, 0x4c, 0xca, 0x32, 0x74, 0x09, 0x7f, 0xdb, + 0x34, 0x2c, 0x15, 0x21, 0x88, 0x09, 0x00, 0x41, 0x1a, 0x6a, 0xa6, 0x66, 0xad, 0x15, 0x06, 0x37, + 0x85, 0xbb, 0x9b, 0xb5, 0x0a, 0xf7, 0x0d, 0xbe, 0x1d, 0x93, 0xdd, 0xe7, 0x9c, 0xdf, 0xc7, 0x21, + 0xf4, 0x74, 0x88, 0x6e, 0xe1, 0x6f, 0xfe, 0x69, 0xdc, 0xab, 0xf5, 0xb0, 0x93, 0xbd, 0xd6, 0xa8, + 0xbe, 0x21, 0x70, 0xe4, 0x62, 0x36, 0xc8, 0x5c, 0xb0, 0xe6, 0x49, 0x6d, 0x90, 0x74, 0x0b, 0x3d, + 0x9b, 0x86, 0x51, 0xe0, 0xb5, 0x60, 0xef, 0xa6, 0x28, 0xd2, 0x47, 0xfb, 0x27, 0x27, 0x2e, 0x16, + 0xa2, 0xb3, 0x0c, 0x01, 0xa1, 0xe7, 0x2e, 0x7e, 0x29, 0x5d, 0x6a, 0x51, 0xb4, 0xbd, 0xb2, 0x0a, + 0x6a, 0x59, 0xaf, 0x47, 0x95, 0xda, 0xd7, 0xca, 0x34, 0x85, 0x1b, 0xb8, 0xa3, 0x3e, 0x64, 0xd7, + 0x2f, 0x2a, 0x07, 0xa3, 0x76, 0x46, 0x89, 0xde, 0x5f, 0xf9, 0xa7, 0x53, 0xee, 0x85, 0x8a, 0x27, + 0xfc, 0x5c, 0xa5, 0xaf, 0x45, 0xf4, 0xb6, 0xe8, 0xcf, 0xad, 0xab, 0x1c, 0x88, 0xe1, 0x32, 0xea, + 0x46, 0x5d, 0xc9, 0x86, 0xaf, 0x57, 0x5c, 0x5a, 0xd4, 0x9d, 0x7e, 0x5f, 0xff, 0x0c, 0xb0, 0x7b, + 0xfa, 0x5e, 0xee, 0x68, 0x2c, 0x69, 0x51, 0xfd, 0x62, 0x25, 0x0e, 0x50, 0x87, 0xe3, 0xb5, 0xa8, + 0x8e, 0x29, 0x85, 0x13, 0x7e, 0x6c, 0x69, 0x11, 0xeb, 0x5a, 0x56, 0xc6, 0x1c, 0xc4, 0xa3, 0x25, + 0x2e, 0xa3, 0x45, 0x1c, 0x0c, 0x3a, 0x9f, 0x35, 0x0c, 0xba, 0x76, 0x10, 0x73, 0x1b, 0x6e, 0xe3, + 0xbd, 0xdc, 0x5e, 0xbc, 0x73, 0xc5, 0xfc, 0x17, 0x9f, 0xee, 0x6c, 0x9f, 0x35, 0x40, 0xea, 0xb9, + 0x97, 0xf9, 0x6f, 0x60, 0xb3, 0xfa, 0x0b, 0xf7, 0xf2, 0x1f, 0x63, 0xb6, 0x7d, 0xa3, 0xfe, 0x8c, + 0xad, 0x27, 0xfd, 0xd8, 0x70, 0x11, 0x03, 0x62, 0x9f, 0xba, 0xa3, 0x72, 0x00, 0x2f, 0x6e, 0x9c, + 0xeb, 0x70, 0x9b, 0x69, 0x02, 0x2c, 0x58, 0x63, 0x20, 0xb6, 0x81, 0xf8, 0xc4, 0xb3, 0x0c, 0x1a, + 0xcb, 0x66, 0x7a, 0xd1, 0xa2, 0x6f, 0xd1, 0x9f, 0x8d, 0x46, 0xa7, 0x4b, 0x58, 0xe6, 0x3e, 0xb7, + 0x4b, 0x9f, 0x06, 0x48, 0x77, 0xe4, 0xd1, 0x43, 0x50, 0x0c, 0x42, 0x23, 0x08, 0x1e, 0xa4, 0x62, + 0xa2, 0x54, 0x1c, 0xe5, 0x34, 0x44, 0xc1, 0xb4, 0x01, 0x03, 0x3d, 0xe8, 0x72, 0xd3, 0x7f, 0x93, + 0x16, 0xe9, 0x71, 0x18, 0xd4, 0x09, 0x2d, 0xfe, 0x96, 0xb0, 0x16, 0x08, 0x71, 0xee, 0x5e, 0x67, + 0x99, 0xe4, 0x42, 0x9e, 0x7a, 0x36, 0x26, 0x05, 0xb9, 0xfd, 0xe0, 0xe5, 0x2c, 0x02, 0xd3, 0xed, + 0x9c, 0x2d, 0x15, 0x68, 0xf1, 0x96, 0x33, 0x4f, 0x5e, 0xf1, 0x2d, 0xc6, 0xaf, 0x2a, 0x43, 0xa0, + 0x22, 0x2b, 0x15, 0xcf, 0xfa, 0xd4, 0xf2, 0x47, 0xb4, 0x46, 0xe3, 0x5f, 0x0c, 0xca, 0xd7, 0x30, + 0x6e, 0x91, 0x67, 0x13, 0xeb, 0xdf, 0x98, 0x27, 0x4f, 0x1e, 0x86, 0x9b, 0x4e, 0xea, 0x53, 0x41, + 0x12, 0xb5, 0xd0, 0x6c, 0x91, 0xab, 0x15, 0x60, 0xb6, 0x07, 0x8c, 0xaa, 0x7f, 0xe1, 0x3e, 0x16, + 0x35, 0x39, 0xac, 0x1b, 0xab, 0xa1, 0xae, 0x76, 0xfc, 0xca, 0x45, 0xce, 0x29, 0xe0, 0x20, 0xe3, + 0xa1, 0x73, 0x2f, 0x8a, 0xf6, 0xf9, 0x8a, 0x3f, 0xd5, 0x44, 0xae, 0xce, 0xf0, 0xff, 0x79, 0xf5, + 0xbe, 0x45, 0x95, 0xab, 0x16, 0x39, 0x6f, 0x94, 0x46, 0xd8, 0xf7, 0xe5, 0xe3, 0xcd, 0x6a, 0xf0, + 0x36, 0x1d, 0x0b, 0x7d, 0xeb, 0x53, 0x18, 0x81, 0x45, 0xda, 0x0f, 0xd0, 0xfa, 0xbf, 0x8c, 0xd4, + 0xff, 0x41, 0xa9, 0xff, 0x3d, 0xad, 0x3f, 0x33, 0x52, 0x4f, 0xb0, 0x5e, 0x65, 0xff, 0x84, 0xd6, + 0x1f, 0x08, 0xd7, 0x3b, 0x05, 0x80, 0x75, 0xd1, 0x5b, 0xdb, 0x77, 0x86, 0xeb, 0x56, 0xc1, 0x7c, + 0x5c, 0x1e, 0xd6, 0xfd, 0xeb, 0x48, 0xff, 0x1c, 0x54, 0xd2, 0x8c, 0xa0, 0x01, 0x36, 0xb5, 0x00, + 0x57, 0xbd, 0x1a, 0x6d, 0x7d, 0xf2, 0x22, 0xae, 0x1a, 0x93, 0x3e, 0x0c, 0xe7, 0x39, 0x71, 0x2e, + 0x1e, 0xf1, 0x46, 0x2e, 0xea, 0xc8, 0x82, 0xef, 0x0c, 0x00, 0xa9, 0x7c, 0x2e, 0xb8, 0xc8, 0xf3, + 0x44, 0x50, 0x80, 0x70, 0xd2, 0xd0, 0x03, 0xbb, 0x68, 0x83, 0x2a, 0x92, 0x61, 0xeb, 0xc5, 0xc6, + 0x88, 0x0e, 0x0d, 0x42, 0xdc, 0xdd, 0xcc, 0xd6, 0xd3, 0xb1, 0xb9, 0xcc, 0x7a, 0x6c, 0xe1, 0xf8, + 0xfa, 0x06, 0x08, 0x64, 0x5b, 0x42, 0x57, 0x23, 0xc8, 0x27, 0x4d, 0x6d, 0x81, 0xda, 0xc3, 0xc3, + 0xd6, 0x7c, 0xab, 0x21, 0x2a, 0x6d, 0x2a, 0xb8, 0xb2, 0x6f, 0xe1, 0xcd, 0xae, 0x34, 0xb1, 0xfc, + 0xc1, 0x28, 0x06, 0xef, 0xec, 0xea, 0x74, 0x75, 0x95, 0x83, 0xe0, 0xca, 0xc8, 0xfc, 0x41, 0x76, + 0x74, 0x9b, 0x38, 0x10, 0x79, 0x68, 0x31, 0xec, 0x3c, 0x87, 0xdf, 0x81, 0x3f, 0x5c, 0x66, 0x33, + 0x84, 0x36, 0x99, 0xcd, 0x39, 0xb2, 0x53, 0xb9, 0x52, 0x0e, 0x0a, 0xb7, 0x2c, 0x72, 0x95, 0x72, + 0x5d, 0x6d, 0xbf, 0x07, 0x6f, 0xd1, 0x9f, 0x08, 0xdd, 0x35, 0x33, 0xf2, 0x7d, 0x71, 0xf4, 0x09, + 0xec, 0xe9, 0xca, 0xd0, 0x9d, 0xba, 0x73, 0xc9, 0x41, 0x15, 0xc0, 0x1c, 0x9a, 0x9f, 0xcd, 0x82, + 0xa3, 0x7d, 0xe7, 0x82, 0x8a, 0x9e, 0x87, 0xe6, 0xd8, 0x7d, 0x30, 0xb4, 0x3c, 0x4b, 0x19, 0x45, + 0x9e, 0xf2, 0xdf, 0x0c, 0x23, 0x9b, 0x0e, 0xd0, 0x7d, 0xef, 0x57, 0x5f, 0x44, 0x30, 0xf6, 0x29, + 0x40, 0x5d, 0x59, 0xa5, 0x0c, 0x2b, 0xbf, 0x78, 0x2e, 0x7c, 0xdb, 0x23, 0x76, 0x26, 0x41, 0x9c, + 0x5d, 0xf9, 0xdc, 0x44, 0x96, 0xab, 0xfe, 0x3f, 0x18, 0xe1, 0x08, 0x89, 0xd2, 0xfa, 0x64, 0xe9, + 0xb9, 0x95, 0xa4, 0x79, 0xe6, 0x20, 0xaa, 0x55, 0x46, 0x5f, 0x23, 0xc3, 0x54, 0x06, 0x39, 0x77, + 0x09, 0xb4, 0x72, 0xef, 0x9e, 0x89, 0xf6, 0xdd, 0x8c, 0x26, 0xa7, 0xc1, 0x7a, 0xcc, 0x6b, 0x20, + 0xb0, 0x57, 0xc7, 0x25, 0xd4, 0x19, 0x8c, 0x5a, 0xe2, 0x03, 0x3f, 0x40, 0x5c, 0x4d, 0x23, 0xa4, + 0x78, 0x43, 0x03, 0x0c, 0x92, 0xd0, 0x7d, 0x50, 0x39, 0xf4, 0x5a, 0x1a, 0x81, 0x77, 0xa2, 0x92, + 0x39, 0x9e, 0x9c, 0x8d, 0xee, 0xe2, 0xaa, 0xe7, 0x60, 0x68, 0x73, 0x51, 0x7a, 0x2e, 0x8e, 0xfb, + 0xf0, 0x39, 0x15, 0x1e, 0x31, 0x12, 0xd7, 0x35, 0x62, 0x3c, 0x15, 0x09, 0x63, 0x98, 0x5b, 0x26, + 0x9b, 0xe3, 0x4a, 0x99, 0x7c, 0x62, 0x6e, 0xca, 0x25, 0xc6, 0xe3, 0x39, 0xf2, 0x8a, 0xcf, 0xe9, + 0x99, 0xa2, 0xf8, 0x9c, 0x0e, 0x54, 0xb3, 0x5d, 0x98, 0x2a, 0x65, 0xcc, 0x5d, 0x02, 0xce, 0xc1, + 0xfa, 0x05, 0x54, 0x0b, 0xf9, 0x76, 0xae, 0xba, 0x98, 0x66, 0x00, 0x5d, 0x08, 0x5d, 0x77, 0x49, + 0x15, 0x71, 0x52, 0xc6, 0x6c, 0x90, 0x9c, 0x28, 0x70, 0x86, 0xfc, 0xc9, 0xd2, 0x7a, 0xf0, 0x4e, + 0x41, 0x93, 0x95, 0x4b, 0x22, 0x1e, 0x9c, 0x88, 0xbe, 0xaf, 0xd8, 0x41, 0x50, 0xf6, 0x18, 0xa3, + 0x0c, 0xda, 0xce, 0x55, 0xbf, 0x0f, 0xbd, 0x21, 0xc6, 0xb1, 0x27, 0x86, 0xa3, 0x67, 0x92, 0x31, + 0x9b, 0x8e, 0x91, 0x84, 0xa7, 0xb8, 0xcf, 0x2d, 0xf5, 0xfc, 0x9c, 0x26, 0x51, 0xf5, 0x72, 0x6b, + 0xaf, 0x93, 0xeb, 0xbe, 0xa1, 0x68, 0xdf, 0xed, 0x19, 0x79, 0x96, 0x7c, 0x93, 0xfc, 0xce, 0x85, + 0xd0, 0x59, 0x27, 0xf7, 0x21, 0x78, 0x1d, 0xad, 0x30, 0xea, 0x15, 0x30, 0x3a, 0xdc, 0x87, 0xa7, + 0x31, 0xdb, 0xa3, 0x73, 0x5e, 0x5d, 0xc2, 0x99, 0xe8, 0x4b, 0x9c, 0xdb, 0xc0, 0x2a, 0x29, 0x8f, + 0xbb, 0x54, 0x12, 0x7f, 0xa1, 0xef, 0x2f, 0xc4, 0x07, 0x38, 0xf4, 0xe0, 0x09, 0xb1, 0xab, 0x13, + 0x4a, 0xf5, 0xe4, 0x12, 0x7b, 0x06, 0x3c, 0x89, 0x18, 0xbe, 0x87, 0x73, 0x63, 0x22, 0x53, 0x64, + 0x41, 0xeb, 0x64, 0x97, 0xcc, 0xed, 0x89, 0xc0, 0x6e, 0x46, 0xb5, 0x94, 0x96, 0x2c, 0xad, 0x5d, + 0x49, 0xea, 0x66, 0x36, 0x23, 0x13, 0xd6, 0x92, 0x6e, 0xdf, 0xe0, 0x8c, 0x5c, 0x4b, 0x8e, 0x49, + 0x7e, 0x30, 0x3c, 0x39, 0xf8, 0xd3, 0x6c, 0x1d, 0xf8, 0x46, 0xb1, 0xa7, 0x15, 0x2b, 0x98, 0x1e, + 0xe0, 0xd2, 0x5b, 0x48, 0xcb, 0xbc, 0x56, 0xd2, 0x95, 0x30, 0xb0, 0x82, 0xef, 0x14, 0x2f, 0x33, + 0x98, 0x35, 0x9a, 0xde, 0x64, 0x38, 0x4f, 0xfa, 0x13, 0x02, 0x0e, 0x75, 0xc7, 0x7f, 0xd2, 0xe4, + 0xad, 0xce, 0x9c, 0x7c, 0xb0, 0x1e, 0x6d, 0xd4, 0x28, 0x74, 0x50, 0x0a, 0xc7, 0xe1, 0x61, 0x42, + 0x2d, 0x34, 0x36, 0x66, 0xe9, 0x58, 0x7a, 0xb0, 0xd8, 0x4e, 0xb2, 0xe6, 0x4a, 0xe6, 0x0b, 0xc4, + 0xb2, 0x40, 0x12, 0xe2, 0x25, 0xe0, 0x50, 0xd7, 0x7c, 0x70, 0xee, 0x84, 0xc4, 0x69, 0x42, 0x0b, + 0x39, 0x0f, 0x36, 0xf4, 0xc3, 0x1b, 0xec, 0x79, 0xf0, 0xf5, 0x30, 0xb1, 0xa5, 0x29, 0xa1, 0x95, + 0xdc, 0x9e, 0x77, 0x9e, 0x26, 0xcb, 0x24, 0x34, 0x1a, 0x2e, 0x93, 0x40, 0x42, 0x3f, 0x97, 0x3e, + 0xc4, 0xa5, 0x5f, 0xa6, 0x47, 0x4f, 0xa7, 0x58, 0x30, 0x7e, 0xea, 0xc8, 0x9c, 0xd9, 0x98, 0xe9, + 0xc2, 0x60, 0x1e, 0x8b, 0xb9, 0x85, 0x74, 0xa1, 0x21, 0xba, 0x0c, 0x72, 0x17, 0x3b, 0x08, 0x83, + 0xc3, 0x14, 0x86, 0x2e, 0xe5, 0x98, 0x79, 0x4f, 0x17, 0x58, 0xa9, 0xb0, 0x6d, 0x4a, 0x52, 0x9c, + 0xb7, 0x5a, 0x23, 0x75, 0xe2, 0x45, 0xe5, 0xc4, 0xab, 0xe2, 0xce, 0x88, 0xe4, 0x3e, 0xe9, 0x71, + 0xbd, 0x5e, 0xfa, 0x24, 0x48, 0x8c, 0xdc, 0xdc, 0x4f, 0x0d, 0x84, 0xfe, 0x04, 0x84, 0xff, 0xbd, + 0x59, 0x92, 0xca, 0x83, 0x69, 0x0a, 0xc4, 0xe7, 0x1b, 0x98, 0x01, 0x31, 0xc4, 0x93, 0x39, 0xa6, + 0x7c, 0xdc, 0x8f, 0x27, 0x50, 0x0b, 0x88, 0x8e, 0x67, 0x5c, 0xa9, 0xda, 0xfe, 0xf5, 0x06, 0xb4, + 0x2c, 0xcb, 0xfa, 0xc2, 0xd6, 0x46, 0xab, 0xf7, 0x42, 0x64, 0x45, 0x77, 0x73, 0xd2, 0x25, 0x1c, + 0xf1, 0xcf, 0xab, 0x72, 0xbd, 0x45, 0xa3, 0xa0, 0xe9, 0x12, 0x38, 0x96, 0x66, 0x35, 0x49, 0xa7, + 0x09, 0x86, 0xe9, 0x60, 0xe3, 0x5b, 0x24, 0xe3, 0x05, 0xb2, 0x4e, 0x45, 0x22, 0xc2, 0x98, 0x3e, + 0x39, 0xe6, 0xd4, 0x38, 0x13, 0x48, 0xeb, 0x71, 0x75, 0xdb, 0xf0, 0x44, 0x15, 0xa2, 0xc0, 0x52, + 0x36, 0xcf, 0x7e, 0x14, 0xc8, 0x9a, 0x6f, 0x91, 0xc9, 0x9d, 0x10, 0x06, 0x5c, 0xf5, 0x6e, 0x16, + 0x1b, 0xb9, 0xfd, 0x7c, 0xf7, 0xfb, 0x3f, 0xe6, 0xdc, 0xcf, 0x40, 0x89, 0x02, 0x9e, 0x56, 0x00, + 0x9f, 0x1a, 0x01, 0x34, 0x8d, 0x01, 0x4c, 0x0f, 0x03, 0x5e, 0x57, 0x00, 0x1f, 0x19, 0x01, 0xfc, + 0xde, 0x18, 0xc0, 0x84, 0x30, 0xe0, 0x5f, 0x15, 0xc0, 0x49, 0x23, 0x80, 0x43, 0xcc, 0x68, 0xc0, + 0x00, 0x7d, 0xdb, 0xe3, 0x77, 0x79, 0xa5, 0xaa, 0xbc, 0xd2, 0x48, 0x08, 0xf3, 0xfe, 0x7c, 0x7b, + 0x18, 0xf0, 0x73, 0xc5, 0x56, 0xc7, 0x81, 0xb1, 0x01, 0x08, 0x53, 0x38, 0x65, 0x52, 0x7f, 0x15, + 0x0d, 0x31, 0xaa, 0x37, 0xf4, 0xc8, 0x2b, 0x7d, 0x18, 0xdb, 0x2c, 0xf2, 0x07, 0x23, 0xfd, 0xde, + 0x54, 0x6c, 0xff, 0x84, 0x70, 0xbf, 0x9f, 0x8c, 0xee, 0x57, 0x19, 0xee, 0x97, 0xab, 0xf4, 0x13, + 0xc2, 0xfd, 0x9c, 0x25, 0xa3, 0xfb, 0x3c, 0x3e, 0xd2, 0xc7, 0x69, 0xc2, 0xb3, 0xb1, 0xd2, 0x48, + 0x05, 0x9e, 0x1f, 0x86, 0x37, 0x84, 0x72, 0x56, 0x28, 0xfc, 0xdc, 0x51, 0xf0, 0xba, 0xbc, 0xd2, + 0x88, 0x3c, 0x7b, 0xb2, 0x8a, 0x2e, 0x7c, 0xca, 0x30, 0x7c, 0xb4, 0xad, 0xca, 0xd5, 0x9d, 0xf7, + 0x0d, 0xc4, 0x61, 0xa4, 0x55, 0x3c, 0x9e, 0x39, 0x72, 0xd4, 0x8b, 0xe7, 0xe6, 0xfa, 0xde, 0x7c, + 0x79, 0xc5, 0x10, 0xdd, 0x39, 0x01, 0x74, 0x06, 0xe6, 0x48, 0xdc, 0xb2, 0x94, 0xaa, 0x2c, 0x76, + 0xb0, 0xe3, 0x78, 0x9f, 0x7b, 0x7a, 0x30, 0x3c, 0x4c, 0xa4, 0x24, 0xdc, 0x0a, 0x9d, 0xe9, 0x8d, + 0xa4, 0x47, 0xc4, 0xa1, 0xb7, 0xe8, 0xd2, 0x32, 0x5c, 0xcd, 0x94, 0x71, 0x98, 0x86, 0xd3, 0x06, + 0x43, 0xa1, 0x68, 0x9a, 0xe4, 0x45, 0xbd, 0x0a, 0x62, 0x5e, 0x45, 0x34, 0x57, 0xba, 0xa9, 0x68, + 0xa2, 0x9f, 0x83, 0xa2, 0x69, 0xca, 0x57, 0x60, 0xa9, 0xc3, 0x58, 0x3a, 0x3c, 0xc7, 0x7d, 0x21, + 0x01, 0x0d, 0x35, 0xca, 0x2f, 0xdd, 0x0a, 0x8b, 0xe9, 0xa4, 0x61, 0x21, 0x0d, 0x08, 0xbf, 0xf3, + 0x3f, 0x53, 0xf5, 0xa9, 0x4c, 0x93, 0x7d, 0x41, 0x4e, 0x0b, 0x3f, 0xf9, 0x96, 0xba, 0x22, 0xda, + 0x15, 0xee, 0x24, 0xb4, 0x07, 0xe2, 0x4b, 0x51, 0x78, 0x14, 0xb7, 0x14, 0x9e, 0x53, 0x90, 0xe8, + 0x8e, 0x47, 0xc9, 0x40, 0xdf, 0x65, 0x6e, 0xcd, 0x19, 0xbc, 0x67, 0x6e, 0xea, 0x7b, 0x6f, 0x41, + 0x90, 0x26, 0xcc, 0x70, 0x2f, 0xd7, 0x63, 0x69, 0x2e, 0x4d, 0x28, 0x25, 0x17, 0x23, 0x85, 0x4e, + 0xb0, 0x4a, 0xea, 0x56, 0xf0, 0x64, 0x84, 0x89, 0x7d, 0x56, 0x2d, 0xeb, 0x8b, 0xbd, 0xc8, 0x89, + 0xd5, 0x98, 0x1c, 0x3b, 0x84, 0x66, 0x06, 0xd0, 0x8c, 0xfb, 0x36, 0x44, 0x26, 0xae, 0x7a, 0x7e, + 0x14, 0xf5, 0xdc, 0xc4, 0xa0, 0xca, 0x91, 0x0d, 0x61, 0xe7, 0x31, 0x94, 0x73, 0x4c, 0x33, 0xd0, + 0x5a, 0xf2, 0x3d, 0xfc, 0x05, 0xba, 0xa8, 0xbd, 0x03, 0xe1, 0x45, 0x61, 0xe2, 0x5a, 0xab, 0xd8, + 0xcf, 0x39, 0xa3, 0xc4, 0xfe, 0x28, 0x01, 0xfc, 0xda, 0x36, 0x3c, 0x6e, 0xc1, 0xe4, 0xe6, 0x0c, + 0xb1, 0x51, 0x2b, 0xde, 0x8e, 0x12, 0x1a, 0xe8, 0x12, 0x3a, 0x3e, 0x07, 0xce, 0x01, 0x85, 0xda, + 0x54, 0x51, 0x74, 0xbc, 0x13, 0x1e, 0xf3, 0x05, 0xda, 0x90, 0x53, 0xaa, 0xcd, 0x31, 0xe5, 0xe2, + 0xa0, 0xa9, 0xe1, 0x41, 0x41, 0xd5, 0xb8, 0xea, 0xf7, 0xf0, 0x68, 0xf1, 0xea, 0xfa, 0x4a, 0x57, + 0x2b, 0xc3, 0x55, 0xbf, 0xae, 0xa2, 0x37, 0x23, 0x28, 0x6a, 0x1e, 0x7c, 0x84, 0xd0, 0x24, 0x86, + 0x4c, 0x92, 0x40, 0x5d, 0xb3, 0x55, 0xd2, 0x3a, 0x35, 0xc9, 0x56, 0xd7, 0xae, 0xd3, 0xd4, 0x64, + 0x6b, 0x56, 0x93, 0x17, 0xb4, 0xd2, 0xba, 0x38, 0x92, 0x1d, 0x27, 0x19, 0xaf, 0xe9, 0xaf, 0x62, + 0x3a, 0x73, 0x76, 0x12, 0xd9, 0xb4, 0x92, 0x64, 0x25, 0x13, 0x4b, 0xbc, 0x92, 0xf0, 0x6b, 0x31, + 0xc9, 0xab, 0xff, 0x42, 0x6f, 0x0d, 0x00, 0xfd, 0x07, 0x25, 0x37, 0xcd, 0x1b, 0xcd, 0x32, 0x49, + 0xee, 0x4c, 0xfa, 0xf0, 0x98, 0x44, 0xa1, 0x24, 0x0f, 0xe6, 0x95, 0x92, 0xec, 0x35, 0x24, 0x2b, + 0xf3, 0xf7, 0x6c, 0xcd, 0xa6, 0x54, 0x8b, 0xac, 0xa6, 0xbd, 0x54, 0x8a, 0xc4, 0xa3, 0x6c, 0x90, + 0xac, 0xad, 0xfb, 0xd8, 0x0e, 0x0d, 0x5e, 0xa7, 0x7f, 0x8c, 0xa3, 0xe8, 0xbd, 0x87, 0x12, 0x90, + 0x89, 0x7d, 0x3d, 0xff, 0x85, 0x1e, 0x38, 0x4b, 0xb2, 0x6e, 0x49, 0x69, 0x2a, 0x92, 0xd5, 0x2f, + 0xa5, 0xa9, 0x49, 0xd6, 0x9d, 0xda, 0x34, 0x4d, 0xcd, 0x38, 0xb2, 0x49, 0x25, 0xa5, 0xc5, 0x91, + 0x2c, 0x35, 0xa6, 0x5c, 0x67, 0xcd, 0x86, 0x50, 0x3e, 0x6b, 0x2e, 0xc9, 0x4a, 0x02, 0xa3, 0x4c, + 0xb2, 0x35, 0x61, 0x66, 0xa7, 0xe0, 0x7d, 0x39, 0xf7, 0xe2, 0x2f, 0x31, 0xd9, 0xe1, 0xaa, 0xe8, + 0xbd, 0x83, 0x1c, 0xad, 0xde, 0x17, 0x8e, 0xfd, 0x1b, 0xb8, 0x77, 0xfb, 0xa3, 0xf1, 0xf4, 0x29, + 0xba, 0xea, 0xc4, 0x69, 0x9a, 0xbb, 0x51, 0xaa, 0x35, 0xe5, 0x84, 0xa4, 0x2a, 0x9c, 0x3e, 0xdd, + 0xd3, 0x37, 0xac, 0xb9, 0xcf, 0x0f, 0x61, 0xae, 0x97, 0xbb, 0x1d, 0x15, 0x01, 0x18, 0x15, 0x0d, + 0x8c, 0xe2, 0xdc, 0x4f, 0x63, 0x06, 0xbb, 0x1b, 0xe5, 0x0c, 0x24, 0x07, 0x17, 0x64, 0x81, 0x47, + 0xf7, 0x55, 0x70, 0x97, 0x56, 0xb8, 0x02, 0xe2, 0x75, 0x06, 0xdd, 0x67, 0x1f, 0x6e, 0xa8, 0xee, + 0x14, 0x9a, 0xeb, 0x1e, 0x58, 0xe1, 0x76, 0xc2, 0xc0, 0x74, 0xff, 0x9f, 0x46, 0xb3, 0x65, 0x39, + 0xf1, 0x01, 0x4c, 0x8b, 0xf1, 0x66, 0xe0, 0x8d, 0x9e, 0x2b, 0xe0, 0xbc, 0x8f, 0x66, 0xd8, 0xe8, + 0xbd, 0x35, 0x59, 0xf6, 0x86, 0xac, 0x8d, 0x4c, 0x47, 0x7b, 0x04, 0x13, 0x4e, 0xbc, 0x84, 0x78, + 0x0b, 0xdc, 0x6f, 0xf9, 0x5e, 0x8a, 0x32, 0xb2, 0xdf, 0xb3, 0x17, 0xb1, 0x1c, 0x83, 0x78, 0xae, + 0x9c, 0x1a, 0x46, 0x99, 0x92, 0x81, 0xab, 0x7e, 0x27, 0x42, 0x91, 0x80, 0x4f, 0x11, 0x73, 0x10, + 0x82, 0x57, 0xd1, 0x13, 0x71, 0x77, 0x22, 0x9e, 0x80, 0xaf, 0x1b, 0x4b, 0x9e, 0x72, 0x24, 0x98, + 0x39, 0x10, 0xb9, 0x77, 0xab, 0x92, 0xdd, 0x83, 0x17, 0x86, 0xf4, 0xe8, 0x96, 0x56, 0xd2, 0xe5, + 0x85, 0x2a, 0xcd, 0x4a, 0x25, 0x5b, 0x07, 0x6e, 0xff, 0x39, 0x28, 0x63, 0x66, 0x9d, 0x44, 0xd1, + 0x00, 0x71, 0x23, 0x53, 0xa5, 0xbd, 0x94, 0xdf, 0x16, 0x95, 0xb4, 0x97, 0xca, 0x81, 0x45, 0x5d, + 0x4b, 0x13, 0x7d, 0x6b, 0x2c, 0x10, 0x4a, 0x69, 0xd3, 0x89, 0x45, 0x2b, 0xed, 0x35, 0xd1, 0x06, + 0x90, 0xae, 0xa5, 0xb8, 0x20, 0x10, 0xac, 0xac, 0xe4, 0xc6, 0xac, 0x95, 0x74, 0x81, 0xee, 0x8d, + 0x54, 0x78, 0xe2, 0x3d, 0xfc, 0x11, 0x90, 0xaf, 0xbf, 0xb4, 0x87, 0xe4, 0x8b, 0xab, 0xf6, 0x53, + 0x87, 0xa1, 0x09, 0x05, 0x8c, 0x3f, 0x8e, 0xd2, 0xc5, 0x1f, 0x91, 0x8c, 0x5e, 0x45, 0xae, 0x40, + 0x78, 0x90, 0x7f, 0x87, 0x2b, 0xa9, 0xed, 0x56, 0x38, 0x97, 0x9b, 0x67, 0x82, 0xa0, 0x59, 0x3e, + 0xdd, 0x45, 0x6d, 0x43, 0xde, 0x41, 0x6c, 0x33, 0x51, 0x82, 0xe0, 0xcd, 0x45, 0x88, 0xbb, 0x34, + 0x10, 0xed, 0x1d, 0x66, 0x30, 0x26, 0x77, 0xc0, 0xc4, 0xfa, 0x13, 0x64, 0x8d, 0x86, 0xac, 0x51, + 0x93, 0x35, 0x2a, 0xa2, 0xf6, 0x78, 0x1e, 0x43, 0x0a, 0x03, 0x7d, 0xe5, 0x2f, 0xba, 0x42, 0x56, + 0x74, 0x3d, 0xd2, 0xcd, 0x88, 0x08, 0x7d, 0x6c, 0xc7, 0x75, 0xef, 0xc5, 0xc4, 0x68, 0xc9, 0xfd, + 0x24, 0x15, 0xf7, 0xa7, 0x14, 0xcb, 0x61, 0xa8, 0x23, 0x01, 0x40, 0x20, 0xa1, 0x89, 0xdb, 0xf3, + 0x00, 0x8a, 0x38, 0xf8, 0x06, 0xe6, 0x53, 0x9e, 0x03, 0xd4, 0x67, 0x0a, 0x72, 0x6b, 0xfb, 0x48, + 0x9f, 0x2f, 0x18, 0xed, 0x1b, 0x9a, 0x01, 0x31, 0x98, 0x44, 0x05, 0x67, 0x6f, 0xbd, 0xee, 0x24, + 0xb8, 0x3e, 0xe0, 0xb8, 0xa1, 0x37, 0x86, 0x47, 0x3b, 0x7d, 0x37, 0xb9, 0x97, 0x1b, 0x63, 0x5c, + 0xb2, 0xfa, 0x86, 0x64, 0x6e, 0xf7, 0x2c, 0x8d, 0x00, 0x4b, 0x84, 0xed, 0x6c, 0x37, 0xda, 0xa0, + 0x7e, 0xce, 0xdd, 0x44, 0x6f, 0x8d, 0x65, 0x70, 0x23, 0xe6, 0x81, 0xcb, 0x09, 0x2e, 0x42, 0x80, + 0x74, 0xcd, 0xf4, 0x89, 0x03, 0xc0, 0x72, 0xbc, 0x5f, 0x06, 0xc9, 0x1e, 0x98, 0x21, 0x36, 0xb0, + 0x10, 0xa1, 0x71, 0x7b, 0x1b, 0xc1, 0xff, 0x86, 0x19, 0x6e, 0xe3, 0x08, 0x01, 0x98, 0xa1, 0x13, + 0xfd, 0x3d, 0xa0, 0xbe, 0x47, 0xc3, 0xd2, 0x49, 0x3a, 0xd5, 0x37, 0x30, 0xfe, 0x63, 0x9b, 0x51, + 0x5e, 0x07, 0x3e, 0xa1, 0xc6, 0x6c, 0x3b, 0x86, 0x5c, 0x1c, 0x72, 0x75, 0x92, 0xb4, 0x81, 0x5a, + 0x88, 0x0d, 0xd4, 0x42, 0x6c, 0x40, 0x0b, 0x01, 0x21, 0x78, 0x1a, 0xc9, 0xd6, 0x4a, 0x1b, 0x14, + 0x23, 0x21, 0x53, 0x66, 0xb6, 0x23, 0x33, 0x2d, 0xd4, 0x4a, 0xbc, 0x00, 0x2c, 0xbc, 0x00, 0x2c, + 0x9c, 0xfd, 0x65, 0xd8, 0x44, 0x3c, 0x8c, 0x17, 0x13, 0xc8, 0xbe, 0x6b, 0x94, 0x7d, 0x17, 0x30, + 0xe1, 0x29, 0xc4, 0x3e, 0x7f, 0x22, 0x10, 0x15, 0x0f, 0x65, 0xe3, 0xc2, 0x29, 0x18, 0x28, 0xfe, + 0xa9, 0x1d, 0x2d, 0xb7, 0x15, 0x45, 0x00, 0xa3, 0x71, 0xfe, 0x8b, 0x61, 0xa3, 0xe1, 0x1c, 0x4f, + 0x0d, 0x06, 0x7a, 0x17, 0x8a, 0x8e, 0xb0, 0x9e, 0xbd, 0xc8, 0x24, 0x29, 0x02, 0x0d, 0x59, 0xd6, + 0xe3, 0x24, 0xfb, 0x49, 0x29, 0x1d, 0x0c, 0xc5, 0x53, 0x52, 0xba, 0x86, 0x64, 0x15, 0xfb, 0xff, + 0x43, 0x4c, 0xc1, 0x6c, 0x6a, 0xc6, 0x59, 0xa4, 0x1c, 0x6c, 0xe1, 0x7e, 0x26, 0x4d, 0xa4, 0xf9, + 0xd6, 0xaa, 0x8f, 0x2a, 0x77, 0xa5, 0xb2, 0x42, 0xa2, 0xe8, 0xcd, 0x2c, 0xd5, 0x82, 0xf3, 0x1a, + 0xfc, 0x26, 0xb4, 0x95, 0x0c, 0xb7, 0x3b, 0x17, 0x57, 0xee, 0xda, 0xc8, 0x0a, 0x09, 0xa2, 0xf7, + 0x71, 0x0a, 0xf1, 0xa7, 0xb1, 0x10, 0x4e, 0x6d, 0xd6, 0x8a, 0x65, 0x38, 0xba, 0xe3, 0xf7, 0x7a, + 0xaf, 0x7f, 0x9c, 0xde, 0x5b, 0x0f, 0x7d, 0x70, 0xef, 0xa3, 0x29, 0xdf, 0x80, 0x6b, 0xca, 0x77, + 0xe6, 0x8c, 0xfb, 0xa8, 0xf2, 0x59, 0x3b, 0x2b, 0x4c, 0xcb, 0x0f, 0x3a, 0xb6, 0xca, 0xf1, 0xff, + 0x1d, 0xba, 0x77, 0x0d, 0x0d, 0x17, 0x4b, 0xfb, 0x65, 0x19, 0x1a, 0x1c, 0x97, 0xc6, 0x8e, 0xa7, + 0xa4, 0x86, 0xbb, 0x4f, 0x38, 0x97, 0x84, 0x0e, 0x97, 0xcc, 0x5a, 0x25, 0xe0, 0x92, 0x52, 0xe8, + 0xa8, 0xe3, 0x0d, 0xe5, 0x6a, 0x21, 0x26, 0xf9, 0x71, 0x8d, 0x10, 0x65, 0x30, 0x69, 0x9d, 0x6a, + 0xb1, 0x51, 0xb5, 0x56, 0xe8, 0x08, 0x9d, 0x47, 0xe1, 0x30, 0xe1, 0xfe, 0xd3, 0xe9, 0x01, 0x8a, + 0x59, 0x2d, 0xd1, 0xf4, 0x73, 0x69, 0x9c, 0x01, 0x81, 0x1b, 0x00, 0xf8, 0x16, 0x3d, 0x3e, 0x03, + 0x50, 0x00, 0xc0, 0x0b, 0x59, 0x8f, 0x51, 0x43, 0x8c, 0x77, 0xc0, 0xa9, 0x56, 0x6e, 0x4d, 0x35, + 0x23, 0x3e, 0x1c, 0x9e, 0x8f, 0xc1, 0x8a, 0x3c, 0x42, 0xa0, 0x71, 0x9c, 0x72, 0xa6, 0x0a, 0x31, + 0x23, 0xb7, 0x7f, 0xf5, 0x10, 0xea, 0xc5, 0x2b, 0x91, 0x98, 0xa6, 0x38, 0xc7, 0xb9, 0x7c, 0x65, + 0x8c, 0x70, 0x5f, 0xd5, 0xed, 0x21, 0xcc, 0x17, 0x9d, 0xd0, 0x20, 0x3e, 0x06, 0x93, 0x4d, 0xcc, + 0x20, 0x05, 0x01, 0xe5, 0x91, 0x09, 0xb5, 0xc4, 0xd4, 0xd0, 0xe2, 0xa8, 0x86, 0xd5, 0xfe, 0x8f, + 0x61, 0x28, 0xb0, 0xb0, 0x9b, 0x7f, 0xbc, 0x5c, 0xec, 0xcf, 0x7d, 0xe1, 0x09, 0xb1, 0x3f, 0x8f, + 0xab, 0x7e, 0x04, 0x5d, 0x88, 0x7e, 0x33, 0x57, 0xcd, 0x29, 0xe9, 0x5d, 0xfd, 0x8f, 0x73, 0x6e, + 0x54, 0x57, 0xd2, 0x43, 0x5a, 0x3c, 0x0e, 0xb5, 0x74, 0x0f, 0xb9, 0x1c, 0x2c, 0x57, 0xc9, 0xaf, + 0x47, 0x85, 0xee, 0x56, 0x49, 0xb3, 0x67, 0xcd, 0xcb, 0xe2, 0x80, 0x7a, 0x67, 0x66, 0x70, 0xb6, + 0xc7, 0x8b, 0x4e, 0xc5, 0x79, 0x09, 0xb3, 0x54, 0x48, 0x17, 0xb8, 0xc9, 0x0e, 0x84, 0x3a, 0x4c, + 0x47, 0x7c, 0xc0, 0x99, 0x8d, 0xa3, 0x65, 0x72, 0xee, 0x05, 0xdf, 0x1d, 0x6d, 0x10, 0x96, 0xd2, + 0xf1, 0x11, 0x4d, 0xbb, 0xdc, 0x02, 0x66, 0x93, 0x76, 0x28, 0xe6, 0xdc, 0x18, 0x84, 0x84, 0x87, + 0x6b, 0xc1, 0x23, 0x99, 0x2e, 0x93, 0x7c, 0x06, 0x41, 0x9f, 0x46, 0x93, 0xa0, 0x17, 0x7d, 0x2a, + 0x62, 0xec, 0xb4, 0xc8, 0xef, 0x77, 0x52, 0x89, 0x05, 0x9a, 0xbc, 0xf4, 0x33, 0xec, 0xe1, 0x5b, + 0x53, 0xf9, 0xfc, 0xa4, 0xe0, 0x03, 0xc2, 0x5f, 0x41, 0x2a, 0xd2, 0xf4, 0xde, 0xd4, 0xda, 0x8d, + 0xe3, 0x82, 0x95, 0x83, 0x31, 0xc2, 0xbd, 0x21, 0x52, 0xa8, 0xc3, 0x44, 0x1a, 0x4b, 0xa1, 0xf1, + 0x35, 0xaf, 0x52, 0x0a, 0x85, 0x6a, 0x53, 0x0d, 0x3e, 0xe1, 0x8f, 0x40, 0x2d, 0x0f, 0x9e, 0x9b, + 0x74, 0x76, 0x24, 0x62, 0xc4, 0xd8, 0xe3, 0xf9, 0x91, 0x5a, 0x8a, 0x25, 0x4d, 0x0a, 0xd6, 0xb7, + 0x23, 0x95, 0xbc, 0x81, 0x2e, 0x72, 0xbd, 0xe3, 0x5b, 0x9c, 0xb8, 0x49, 0x8a, 0xf6, 0x94, 0xab, + 0xf1, 0xe4, 0xa2, 0x10, 0x11, 0x34, 0xa9, 0xdc, 0xe7, 0x9c, 0xcb, 0x6b, 0xd9, 0x95, 0xff, 0x1f, + 0x53, 0x8b, 0xa3, 0xa7, 0x4e, 0x5b, 0x27, 0x9c, 0xc0, 0x97, 0xf8, 0xba, 0x3a, 0x90, 0x09, 0x63, + 0x59, 0xbb, 0x6a, 0x14, 0x07, 0x3b, 0xdc, 0x38, 0x4d, 0x84, 0x58, 0x47, 0xb3, 0x1b, 0x17, 0xe3, + 0x16, 0xbc, 0x5f, 0x2d, 0x0e, 0xc4, 0x38, 0x63, 0x10, 0x07, 0x2b, 0x26, 0x3d, 0xff, 0x8f, 0x13, + 0x4b, 0x63, 0xd6, 0xec, 0x3f, 0x3a, 0x9a, 0x7d, 0xf7, 0xd1, 0x34, 0x47, 0x58, 0x62, 0xc7, 0x74, + 0x5c, 0xde, 0xd9, 0xda, 0x88, 0xff, 0xad, 0xa8, 0x01, 0x8b, 0xc2, 0xb8, 0x5e, 0x55, 0xc2, 0x3e, + 0x7a, 0x29, 0x1a, 0xe3, 0x1c, 0x07, 0xbc, 0x59, 0xec, 0xff, 0xdf, 0x91, 0x25, 0xcb, 0x5f, 0xa7, + 0xf0, 0xa3, 0xe3, 0x5f, 0x61, 0xac, 0x43, 0xdb, 0x41, 0xd8, 0xb8, 0xfd, 0xb1, 0xe2, 0x20, 0xae, + 0xf7, 0x1c, 0x57, 0xdd, 0x8c, 0x6f, 0xa6, 0xfc, 0xef, 0x78, 0x9c, 0xe6, 0x3f, 0x7a, 0x50, 0x19, + 0x86, 0x92, 0x6d, 0x1c, 0x5e, 0xf3, 0xfd, 0xaf, 0x49, 0x86, 0x48, 0x61, 0xfa, 0x4f, 0xa0, 0xa3, + 0x10, 0xa2, 0x9b, 0xca, 0x14, 0x7a, 0x20, 0x23, 0x2c, 0x51, 0x8e, 0x49, 0x58, 0x61, 0x89, 0x98, + 0xb2, 0xf5, 0x41, 0x34, 0x8a, 0x33, 0xf5, 0xbd, 0x6f, 0xdb, 0xe1, 0x29, 0xcf, 0x8e, 0x1d, 0x83, + 0x4b, 0xf7, 0xc9, 0xe3, 0x61, 0xdf, 0x07, 0x7d, 0x07, 0xc3, 0x86, 0x10, 0x8e, 0x9b, 0xee, 0xab, + 0xc2, 0x2a, 0xba, 0x36, 0x70, 0x6b, 0xaa, 0x5f, 0x44, 0x7d, 0xef, 0xf5, 0xb8, 0x8e, 0xe3, 0x2b, + 0x41, 0xf9, 0xf2, 0xf6, 0xaf, 0xa9, 0x39, 0xe4, 0x8e, 0xfe, 0x0b, 0x45, 0x8a, 0x99, 0x44, 0xaf, + 0xb0, 0xf2, 0xf3, 0x4b, 0xb5, 0x72, 0xa5, 0x8f, 0x36, 0x65, 0x19, 0x7a, 0x84, 0xf3, 0xfa, 0xde, + 0x63, 0xcc, 0x6c, 0x46, 0x1d, 0x9e, 0x3c, 0x35, 0x8c, 0xce, 0x23, 0x95, 0x29, 0xe9, 0xd4, 0x34, + 0x2f, 0x0c, 0x8d, 0x60, 0x92, 0x3f, 0x54, 0xbc, 0x43, 0x6e, 0xff, 0x4b, 0x58, 0xae, 0xf6, 0x0a, + 0x31, 0xe2, 0xc0, 0xb4, 0x9d, 0x93, 0xb8, 0x77, 0xce, 0x54, 0x44, 0xe7, 0xc8, 0xf3, 0xdd, 0x54, + 0xb8, 0x71, 0xd0, 0xdf, 0x85, 0x83, 0x60, 0x6a, 0x61, 0xb9, 0xfd, 0x11, 0x61, 0x06, 0xa6, 0xfb, + 0x67, 0x48, 0xfa, 0xaa, 0x21, 0x4a, 0x96, 0x49, 0x9e, 0x17, 0x58, 0x62, 0x68, 0x50, 0xb0, 0x93, + 0xf4, 0xca, 0x03, 0x33, 0xdc, 0x3c, 0x91, 0x36, 0xd7, 0xd0, 0xda, 0xe1, 0xd6, 0x74, 0xff, 0xef, + 0x46, 0xa7, 0x7f, 0xe9, 0xc8, 0x25, 0x3c, 0x04, 0xf6, 0x12, 0x9e, 0xe6, 0x38, 0xc1, 0xf6, 0x85, + 0xf9, 0x89, 0x17, 0x1a, 0x78, 0x19, 0xfc, 0xf0, 0xe8, 0x16, 0xa7, 0x19, 0x5f, 0x7e, 0x41, 0x3b, + 0xa0, 0xaf, 0xd3, 0x37, 0xce, 0x6b, 0x4c, 0xa8, 0x3b, 0x3a, 0x99, 0x6e, 0xcc, 0x98, 0x54, 0x10, + 0x93, 0x9b, 0x2f, 0xbf, 0x52, 0xaf, 0x9c, 0x49, 0xf8, 0x58, 0x9f, 0x47, 0x43, 0xc8, 0xed, 0x79, + 0x27, 0x2b, 0x4f, 0x26, 0xd5, 0x3c, 0xb9, 0xec, 0x42, 0xf6, 0xa1, 0x68, 0x3c, 0x49, 0x1c, 0xa0, + 0x79, 0xd7, 0xd3, 0x8c, 0x9d, 0xa4, 0xd1, 0x71, 0x42, 0x74, 0xa9, 0x99, 0x5d, 0x0f, 0x64, 0xf9, + 0xe7, 0x48, 0x6c, 0x4a, 0x68, 0x01, 0x26, 0x96, 0xc4, 0x36, 0x54, 0x22, 0x66, 0x49, 0x12, 0xab, + 0x3c, 0x30, 0xfe, 0xd8, 0x86, 0xcc, 0x65, 0x17, 0x1e, 0xf2, 0x6c, 0x5c, 0x06, 0xdb, 0x68, 0x40, + 0x1e, 0xa4, 0xb1, 0x99, 0x6e, 0x4c, 0xa0, 0xad, 0x83, 0x8d, 0xfb, 0xef, 0x23, 0xdd, 0x12, 0x1d, + 0x70, 0x3e, 0x46, 0x2e, 0x01, 0xda, 0x9e, 0x02, 0x7c, 0xaf, 0x11, 0xf1, 0xb4, 0xe4, 0xcb, 0x5f, + 0xd7, 0x29, 0x78, 0x5e, 0xa4, 0x98, 0xc6, 0x11, 0x32, 0x30, 0xef, 0x6c, 0xe5, 0x89, 0xa4, 0x9a, + 0xf5, 0xc1, 0xf5, 0xdf, 0x45, 0x14, 0xdf, 0x9f, 0x25, 0x57, 0xe4, 0x2a, 0xfa, 0xda, 0xd5, 0x3f, + 0xc7, 0x75, 0x14, 0x62, 0xf4, 0x4c, 0x1b, 0xcf, 0xc7, 0xd4, 0xe0, 0x63, 0xc1, 0x00, 0x30, 0x14, + 0x78, 0x0e, 0xc6, 0xf6, 0x06, 0xfe, 0x16, 0xe8, 0x71, 0xb4, 0xcf, 0xb9, 0xc2, 0xe3, 0xba, 0x45, + 0x7c, 0xdc, 0xbb, 0x67, 0x13, 0xc5, 0x2f, 0xb8, 0xda, 0x57, 0x52, 0x2c, 0x2c, 0x53, 0x93, 0x1f, + 0xdc, 0xe0, 0x93, 0x55, 0xa4, 0x39, 0xda, 0x27, 0xb4, 0x93, 0xae, 0xc3, 0xff, 0x85, 0x07, 0x79, + 0xd1, 0xe8, 0x90, 0x76, 0x91, 0x41, 0x99, 0xa1, 0x2b, 0x8f, 0x43, 0x7e, 0x41, 0x9b, 0x2e, 0x17, + 0xdf, 0x60, 0xc7, 0x52, 0xc7, 0x5f, 0xbe, 0x0d, 0x1f, 0x85, 0x98, 0x80, 0x10, 0xee, 0x5e, 0x21, + 0x82, 0xfc, 0xd5, 0x3e, 0x1b, 0xda, 0xe5, 0xfb, 0x69, 0x78, 0xa4, 0x3a, 0x56, 0x73, 0x50, 0xc5, + 0x48, 0x59, 0x60, 0xa3, 0x9c, 0x4f, 0x4b, 0x0f, 0x87, 0x4e, 0x0f, 0x0f, 0xa9, 0x7e, 0x80, 0x29, + 0xb3, 0x67, 0xa4, 0x58, 0x43, 0x5d, 0xc5, 0xa3, 0x44, 0x08, 0x40, 0xec, 0x73, 0x91, 0xdc, 0x80, + 0xcd, 0x94, 0xdc, 0xae, 0x5c, 0x99, 0xc0, 0x78, 0x9e, 0x60, 0x85, 0x3e, 0x29, 0x2e, 0xc1, 0x50, + 0xe7, 0xf8, 0x0b, 0x3b, 0x40, 0xea, 0xe6, 0x75, 0xe7, 0xe6, 0x98, 0xec, 0x3f, 0x05, 0x34, 0xe5, + 0x06, 0x7a, 0xca, 0x02, 0x9b, 0x72, 0x80, 0x8e, 0xec, 0x9f, 0x64, 0xb2, 0xeb, 0x71, 0xba, 0xdf, + 0xf6, 0x2b, 0x3b, 0x7c, 0xaf, 0xf0, 0x8a, 0xbd, 0xc9, 0x0c, 0x15, 0x6f, 0x2a, 0x15, 0xa3, 0x2f, + 0x7a, 0x2a, 0x53, 0x5a, 0x37, 0xb1, 0x0c, 0xcb, 0x55, 0xf7, 0xd0, 0xc3, 0x7e, 0x8d, 0x54, 0xa0, + 0xae, 0xaa, 0xc7, 0xec, 0x23, 0xf1, 0x12, 0x5e, 0xa9, 0xe2, 0xeb, 0xb6, 0xbe, 0xbe, 0xcb, 0xd1, + 0x3e, 0xce, 0x7d, 0x19, 0x00, 0xaa, 0xbe, 0xc4, 0xd4, 0xa3, 0xb7, 0xdb, 0xa1, 0x8b, 0xb4, 0xac, + 0x0d, 0xfe, 0x92, 0x2e, 0xf6, 0x32, 0xa9, 0x8b, 0x1d, 0x24, 0xae, 0x00, 0xb9, 0xf1, 0x09, 0x4d, + 0xe4, 0x39, 0x49, 0x79, 0x95, 0x70, 0xd6, 0xf1, 0x94, 0xfe, 0x44, 0x4e, 0x4e, 0x4e, 0x29, 0x4b, + 0x13, 0x8d, 0xc0, 0x1a, 0xe4, 0xe5, 0x9b, 0x2c, 0xf6, 0x97, 0x1f, 0x8e, 0x62, 0xec, 0x6f, 0xc1, + 0x1f, 0xf9, 0xdf, 0x69, 0x92, 0xd9, 0x02, 0x65, 0x1c, 0x50, 0xb6, 0x14, 0x3a, 0x6c, 0x55, 0x03, + 0x42, 0xe3, 0xd1, 0x7e, 0x17, 0xae, 0x32, 0xf6, 0xca, 0xd8, 0x41, 0x09, 0x85, 0x7e, 0x07, 0x21, + 0x2b, 0xde, 0xb2, 0x5f, 0x52, 0xce, 0x9e, 0xfa, 0x3a, 0xd0, 0x57, 0x83, 0xd1, 0xe5, 0x1f, 0x7e, + 0xa5, 0x1c, 0xa6, 0xa7, 0x20, 0x54, 0xec, 0xfd, 0x08, 0xa6, 0xf7, 0x9a, 0x46, 0x4d, 0x9a, 0xcf, + 0x0c, 0xbf, 0xa4, 0x1c, 0xca, 0xfd, 0xa9, 0xda, 0xc8, 0x32, 0xfe, 0xc3, 0x34, 0x05, 0xc8, 0xff, + 0x7b, 0xbc, 0x35, 0xe1, 0x75, 0xb5, 0xc6, 0xd9, 0xdc, 0x7e, 0xf3, 0x5c, 0x6e, 0xff, 0x09, 0x58, + 0x3e, 0x50, 0xf9, 0xee, 0x4c, 0x4f, 0x41, 0x3d, 0x6a, 0xc4, 0x16, 0x9a, 0x08, 0xb6, 0x60, 0x44, + 0xfa, 0x69, 0x6a, 0x97, 0x16, 0xed, 0xef, 0x3d, 0xf4, 0x45, 0x2b, 0xb5, 0x27, 0x4b, 0x4d, 0xf8, + 0xe3, 0x10, 0x1d, 0xa8, 0x9e, 0x10, 0x9f, 0x6f, 0xd0, 0x42, 0x3c, 0x56, 0x87, 0xde, 0xbe, 0xaa, + 0x01, 0x15, 0xa3, 0xe0, 0x14, 0x29, 0x38, 0x02, 0x1a, 0x4b, 0x2e, 0x4a, 0x05, 0xc7, 0xc5, 0x6d, + 0x47, 0x58, 0x6e, 0x8f, 0x5f, 0x49, 0x44, 0x96, 0x92, 0xa5, 0x35, 0x2a, 0xc9, 0xa4, 0x26, 0xae, + 0x6b, 0xec, 0xa0, 0x94, 0xaa, 0x89, 0x05, 0x7f, 0x1e, 0xb7, 0x79, 0x94, 0x5b, 0xc1, 0x2b, 0x55, + 0xf4, 0x4b, 0xeb, 0xef, 0x48, 0x2b, 0x88, 0xd0, 0xc4, 0xf6, 0x49, 0x82, 0x97, 0xb8, 0xda, 0xa4, + 0xe7, 0x60, 0xf7, 0xbf, 0x10, 0x7b, 0x86, 0xb8, 0xda, 0xb9, 0x3d, 0xf8, 0x1a, 0xbc, 0xc1, 0xdc, + 0x06, 0x8e, 0x71, 0x82, 0x8f, 0x7b, 0x85, 0x3f, 0x2f, 0xb9, 0x9a, 0x0c, 0xae, 0x6b, 0xe0, 0x2d, + 0x4f, 0x33, 0x5e, 0x70, 0x4c, 0x1a, 0x6e, 0x11, 0x31, 0xd9, 0x7b, 0x05, 0x34, 0xb8, 0x2e, 0x90, + 0x81, 0x69, 0x46, 0x19, 0x13, 0x4a, 0x0d, 0xe6, 0xa6, 0x84, 0x46, 0x70, 0xc6, 0x67, 0x19, 0x7b, + 0x24, 0xd7, 0x35, 0x03, 0x0c, 0xec, 0x6a, 0x9f, 0xe6, 0xa2, 0x4d, 0xb5, 0xdb, 0xce, 0xcf, 0xda, + 0xd6, 0xa3, 0xfb, 0xac, 0xf2, 0x5b, 0x90, 0x98, 0x74, 0xd8, 0x0c, 0x7b, 0x7d, 0x2c, 0xc7, 0xf3, + 0x17, 0x38, 0xde, 0xdc, 0x24, 0xb9, 0xda, 0x0c, 0x97, 0x42, 0xf3, 0xf9, 0xaa, 0xa1, 0xaf, 0xf1, + 0x1a, 0x8a, 0x33, 0x74, 0xe4, 0x5d, 0xed, 0xf4, 0xd5, 0xfb, 0x56, 0xc2, 0xcd, 0x6b, 0x06, 0xdf, + 0x1b, 0xea, 0xc8, 0x6e, 0x55, 0x42, 0x3f, 0xc9, 0x51, 0x93, 0x34, 0x8d, 0x58, 0x1f, 0x9f, 0xcd, + 0xb9, 0x59, 0x1a, 0x36, 0xb7, 0x4a, 0x6b, 0xd4, 0x78, 0xb7, 0xde, 0x1c, 0x5d, 0xe7, 0x7c, 0xa1, + 0xd2, 0xa5, 0x65, 0x9c, 0x05, 0x55, 0x03, 0x28, 0x10, 0xa4, 0x4e, 0xbc, 0xc2, 0x38, 0x9e, 0x91, + 0x84, 0x56, 0x69, 0xaa, 0xb4, 0x43, 0x45, 0x2e, 0x55, 0x35, 0xa2, 0x90, 0x12, 0x41, 0x16, 0x2f, + 0xc2, 0xdf, 0x76, 0xee, 0x95, 0x7a, 0x6e, 0x7f, 0x0f, 0xe9, 0xe9, 0xbb, 0x1a, 0xdd, 0x23, 0x64, + 0x1e, 0x45, 0x29, 0x9d, 0xd9, 0xc7, 0xc2, 0x64, 0x72, 0xac, 0x0f, 0x8f, 0x07, 0x93, 0xe7, 0x0d, + 0xc2, 0x2a, 0xc8, 0x2e, 0x55, 0xc2, 0xc0, 0xcc, 0x6e, 0x62, 0x52, 0x47, 0x37, 0x43, 0xa0, 0xe5, + 0x9c, 0x86, 0x29, 0xc1, 0x82, 0x5a, 0x2a, 0x38, 0xe5, 0x5f, 0x8c, 0x31, 0x41, 0x2c, 0x49, 0x53, + 0x81, 0xe1, 0x4a, 0xd3, 0x90, 0x34, 0x35, 0x34, 0xad, 0xc3, 0x7b, 0xed, 0xf3, 0x15, 0x93, 0x3d, + 0xaa, 0x5c, 0xbc, 0x53, 0x5e, 0xea, 0x3b, 0x34, 0x8e, 0x2a, 0x49, 0x6b, 0xcf, 0x7b, 0xeb, 0xa1, + 0x5b, 0x86, 0xe1, 0x3c, 0xb7, 0xe7, 0x7b, 0x18, 0xcb, 0x02, 0xaf, 0x1f, 0xc4, 0x48, 0xd7, 0x5b, + 0x3b, 0xf1, 0x35, 0x90, 0x89, 0x1a, 0xa3, 0xec, 0xd1, 0xa4, 0x8a, 0xcf, 0x9f, 0x46, 0x5e, 0xff, + 0x9b, 0x62, 0x91, 0x3d, 0x2b, 0x4f, 0x57, 0xba, 0x64, 0x46, 0x28, 0x82, 0xb0, 0xa6, 0x50, 0x75, + 0x18, 0x91, 0xc7, 0xcc, 0x21, 0x14, 0xea, 0x2b, 0x8e, 0xc7, 0xa4, 0x7c, 0xb5, 0xb4, 0x53, 0x43, + 0x84, 0x6b, 0xe4, 0x34, 0x31, 0xb7, 0xb1, 0x17, 0x25, 0xf3, 0xb5, 0xd8, 0xf3, 0xc0, 0xb6, 0xf6, + 0xaa, 0x21, 0x56, 0x4b, 0x85, 0x48, 0xbc, 0x8a, 0x19, 0x0b, 0x31, 0x05, 0xed, 0xc2, 0x82, 0xaa, + 0x13, 0xb8, 0xbc, 0x48, 0x63, 0x9b, 0x78, 0x2e, 0x48, 0x20, 0x2e, 0xca, 0xd7, 0x34, 0xae, 0xa6, + 0xb9, 0x7d, 0x8d, 0xe3, 0xa9, 0xa6, 0x6d, 0x50, 0x4f, 0xd8, 0xa0, 0x71, 0x46, 0xc1, 0x02, 0xfc, + 0x89, 0xb8, 0x0a, 0x43, 0x0b, 0x2c, 0x41, 0x93, 0x8b, 0x92, 0xb8, 0xf4, 0x34, 0x5d, 0x42, 0xcf, + 0x7b, 0x50, 0x58, 0x93, 0x6a, 0x68, 0xe1, 0xf6, 0xe0, 0x35, 0x19, 0x4d, 0x04, 0x7e, 0x9a, 0x1e, + 0xe9, 0x80, 0x73, 0x08, 0x9e, 0x28, 0xbe, 0x56, 0xb0, 0x16, 0x04, 0x54, 0x4a, 0xc2, 0x34, 0x86, + 0x5d, 0x2a, 0x52, 0xd0, 0x06, 0x2e, 0x1e, 0x08, 0x29, 0xdf, 0x2e, 0x4d, 0xc6, 0xb8, 0x2f, 0x43, + 0x65, 0xe8, 0x26, 0x75, 0x09, 0x83, 0x12, 0x26, 0x18, 0xf4, 0xe3, 0x91, 0x7f, 0xba, 0x20, 0x73, + 0xe9, 0xbe, 0x34, 0x60, 0xa6, 0xa1, 0x59, 0xb8, 0xe4, 0x51, 0xa5, 0x22, 0xc5, 0x12, 0x15, 0x8a, + 0x79, 0xf8, 0x77, 0x49, 0x23, 0xb9, 0xde, 0xf3, 0x1e, 0x2d, 0x91, 0x1b, 0x98, 0xdd, 0x30, 0x52, + 0x22, 0x0d, 0x14, 0x1d, 0x10, 0x17, 0x4f, 0x1a, 0x2b, 0x15, 0xb4, 0xe1, 0x10, 0x2d, 0x9c, 0x7b, + 0x27, 0x5e, 0x28, 0x65, 0x21, 0x02, 0xfa, 0xab, 0xfa, 0x13, 0x69, 0x9e, 0x95, 0x4f, 0x48, 0x99, + 0x43, 0x5a, 0x4c, 0x75, 0xbb, 0x27, 0x25, 0x12, 0x96, 0xe9, 0x9c, 0x90, 0x82, 0xab, 0xe5, 0xdc, + 0xaf, 0x33, 0x8a, 0x4e, 0x00, 0x8d, 0x35, 0x43, 0xd2, 0x6e, 0xb5, 0x94, 0xa3, 0x91, 0xf4, 0xa0, + 0x03, 0xec, 0x10, 0xbe, 0xd3, 0xbc, 0x5b, 0x45, 0x80, 0x96, 0x97, 0x2a, 0xd4, 0x0a, 0xab, 0xfd, + 0xdb, 0x30, 0xf9, 0x5b, 0xb3, 0x16, 0xb6, 0x55, 0x43, 0x66, 0xb3, 0x96, 0xb4, 0x08, 0xf9, 0x1e, + 0x55, 0xd3, 0x92, 0xa4, 0x25, 0xbb, 0x54, 0xd1, 0x7d, 0xc2, 0x55, 0x10, 0xdf, 0x48, 0x90, 0x40, + 0xf3, 0xb5, 0xc9, 0x26, 0x8d, 0xe3, 0x33, 0xfc, 0xfd, 0x8d, 0x36, 0xb2, 0x0e, 0x8f, 0x98, 0x3d, + 0x19, 0x11, 0x2b, 0xf8, 0xce, 0x8a, 0x07, 0xf0, 0x1e, 0xe1, 0x8a, 0x58, 0x37, 0x04, 0x41, 0xa4, + 0x47, 0xf3, 0x04, 0x74, 0xf5, 0xec, 0x92, 0x95, 0x75, 0xc0, 0x2a, 0x44, 0x6f, 0xfc, 0x3a, 0xe1, + 0xaf, 0x48, 0xf2, 0xf5, 0xfe, 0x57, 0xe1, 0x8b, 0x34, 0x78, 0x32, 0x58, 0xb1, 0x3e, 0xc2, 0x70, + 0x9e, 0x5c, 0x26, 0xf5, 0xdc, 0x1e, 0xfc, 0x45, 0x00, 0x08, 0x1d, 0xcf, 0x61, 0x56, 0x88, 0x56, + 0x3c, 0x6e, 0x52, 0x0c, 0xd0, 0x3a, 0x25, 0xf9, 0x70, 0xf1, 0x9f, 0xe9, 0xae, 0x81, 0xc9, 0x9c, + 0x60, 0x32, 0x47, 0xec, 0xcb, 0x7b, 0xca, 0x1d, 0xdb, 0xdb, 0x58, 0x43, 0xc6, 0x35, 0x44, 0x51, + 0x73, 0x7d, 0x10, 0x9b, 0x36, 0x8d, 0xfa, 0xfd, 0x0c, 0x31, 0x45, 0x67, 0xc7, 0x5f, 0x29, 0xa8, + 0xfe, 0x15, 0x65, 0xe3, 0xc1, 0xd9, 0xf8, 0xe2, 0x6c, 0x0a, 0xed, 0x63, 0xec, 0xac, 0x0a, 0xe2, + 0x7b, 0x89, 0x5c, 0x35, 0xfe, 0x05, 0x43, 0xed, 0xd1, 0x7c, 0x4b, 0xdf, 0x5b, 0x7a, 0x6d, 0x2d, + 0x8e, 0xa2, 0x60, 0x7f, 0x89, 0x72, 0xe1, 0x59, 0x95, 0x14, 0x23, 0x39, 0xd4, 0xec, 0x69, 0xe9, + 0x87, 0x9a, 0xd8, 0xdb, 0xa4, 0xa0, 0x1d, 0xc8, 0xe6, 0x0a, 0x74, 0xa4, 0x62, 0xf8, 0xf1, 0x2c, + 0x0a, 0x33, 0x8d, 0x54, 0x04, 0xf9, 0xf0, 0x24, 0x90, 0x37, 0x9b, 0x74, 0x0f, 0x77, 0xec, 0x1c, + 0x77, 0xa0, 0xdb, 0xf7, 0x95, 0xaa, 0x6a, 0x90, 0x79, 0x2b, 0x18, 0x3c, 0x8c, 0xbf, 0xb4, 0xc2, + 0x19, 0xbb, 0x0d, 0x5d, 0xe2, 0x0d, 0xc6, 0xf1, 0x94, 0x32, 0xbf, 0x27, 0x8e, 0xce, 0x26, 0xfd, + 0x24, 0x17, 0x67, 0x3b, 0x1a, 0x04, 0xc9, 0x37, 0x9c, 0x3e, 0x4a, 0xb7, 0xf3, 0x3f, 0xe4, 0xbe, + 0x0b, 0x55, 0x8e, 0x47, 0xaa, 0x5c, 0x32, 0x0b, 0xbc, 0x94, 0x84, 0x76, 0xf1, 0x3a, 0xfc, 0xed, + 0xe4, 0xf6, 0x9c, 0xa5, 0xf8, 0xd1, 0x1e, 0x20, 0xed, 0x20, 0xee, 0xec, 0x3a, 0xb5, 0x98, 0xab, + 0x09, 0x36, 0xa6, 0x2b, 0x82, 0x1e, 0x81, 0x9b, 0xc2, 0x21, 0x05, 0x8b, 0x68, 0xee, 0xd8, 0x59, + 0xee, 0x40, 0xb3, 0xef, 0xe6, 0x58, 0x2c, 0x50, 0xb9, 0x70, 0x4c, 0xd9, 0xd0, 0x7d, 0x58, 0xb9, + 0xc8, 0x6e, 0x4f, 0x18, 0x74, 0x58, 0x0d, 0x5d, 0xca, 0x4e, 0x32, 0x50, 0xf1, 0xc3, 0xff, 0xa1, + 0xbf, 0x34, 0x85, 0x92, 0xcf, 0x1c, 0xf0, 0xc4, 0x7d, 0x4e, 0x0f, 0x76, 0x6f, 0x93, 0x3e, 0xe9, + 0x0f, 0xb9, 0xef, 0x43, 0xe5, 0xbc, 0x21, 0xe9, 0x48, 0xee, 0x6f, 0xe0, 0x21, 0xe1, 0x06, 0x7b, + 0x9a, 0x28, 0x75, 0xb0, 0x5f, 0x12, 0xa5, 0xd2, 0x1f, 0x2d, 0x4d, 0x54, 0x28, 0x1f, 0x00, 0xea, + 0xad, 0x26, 0x94, 0x0c, 0xb0, 0xac, 0x2c, 0x90, 0x8f, 0x15, 0xcb, 0x90, 0x4f, 0xa4, 0x8b, 0xdb, + 0x53, 0x8c, 0x27, 0xd1, 0xcc, 0x28, 0x46, 0x1f, 0x51, 0x7e, 0x75, 0xe2, 0x20, 0xfe, 0x5e, 0x94, + 0xfe, 0x44, 0x14, 0x5a, 0x08, 0x30, 0xa4, 0xa4, 0xb9, 0xef, 0x8a, 0xbe, 0x59, 0xd8, 0x78, 0x88, + 0x9a, 0xb4, 0x26, 0xb6, 0x49, 0xdf, 0x7b, 0x08, 0xe5, 0xfe, 0x18, 0x76, 0xfc, 0x04, 0x3b, 0xd2, + 0x34, 0xe0, 0x1c, 0x8b, 0xc9, 0x92, 0x93, 0x9f, 0x27, 0xa7, 0x53, 0xaf, 0x67, 0x81, 0x05, 0x1e, + 0xb7, 0x2a, 0xe3, 0x29, 0x12, 0x33, 0x9c, 0xab, 0x6c, 0x4f, 0xca, 0xa6, 0xe2, 0x56, 0xff, 0x45, + 0x30, 0xa8, 0x6c, 0x7a, 0xdd, 0xa1, 0x97, 0x1a, 0x26, 0x52, 0xcc, 0xd4, 0x54, 0x74, 0xa8, 0x64, + 0x61, 0xda, 0xd7, 0xa8, 0xdc, 0x65, 0xcd, 0x70, 0x02, 0xc4, 0x41, 0x9a, 0x9d, 0xcc, 0x6b, 0xf0, + 0x50, 0xee, 0x95, 0x3a, 0x6e, 0xff, 0x39, 0x72, 0xb1, 0xef, 0x7a, 0xf4, 0x45, 0xf4, 0xf0, 0xa9, + 0x74, 0x3a, 0xf5, 0x73, 0x68, 0x86, 0xf2, 0xb9, 0x74, 0x7d, 0x6f, 0xae, 0xc5, 0x62, 0x81, 0x2d, + 0xd4, 0x32, 0x76, 0xd3, 0xfc, 0x19, 0xcd, 0xf6, 0x5b, 0xb0, 0x29, 0x94, 0x7b, 0xeb, 0x8f, 0xa2, + 0xdb, 0x30, 0xa0, 0xb5, 0xe0, 0x8b, 0xb0, 0xef, 0x24, 0x15, 0xc4, 0x63, 0x4a, 0x36, 0xcd, 0xa8, + 0x00, 0x67, 0xb7, 0x15, 0x50, 0x74, 0xa6, 0x1d, 0xc4, 0xa5, 0x97, 0x32, 0x26, 0x53, 0x5e, 0xbe, + 0xcc, 0xb0, 0xa1, 0x94, 0x65, 0x74, 0x5c, 0x9d, 0x8f, 0x00, 0x98, 0xe1, 0x8c, 0xc4, 0x6b, 0x13, + 0xea, 0xb9, 0x8c, 0x01, 0x72, 0x12, 0x53, 0xcb, 0x2d, 0xf2, 0xf7, 0xae, 0xe3, 0xae, 0x02, 0x0a, + 0xad, 0xc5, 0xa8, 0x4d, 0xe3, 0x1f, 0x47, 0x7f, 0xba, 0x64, 0x02, 0x20, 0x24, 0xe3, 0x59, 0x3c, + 0xf5, 0x04, 0xc2, 0xde, 0xd0, 0xf0, 0xd8, 0xa1, 0x55, 0xbf, 0x45, 0x57, 0x1d, 0x17, 0xca, 0x50, + 0xa1, 0x44, 0x37, 0xe5, 0xe4, 0xd0, 0x0c, 0x41, 0xf7, 0xa8, 0x26, 0x44, 0x15, 0x2f, 0xd4, 0xe2, + 0x68, 0x72, 0xc3, 0x70, 0x66, 0x83, 0x16, 0xef, 0x36, 0xeb, 0x49, 0xa0, 0xcf, 0x0a, 0x56, 0x77, + 0x3c, 0xf7, 0xf2, 0x1f, 0xd5, 0x7f, 0x52, 0x7f, 0x06, 0xa8, 0xe0, 0xd1, 0x7d, 0x77, 0x38, 0xb1, + 0xc1, 0x19, 0x7f, 0x48, 0x99, 0x34, 0x07, 0x73, 0x3a, 0x17, 0x29, 0xa3, 0x2a, 0x6c, 0x8a, 0x50, + 0x72, 0xe3, 0x12, 0x6f, 0x52, 0x7a, 0x20, 0x2b, 0x46, 0xbc, 0x8f, 0x10, 0x43, 0xe2, 0x46, 0xe7, + 0xa7, 0x19, 0xe3, 0xc0, 0x79, 0xf3, 0xa4, 0x05, 0x23, 0x79, 0x35, 0x7a, 0x6e, 0x7b, 0xde, 0xa1, + 0xa7, 0xca, 0x39, 0xf9, 0x26, 0xd2, 0x20, 0xff, 0xdb, 0x41, 0xea, 0x1f, 0xce, 0x6b, 0x80, 0x8d, + 0x32, 0xe1, 0x12, 0x71, 0xb5, 0x2a, 0x7c, 0x02, 0xdb, 0xf9, 0x22, 0xfc, 0xa5, 0x96, 0xc5, 0xb3, + 0x26, 0x88, 0x3f, 0xfc, 0xc0, 0x9f, 0x02, 0xcb, 0xed, 0x51, 0xfd, 0xf1, 0x75, 0x14, 0x5f, 0xbe, + 0x05, 0x77, 0x03, 0xfe, 0x42, 0xe8, 0x3d, 0x2c, 0x7c, 0x81, 0xf6, 0x9a, 0xe8, 0x6a, 0x62, 0xb8, + 0x1a, 0x7a, 0x61, 0xe9, 0x6a, 0x81, 0xed, 0x51, 0x5c, 0x05, 0x56, 0xe1, 0x27, 0x58, 0x5c, 0x1d, + 0x90, 0x36, 0xdc, 0x92, 0x76, 0xf6, 0xb3, 0x0d, 0x52, 0xfe, 0x9d, 0xd8, 0x66, 0xc7, 0xb3, 0xf4, + 0xb5, 0xb9, 0x4e, 0x03, 0xde, 0x68, 0x5e, 0x20, 0x01, 0xd8, 0x35, 0x12, 0x60, 0x1f, 0x02, 0x83, + 0x6a, 0x30, 0x07, 0x48, 0x53, 0x02, 0xb4, 0xc9, 0xe4, 0xb4, 0x63, 0xbc, 0x3f, 0x17, 0x0d, 0xe5, + 0x69, 0xd2, 0x32, 0x9f, 0xbe, 0x66, 0x95, 0xd0, 0xb5, 0x82, 0x6f, 0x9f, 0x66, 0x6c, 0x75, 0xac, + 0xc0, 0x77, 0x51, 0xf8, 0xce, 0xf9, 0x18, 0x44, 0x1c, 0x47, 0x7f, 0x47, 0x90, 0xa7, 0x09, 0xad, + 0x94, 0x0e, 0x16, 0x93, 0x7c, 0xfc, 0x80, 0xe2, 0xf1, 0x1a, 0x8f, 0xcf, 0xf3, 0x25, 0x5c, 0x24, + 0xcd, 0x2b, 0xf0, 0xd7, 0x19, 0x3a, 0xc1, 0x69, 0x9e, 0x26, 0x78, 0x2b, 0x1e, 0x5e, 0x2f, 0x36, + 0xca, 0x10, 0x30, 0xfe, 0x6b, 0x21, 0xf5, 0x29, 0xae, 0x55, 0xf3, 0xf1, 0xa1, 0xbc, 0x3b, 0x7a, + 0x21, 0x4b, 0x83, 0x92, 0x0b, 0x9c, 0x5b, 0x8f, 0x09, 0x89, 0x86, 0x5c, 0x4a, 0xe6, 0x8f, 0x6f, + 0x40, 0xfd, 0x25, 0x72, 0x72, 0xde, 0x79, 0x4c, 0x2e, 0x15, 0x02, 0x09, 0xdd, 0x7a, 0x2f, 0x6c, + 0x3a, 0x26, 0x60, 0x38, 0x50, 0x3d, 0x37, 0xcf, 0x92, 0x3f, 0x4a, 0x78, 0xaf, 0x53, 0xc1, 0x5b, + 0x50, 0xe9, 0x8a, 0xc7, 0x17, 0x7a, 0x53, 0x28, 0xad, 0x96, 0xbd, 0x01, 0x7f, 0x8f, 0xe1, 0xa3, + 0x7f, 0x52, 0x50, 0x68, 0xc7, 0xf8, 0xf4, 0xf4, 0x55, 0x2a, 0x60, 0x63, 0x74, 0xbc, 0x55, 0xf9, + 0x3d, 0x0a, 0xd2, 0x3f, 0x9c, 0x02, 0x97, 0x05, 0xea, 0xd8, 0xf1, 0x2c, 0xa2, 0x82, 0x1a, 0xd0, + 0x81, 0x87, 0xe1, 0xc3, 0x2f, 0xff, 0xa0, 0x5c, 0x19, 0xb5, 0xa2, 0x4f, 0x0b, 0x6e, 0x9d, 0xfe, + 0x1c, 0x4d, 0x93, 0xc7, 0x34, 0x51, 0x9a, 0x3a, 0x8d, 0x06, 0x49, 0xe8, 0x04, 0xaa, 0x42, 0x0c, + 0x13, 0xca, 0x2f, 0x44, 0x3a, 0xbb, 0xae, 0x89, 0x8f, 0x02, 0x47, 0xf0, 0x85, 0x5d, 0xc9, 0x12, + 0x90, 0x36, 0xdd, 0x92, 0xb2, 0xfb, 0xd9, 0xb3, 0xd2, 0x0b, 0x77, 0x62, 0x6f, 0x38, 0x76, 0x10, + 0x73, 0x8b, 0xc1, 0x7c, 0x0d, 0xe9, 0x5d, 0x70, 0x2a, 0xe1, 0x8a, 0x54, 0x70, 0x0d, 0x5c, 0xba, + 0x36, 0xc3, 0x49, 0xfc, 0xa1, 0x8b, 0x41, 0x50, 0xe4, 0x59, 0xe6, 0xb6, 0x1a, 0x73, 0x0f, 0x19, + 0x84, 0x6d, 0x53, 0x18, 0x47, 0xa1, 0xda, 0x90, 0x09, 0x05, 0xed, 0x2b, 0x0a, 0x60, 0x23, 0x94, + 0xa7, 0x99, 0x4f, 0x71, 0xaf, 0x42, 0x68, 0xdf, 0x0e, 0x3d, 0x0a, 0xe4, 0x84, 0xdb, 0xdc, 0x2b, + 0x0d, 0xba, 0x8b, 0xb5, 0x05, 0x3d, 0xea, 0x9e, 0xea, 0x5e, 0x80, 0x07, 0x07, 0xcf, 0xd8, 0x2e, + 0x99, 0x5b, 0xd5, 0x57, 0x88, 0xb9, 0x15, 0x5f, 0x3e, 0xc2, 0x8a, 0x36, 0x62, 0xbc, 0x26, 0x36, + 0xc4, 0xaf, 0xe1, 0xdc, 0x56, 0xe4, 0x85, 0xeb, 0x5a, 0x2f, 0xdf, 0xca, 0x22, 0x1c, 0xac, 0x0c, + 0x09, 0xdd, 0xc9, 0xd1, 0xdf, 0x4d, 0xa1, 0x29, 0xfc, 0x86, 0x46, 0x2e, 0xa3, 0x1f, 0x94, 0x88, + 0xef, 0xc7, 0x8c, 0xd1, 0x5d, 0xaa, 0x2a, 0x1f, 0x1a, 0x7e, 0xa2, 0x0e, 0xbd, 0xfc, 0x53, 0xa7, + 0x52, 0x24, 0x15, 0xf4, 0x37, 0x3b, 0x14, 0xbb, 0x1c, 0xdd, 0x87, 0x86, 0xf5, 0x85, 0x80, 0x94, + 0x7d, 0x4b, 0xda, 0xd4, 0xcf, 0xde, 0x96, 0x2c, 0x28, 0x78, 0x0f, 0xd0, 0x9f, 0xea, 0x50, 0x1b, + 0x06, 0x40, 0x21, 0xa6, 0xb9, 0x02, 0xdc, 0xab, 0x3e, 0x43, 0x01, 0x6c, 0x63, 0x9a, 0x84, 0x4b, + 0xb0, 0x46, 0x5d, 0x73, 0xe5, 0x20, 0xeb, 0x9c, 0x8c, 0x38, 0x09, 0x7f, 0xd4, 0x9f, 0x5b, 0x47, + 0x5a, 0xfc, 0x31, 0xf8, 0x73, 0x26, 0x75, 0xf5, 0xd2, 0x38, 0xfd, 0xb9, 0x51, 0x39, 0x69, 0x4a, + 0x12, 0x94, 0xe4, 0x4a, 0x94, 0x84, 0xf8, 0x5a, 0xe3, 0x02, 0x4c, 0xf6, 0x0a, 0x44, 0xf7, 0x73, + 0xaf, 0x79, 0x67, 0x19, 0x93, 0xd4, 0x3e, 0x29, 0x06, 0x88, 0xf4, 0x3b, 0x20, 0x74, 0x4f, 0xe8, + 0xf7, 0x99, 0x78, 0x2d, 0x1b, 0x20, 0xbc, 0x0c, 0x81, 0x90, 0xb9, 0xb3, 0x22, 0xae, 0xd2, 0x35, + 0x97, 0x51, 0xae, 0x69, 0xed, 0x1f, 0x21, 0x7f, 0x6f, 0xe0, 0x09, 0xc6, 0x09, 0xe7, 0xb3, 0x92, + 0x6b, 0x36, 0x9e, 0x6e, 0x96, 0x6b, 0xf5, 0xe7, 0xdc, 0x41, 0xa7, 0xca, 0xf0, 0xa8, 0x50, 0x84, + 0x69, 0xa0, 0xc0, 0xa8, 0x2c, 0xba, 0x82, 0xf3, 0xc0, 0x28, 0xf0, 0xb1, 0x62, 0x1b, 0xd1, 0x5d, + 0x81, 0xcd, 0x63, 0xb6, 0x3f, 0x0d, 0x46, 0x36, 0x00, 0xf5, 0xe3, 0xa6, 0x99, 0xc1, 0xc7, 0xf5, + 0x1a, 0x0a, 0xf0, 0x97, 0xb2, 0x80, 0x5b, 0xaf, 0xd6, 0xad, 0x28, 0x90, 0xa7, 0xb9, 0x3a, 0xc1, + 0x27, 0x54, 0x9f, 0x57, 0xd7, 0x57, 0xba, 0x16, 0x30, 0x42, 0x54, 0x6f, 0x3d, 0xeb, 0x9c, 0x5f, + 0xd9, 0x83, 0x99, 0xe0, 0xea, 0x2b, 0x50, 0x80, 0x01, 0x04, 0x33, 0x2c, 0x75, 0xad, 0xf0, 0x7f, + 0x6a, 0x8d, 0x49, 0xa4, 0x69, 0x29, 0x5b, 0x6b, 0x9e, 0x4b, 0x13, 0x61, 0x9c, 0xeb, 0xab, 0x4f, + 0x38, 0x93, 0x3d, 0x2e, 0xcc, 0x36, 0xc0, 0x60, 0x36, 0x28, 0xe8, 0x46, 0x07, 0x39, 0xf2, 0x32, + 0xc5, 0xc0, 0x94, 0xe2, 0x45, 0xed, 0xec, 0x1e, 0x2a, 0xb3, 0xd2, 0x78, 0x34, 0xc4, 0xec, 0xef, + 0xf0, 0xf0, 0xfb, 0x5c, 0xe5, 0x17, 0x2c, 0x69, 0x19, 0xb6, 0x55, 0x09, 0x79, 0x54, 0x89, 0xca, + 0xaf, 0x8d, 0xc8, 0x6e, 0x32, 0xbe, 0x19, 0x68, 0xd4, 0x42, 0x34, 0x49, 0xae, 0x83, 0x3b, 0xc1, + 0x6b, 0x26, 0x63, 0x4a, 0x2c, 0xf8, 0x9b, 0x37, 0xe9, 0x01, 0x1d, 0xbd, 0xb0, 0x22, 0x66, 0xbc, + 0x93, 0xa6, 0x1e, 0x05, 0x5e, 0xf4, 0x15, 0x1c, 0x47, 0x1f, 0x0f, 0xa4, 0x22, 0x71, 0x50, 0xca, + 0x1c, 0x54, 0x49, 0x8f, 0x0d, 0x42, 0x5f, 0x30, 0x4a, 0xb0, 0xc3, 0xba, 0x5a, 0xa5, 0x8d, 0x83, + 0x1a, 0xe2, 0x8b, 0x3d, 0x5b, 0x31, 0x01, 0x09, 0x53, 0x70, 0xbc, 0x23, 0x8d, 0x66, 0x98, 0x9c, + 0x32, 0x80, 0xcb, 0xdc, 0x8c, 0xbf, 0x28, 0x74, 0x06, 0xfc, 0x66, 0xe4, 0x30, 0xff, 0x0d, 0x41, + 0x81, 0x55, 0x93, 0xc6, 0x69, 0x10, 0xcc, 0x42, 0x60, 0x83, 0x6f, 0xb2, 0xb5, 0x7a, 0xe2, 0xae, + 0x40, 0x53, 0x2b, 0xa9, 0x77, 0x2c, 0x30, 0xf4, 0x91, 0xa6, 0x69, 0x7c, 0x1b, 0x88, 0xc9, 0x25, + 0x18, 0x0a, 0x5c, 0xfc, 0xe3, 0xe0, 0xe2, 0x6b, 0xa9, 0x8b, 0x2f, 0x87, 0x5d, 0x7c, 0xf0, 0xef, + 0x3b, 0xda, 0xa8, 0x86, 0x5d, 0x00, 0xa7, 0xc4, 0x30, 0x84, 0x21, 0x5a, 0x6b, 0x42, 0x13, 0x30, + 0x00, 0xef, 0x32, 0xa1, 0x4b, 0xad, 0xf5, 0x1b, 0x61, 0xa6, 0xae, 0xcd, 0x79, 0x3f, 0x78, 0x02, + 0xfc, 0x91, 0x84, 0xa6, 0x48, 0xa1, 0x69, 0x32, 0x7f, 0x8a, 0x2c, 0xc7, 0xec, 0x03, 0x07, 0xfa, + 0x8b, 0x1d, 0xca, 0x7b, 0x75, 0xed, 0xb5, 0xc6, 0xd6, 0x1a, 0xa0, 0x3b, 0x1e, 0x7a, 0x0b, 0x17, + 0x0c, 0xdd, 0x20, 0x86, 0x64, 0x70, 0x9a, 0xb9, 0x0d, 0x13, 0x8d, 0xbf, 0x50, 0xd7, 0xf5, 0xd6, + 0xb1, 0xce, 0x42, 0xdd, 0x4d, 0xd8, 0x09, 0x00, 0x15, 0xe1, 0x47, 0x92, 0x00, 0x03, 0xa9, 0x25, + 0xfe, 0x54, 0x6c, 0xff, 0x7c, 0x98, 0x19, 0x74, 0xe8, 0x47, 0xd0, 0xad, 0x0d, 0x6c, 0x65, 0x9a, + 0x06, 0x7c, 0x13, 0x70, 0x7a, 0x2a, 0x4a, 0x3d, 0x2b, 0x73, 0xa5, 0x1c, 0x2d, 0xde, 0x7a, 0x6c, + 0x1c, 0x00, 0x59, 0x08, 0xa4, 0x4b, 0x7c, 0x0b, 0xc9, 0x1c, 0x50, 0xe1, 0xdd, 0x86, 0x6a, 0x00, + 0xdc, 0xd2, 0xf9, 0xf0, 0x90, 0x39, 0xa0, 0xc6, 0x8c, 0x10, 0xe7, 0x80, 0x06, 0x23, 0x80, 0xa6, + 0x48, 0xb3, 0x32, 0xe8, 0xbc, 0x6e, 0x58, 0x38, 0x0e, 0x4b, 0xe3, 0x2e, 0xe8, 0x9c, 0x01, 0xd2, + 0x87, 0x41, 0x4c, 0x25, 0xde, 0x0f, 0x0a, 0x81, 0xaa, 0xa1, 0x20, 0xfd, 0x35, 0x01, 0x64, 0xdb, + 0x8e, 0x09, 0xd4, 0x53, 0xf0, 0x1b, 0xf4, 0xbd, 0x40, 0x60, 0x3e, 0xde, 0xb3, 0x72, 0x07, 0x4e, + 0x9a, 0x39, 0x40, 0x73, 0x9a, 0x61, 0x42, 0x92, 0x38, 0x80, 0x69, 0xce, 0x99, 0x03, 0x1a, 0xc0, + 0x44, 0x9d, 0x25, 0xf1, 0x5e, 0x92, 0x34, 0xfc, 0xcb, 0x5f, 0xbf, 0x32, 0x52, 0x89, 0xd8, 0x74, + 0x25, 0xb4, 0x7b, 0x95, 0x96, 0xcb, 0x3f, 0x55, 0xce, 0x1e, 0x1a, 0x52, 0x27, 0xb2, 0x8a, 0x23, + 0x01, 0x06, 0xce, 0x23, 0x5c, 0xc0, 0xb3, 0x3c, 0x8b, 0xfc, 0xcb, 0x8b, 0x54, 0xc6, 0x1a, 0xb3, + 0x66, 0x9b, 0x2c, 0x0c, 0x7a, 0x34, 0xf7, 0xc9, 0x47, 0x3e, 0xa0, 0x55, 0xb6, 0xaa, 0x17, 0x66, + 0x67, 0x5b, 0x04, 0x07, 0x77, 0x80, 0x6f, 0xf5, 0xb5, 0xa9, 0xb8, 0x03, 0xc2, 0x2d, 0xb6, 0xa1, + 0x74, 0x9c, 0xbd, 0x22, 0x1b, 0x5f, 0xba, 0x69, 0xbe, 0x18, 0xba, 0x12, 0x11, 0x1e, 0x07, 0xc0, + 0x71, 0x4c, 0xc4, 0x8e, 0x7c, 0x29, 0x6b, 0x2e, 0x77, 0x20, 0xe0, 0x93, 0x35, 0x62, 0x5b, 0x00, + 0x20, 0x55, 0xf6, 0xa5, 0x79, 0x08, 0xf9, 0xd6, 0x30, 0xe4, 0x4a, 0x4c, 0x27, 0x3e, 0xfa, 0x21, + 0x3d, 0x89, 0xa9, 0x4c, 0x49, 0x9d, 0x1a, 0xc5, 0xb0, 0xc2, 0x44, 0x7b, 0x2c, 0xfe, 0x3a, 0x88, + 0x4b, 0x39, 0x00, 0x44, 0x8b, 0x03, 0x8b, 0xe8, 0xc1, 0x5c, 0xf4, 0xc9, 0xf6, 0x4d, 0x4a, 0xce, + 0xfa, 0x67, 0xd9, 0xd4, 0x4f, 0x69, 0x51, 0x52, 0x96, 0xab, 0x2f, 0x8f, 0xbc, 0x96, 0x4f, 0x7f, + 0x82, 0x41, 0xd0, 0xb8, 0x7b, 0x9d, 0x49, 0x16, 0xf9, 0xa1, 0xcf, 0x43, 0x47, 0xef, 0xce, 0x07, + 0x3c, 0xf4, 0xbe, 0xdf, 0x64, 0x91, 0x17, 0x7e, 0x1e, 0xba, 0x69, 0xe1, 0xdc, 0xf8, 0xd2, 0x90, + 0xf4, 0x31, 0xd6, 0x77, 0x88, 0xf4, 0x9d, 0x10, 0x8f, 0x07, 0x0b, 0x84, 0x85, 0x88, 0x13, 0x82, + 0x4f, 0x5b, 0x63, 0x5a, 0x44, 0x24, 0x83, 0x17, 0xad, 0x2a, 0xf1, 0xa6, 0x86, 0x3b, 0xe0, 0xcd, + 0x31, 0x95, 0xfe, 0x48, 0x9e, 0xf6, 0x61, 0x38, 0xcd, 0xce, 0xed, 0x8f, 0xc4, 0x9b, 0x4a, 0x7c, + 0x41, 0x17, 0x77, 0x81, 0x3f, 0xe1, 0x71, 0xb4, 0xcf, 0xd7, 0xa1, 0x11, 0x6f, 0x06, 0x60, 0xd1, + 0xec, 0xe9, 0xca, 0x14, 0x2d, 0x86, 0x01, 0xc2, 0xf7, 0xb8, 0x03, 0x34, 0xc1, 0xe0, 0x10, 0xbe, + 0x92, 0x6e, 0x68, 0xe2, 0xd2, 0x9b, 0x72, 0x2c, 0x76, 0xd9, 0x06, 0x3b, 0xd0, 0x94, 0xcf, 0x43, + 0x5e, 0x21, 0x02, 0xb2, 0xd2, 0x8e, 0x38, 0xcf, 0xa7, 0xf8, 0x2b, 0x67, 0xa5, 0x8b, 0x71, 0xcb, + 0x9a, 0xf6, 0x79, 0x68, 0x7b, 0xc2, 0xf9, 0xff, 0x32, 0x09, 0xe6, 0xcf, 0x37, 0x95, 0x6a, 0xe4, + 0x9f, 0xfd, 0x56, 0xb9, 0x7d, 0xc4, 0x39, 0xdd, 0x2d, 0xca, 0x6f, 0x82, 0xa8, 0xd0, 0x7d, 0xea, + 0x5f, 0xb4, 0x73, 0xb2, 0xc9, 0xbe, 0x07, 0xcf, 0x9a, 0xd2, 0xe9, 0xc9, 0x8b, 0xba, 0xe3, 0x23, + 0xd4, 0x4b, 0xbe, 0x0d, 0x8d, 0xc8, 0x2c, 0x9a, 0x11, 0xa5, 0x52, 0x92, 0x1c, 0xee, 0xb1, 0x07, + 0x80, 0x80, 0xf2, 0x34, 0x0a, 0xa6, 0xea, 0xc0, 0x5f, 0x16, 0x21, 0xf5, 0x9e, 0x4f, 0x71, 0xf1, + 0xf6, 0x97, 0xe8, 0xdb, 0x62, 0xf9, 0xf2, 0x1b, 0x17, 0x94, 0xe9, 0x77, 0x46, 0x78, 0xdc, 0xf8, + 0x23, 0x6a, 0xa4, 0xa0, 0x33, 0x23, 0x0f, 0x46, 0x32, 0xc9, 0x85, 0x17, 0x46, 0x23, 0xc6, 0x29, + 0x88, 0xcd, 0x91, 0x23, 0x46, 0x23, 0x46, 0xef, 0x69, 0xf8, 0xb6, 0x16, 0x7c, 0xfd, 0x37, 0x49, + 0x9e, 0x4f, 0xef, 0x56, 0xd5, 0xa4, 0x40, 0x26, 0xf5, 0x12, 0x7f, 0x98, 0x3c, 0xa7, 0x23, 0x19, + 0x89, 0xfb, 0xd8, 0x9a, 0xc8, 0x9a, 0x8c, 0xd9, 0xa4, 0x62, 0xae, 0xad, 0x31, 0x63, 0x01, 0xcf, + 0x80, 0x83, 0x21, 0x7a, 0xc1, 0x18, 0xb5, 0xe7, 0x9b, 0xe4, 0x41, 0xe5, 0x35, 0x44, 0x92, 0xa1, + 0x6e, 0x60, 0x16, 0x49, 0x19, 0xea, 0xd4, 0xa0, 0xd0, 0x09, 0x16, 0x0c, 0x3c, 0xc5, 0x2f, 0xce, + 0x2b, 0x93, 0x17, 0xd0, 0xf7, 0x88, 0x33, 0x34, 0x07, 0x31, 0x25, 0xcb, 0xf3, 0x66, 0x39, 0x5e, + 0x79, 0x83, 0x9f, 0xfd, 0x55, 0xa8, 0xb9, 0x22, 0x02, 0x74, 0xd5, 0xd6, 0x28, 0x62, 0x2b, 0xc3, + 0xdb, 0xc8, 0xef, 0xd1, 0x2d, 0xf2, 0xb8, 0x9f, 0xc5, 0xf4, 0x0c, 0x41, 0xa6, 0xcb, 0x78, 0x3d, + 0x04, 0xda, 0x8a, 0xcb, 0xf8, 0x12, 0xe9, 0x9b, 0x67, 0x2a, 0xd5, 0xc9, 0x2b, 0x3e, 0x08, 0x67, + 0x91, 0xdc, 0x0b, 0x94, 0xa5, 0xe3, 0xda, 0x7f, 0x81, 0x69, 0x81, 0xff, 0xad, 0x5c, 0x42, 0xfb, + 0xd3, 0xa0, 0x1a, 0x7f, 0xaf, 0xce, 0x66, 0x08, 0x90, 0xae, 0x1d, 0x9b, 0xb8, 0x03, 0x27, 0x72, + 0x4c, 0xf6, 0x33, 0x08, 0x71, 0x92, 0x42, 0x68, 0x3c, 0xfc, 0x45, 0x5b, 0x23, 0xa3, 0x08, 0x83, + 0x4a, 0x6c, 0x83, 0x91, 0x4f, 0x98, 0x72, 0x4a, 0x67, 0xca, 0x37, 0x7f, 0x13, 0x22, 0x50, 0x3e, + 0xa8, 0x77, 0xe8, 0x75, 0xc8, 0x47, 0x94, 0x9c, 0x15, 0xfa, 0x3a, 0xe4, 0xfc, 0x5b, 0x21, 0xba, + 0x8e, 0xfa, 0xbd, 0x10, 0xee, 0x80, 0xaf, 0x14, 0x9d, 0x3f, 0x93, 0x7c, 0xd9, 0xaf, 0x90, 0x84, + 0x97, 0xc3, 0xf3, 0xe3, 0x01, 0x00, 0x0e, 0x44, 0xdf, 0x19, 0x6c, 0xba, 0xa5, 0x34, 0x67, 0x69, + 0xa5, 0xac, 0xc4, 0x09, 0x59, 0x3a, 0xae, 0xfa, 0x1e, 0x7a, 0x53, 0x2e, 0x13, 0x9f, 0x78, 0x93, + 0x23, 0x46, 0x2f, 0x9e, 0x9d, 0xf2, 0xc7, 0x01, 0xb7, 0x30, 0x5a, 0xfa, 0x5e, 0x58, 0x32, 0xe1, + 0x9b, 0x60, 0x0a, 0x70, 0x35, 0xf5, 0x57, 0x43, 0x3f, 0xa1, 0xd7, 0xc8, 0x5f, 0x0c, 0xbd, 0xe3, + 0x7a, 0x05, 0xfb, 0x7b, 0x6d, 0xf8, 0xca, 0x00, 0x7f, 0x1c, 0xbe, 0xae, 0x07, 0x85, 0xa6, 0xa0, + 0x70, 0xaa, 0x74, 0x96, 0x7c, 0xef, 0x6f, 0x86, 0x75, 0x20, 0x9a, 0x4a, 0x20, 0x7f, 0xc5, 0xb6, + 0x82, 0x6f, 0xe3, 0x5e, 0xfc, 0x6f, 0xa4, 0xf2, 0xca, 0x48, 0x09, 0x36, 0xfd, 0x9c, 0x44, 0x69, + 0xad, 0xce, 0x30, 0x48, 0xce, 0x40, 0xf8, 0xc9, 0xed, 0xb9, 0x40, 0xdf, 0x9d, 0x11, 0x62, 0x0c, + 0xe7, 0x13, 0x4e, 0x73, 0x7b, 0x3e, 0x63, 0x94, 0x1f, 0x3d, 0xca, 0xd6, 0xb2, 0x97, 0xc1, 0x87, + 0x97, 0x73, 0xe4, 0x09, 0xe7, 0x94, 0xfb, 0x83, 0x03, 0xe6, 0x2b, 0xec, 0x79, 0xdb, 0x0a, 0xd8, + 0x5f, 0x5f, 0xf5, 0xc5, 0x18, 0x3b, 0x61, 0x2d, 0xbd, 0x3e, 0x56, 0xca, 0xd6, 0x39, 0x55, 0xe4, + 0x86, 0x3f, 0x29, 0x84, 0x22, 0xb9, 0x11, 0xce, 0x28, 0x3f, 0x59, 0x91, 0x98, 0x6b, 0x4f, 0x42, + 0x6b, 0xb1, 0x41, 0xb9, 0x5f, 0xc6, 0x99, 0xd3, 0x70, 0xe6, 0xdf, 0xb1, 0xb0, 0xf9, 0x83, 0xb9, + 0xbc, 0x6d, 0x68, 0xa4, 0x39, 0x16, 0x78, 0x01, 0x3f, 0x13, 0x4f, 0x31, 0xfe, 0x01, 0x73, 0x32, + 0xff, 0x2b, 0x6c, 0x92, 0xb2, 0xd0, 0xaf, 0x6d, 0x01, 0xac, 0xe4, 0x9f, 0x76, 0x2b, 0x9b, 0x2d, + 0x44, 0xdd, 0x98, 0xde, 0x61, 0xef, 0xc6, 0xe8, 0x48, 0x67, 0xb1, 0x0b, 0x18, 0x0e, 0xb0, 0xf2, + 0x44, 0x50, 0x50, 0x7b, 0xb6, 0x85, 0x1a, 0xa4, 0xab, 0x4a, 0xfe, 0x5d, 0x87, 0x62, 0x90, 0x7a, + 0x40, 0x43, 0xec, 0xd7, 0xc3, 0xf1, 0x9c, 0xe5, 0xe0, 0x90, 0x0b, 0x63, 0x5b, 0x35, 0x4c, 0xbc, + 0xf4, 0x1e, 0x9b, 0xa4, 0x85, 0xb2, 0x16, 0xca, 0x49, 0xfb, 0x58, 0x9b, 0xa1, 0x5b, 0x98, 0x1e, + 0x6a, 0xd6, 0xf6, 0x9d, 0xb3, 0x11, 0xad, 0x4d, 0x62, 0x0e, 0x2b, 0xcd, 0xf7, 0xd8, 0x0c, 0xf8, + 0x3a, 0xc7, 0x61, 0xda, 0x4a, 0x62, 0xc2, 0x69, 0xed, 0x60, 0xa9, 0x7f, 0xcf, 0xca, 0xef, 0xc1, + 0x52, 0xf0, 0x45, 0xe8, 0x59, 0x78, 0x78, 0x29, 0xb4, 0x28, 0x86, 0xbb, 0xa3, 0x25, 0x6c, 0xb8, + 0xd9, 0xd9, 0xd4, 0x70, 0x4f, 0x91, 0x23, 0xdf, 0xa7, 0x55, 0xb2, 0x10, 0x82, 0xc7, 0x1f, 0xb1, + 0x3d, 0xb4, 0xa1, 0x9e, 0x61, 0xda, 0x8b, 0xc5, 0x0e, 0x16, 0x7c, 0xb0, 0xf7, 0x23, 0x9c, 0xaa, + 0xea, 0x73, 0xce, 0xc0, 0xfb, 0x11, 0x9c, 0xbb, 0x0e, 0x03, 0x8b, 0x0f, 0xbe, 0x2a, 0xfe, 0x87, + 0x00, 0x6f, 0x23, 0x40, 0xcb, 0xdd, 0x00, 0xac, 0xa0, 0x00, 0xb0, 0x4a, 0xde, 0xda, 0x61, 0xda, + 0xf8, 0x14, 0xf1, 0x01, 0xc0, 0xd7, 0x00, 0x70, 0x9c, 0x8e, 0xd0, 0x8e, 0x23, 0x08, 0x5b, 0xf6, + 0x9d, 0xfd, 0xaa, 0xf8, 0x70, 0xa8, 0xf7, 0xdd, 0x8d, 0x59, 0x95, 0x27, 0x22, 0x48, 0xd3, 0x57, + 0x4f, 0xfd, 0x83, 0xe9, 0x85, 0x07, 0xf7, 0xfd, 0xf6, 0x1f, 0xe2, 0x26, 0x44, 0xcb, 0xaf, 0x0c, + 0xe1, 0x12, 0x85, 0xc9, 0xed, 0xaf, 0x40, 0x71, 0xdc, 0xec, 0x3b, 0x9a, 0x88, 0xaf, 0x5e, 0x91, + 0x5d, 0x78, 0x41, 0x40, 0x53, 0xd9, 0xe6, 0x8e, 0xbc, 0x42, 0xa4, 0xef, 0xd5, 0x7b, 0xb9, 0x5f, + 0x8a, 0xfd, 0x53, 0xe8, 0x59, 0x84, 0x63, 0xb9, 0xbe, 0xf7, 0xe0, 0x14, 0xfa, 0xfb, 0x22, 0xdc, + 0x2f, 0x49, 0x23, 0x7d, 0x8f, 0x08, 0x13, 0x77, 0xea, 0xd4, 0x75, 0x98, 0xac, 0xec, 0x55, 0xb7, + 0x50, 0x30, 0x61, 0x32, 0x69, 0xea, 0xfb, 0x12, 0x2c, 0x23, 0x04, 0x87, 0x8d, 0xbf, 0x0a, 0xff, + 0xbe, 0xd9, 0x32, 0xfc, 0x39, 0x34, 0x32, 0x05, 0x7f, 0x1a, 0x6d, 0x8c, 0xb3, 0x9a, 0xea, 0xe1, + 0x4f, 0x21, 0x53, 0x4c, 0xf2, 0xc6, 0x33, 0x8a, 0xd6, 0xf7, 0x1e, 0x63, 0x64, 0x10, 0xbf, 0x82, + 0x3f, 0x34, 0xf2, 0x01, 0x9d, 0x8c, 0x7a, 0x26, 0xc7, 0x53, 0x75, 0x6b, 0x37, 0xa5, 0x19, 0xf3, + 0x48, 0xc1, 0x35, 0xfc, 0x99, 0x1c, 0x13, 0xb0, 0xcc, 0xf4, 0x1f, 0xca, 0xcf, 0xe4, 0xe1, 0xdb, + 0x5e, 0x8b, 0x21, 0x56, 0x1b, 0xf4, 0x1c, 0x9b, 0x5d, 0x19, 0x3e, 0x1a, 0xba, 0xde, 0xf3, 0x9e, + 0xe8, 0xea, 0x64, 0x9c, 0x53, 0x49, 0x43, 0x96, 0x58, 0x17, 0x4f, 0x2e, 0x09, 0xfb, 0xec, 0x09, + 0xca, 0x4f, 0x1b, 0xbc, 0x00, 0x2a, 0x04, 0xb5, 0x84, 0x1e, 0x6a, 0x88, 0xc7, 0x53, 0xc3, 0xf8, + 0x40, 0x44, 0x1c, 0x47, 0xdf, 0xf2, 0x57, 0x1f, 0x5e, 0x0c, 0x82, 0x2b, 0x0e, 0x4d, 0xdf, 0x39, + 0x5e, 0x8a, 0xfb, 0xb8, 0x3d, 0x1f, 0x7f, 0xbd, 0x2b, 0xd7, 0xfe, 0xac, 0x72, 0x04, 0x91, 0x0a, + 0xbd, 0x0f, 0x56, 0x62, 0x5c, 0x50, 0xd3, 0xf6, 0x38, 0x0b, 0x02, 0xf7, 0x13, 0x66, 0x41, 0x55, + 0x14, 0xd3, 0x58, 0xcd, 0x2c, 0x84, 0x2f, 0xc0, 0xf4, 0x25, 0x5f, 0x87, 0x16, 0x6b, 0x17, 0x43, + 0x51, 0xf4, 0xaa, 0x84, 0x4b, 0x30, 0x34, 0xc7, 0xde, 0xff, 0x71, 0x80, 0x61, 0x0a, 0xea, 0xef, + 0xe8, 0xbd, 0x98, 0x2d, 0x00, 0xe3, 0x48, 0x30, 0xc4, 0xcb, 0x2f, 0x87, 0xcb, 0xac, 0xfc, 0xdc, + 0x98, 0x72, 0x84, 0xfc, 0xcc, 0x98, 0x72, 0xa4, 0xfc, 0xc4, 0x98, 0xb2, 0x4a, 0x5e, 0x3f, 0xa6, + 0x1c, 0x25, 0xaf, 0x18, 0x53, 0x1e, 0x27, 0xcf, 0x1f, 0x53, 0x1e, 0x2f, 0x4f, 0x53, 0xca, 0x8f, + 0xd3, 0xa2, 0x5a, 0xd6, 0xd0, 0xe2, 0x70, 0x7b, 0xb4, 0x7c, 0x7b, 0x68, 0x54, 0x7b, 0x8c, 0xdc, + 0x39, 0xa4, 0xb4, 0x2b, 0xe5, 0x09, 0xf2, 0xb5, 0x31, 0x65, 0x8d, 0x7c, 0x6a, 0x4c, 0x79, 0xa2, + 0x7c, 0x64, 0x4c, 0x79, 0x92, 0xfc, 0x9b, 0xa1, 0x31, 0xe3, 0x73, 0xf2, 0xcf, 0x86, 0x46, 0xe3, + 0xa3, 0x95, 0xa5, 0xd1, 0xf3, 0xc5, 0xca, 0xcf, 0x8f, 0x85, 0xbf, 0x47, 0x7e, 0x66, 0x0c, 0xfc, + 0x64, 0xf9, 0x89, 0x31, 0xe5, 0x38, 0x79, 0xfd, 0x98, 0xf2, 0x14, 0x9a, 0x6e, 0x39, 0x52, 0x9e, + 0x2a, 0xcf, 0x1f, 0x53, 0xbe, 0x57, 0x9e, 0x36, 0xa6, 0x1c, 0x2f, 0x4f, 0x18, 0x53, 0x4e, 0x90, + 0x6f, 0x7f, 0x3b, 0xba, 0x7c, 0x9f, 0xec, 0x1f, 0x53, 0x9e, 0x26, 0x5f, 0x1d, 0x53, 0x4e, 0x94, + 0x4f, 0x8e, 0x29, 0xdf, 0x2f, 0x7f, 0xf2, 0xed, 0xa8, 0xf5, 0x4c, 0x97, 0x7f, 0xf3, 0xed, 0x98, + 0xf5, 0xcc, 0x90, 0x7f, 0xf6, 0xad, 0x92, 0x59, 0xc9, 0xa0, 0x47, 0xcc, 0xe0, 0x81, 0x20, 0xfe, + 0xb4, 0x0b, 0xfe, 0xea, 0x17, 0x4a, 0x37, 0x66, 0x9c, 0x27, 0xc1, 0x07, 0x7f, 0x9b, 0x29, 0x23, + 0x33, 0x29, 0x49, 0xcf, 0xa4, 0x39, 0x9d, 0xd6, 0x6d, 0xe5, 0x4e, 0x6b, 0xb1, 0x6e, 0x47, 0xd9, + 0x56, 0x61, 0x9b, 0xb5, 0xd0, 0x61, 0x2d, 0x2a, 0x9e, 0x3b, 0x4f, 0x57, 0xb6, 0x5d, 0x57, 0xbe, + 0xcb, 0xca, 0x94, 0x6f, 0xdb, 0xb6, 0x5c, 0xb7, 0x76, 0xbb, 0xd3, 0xfa, 0xb4, 0xd5, 0xa1, 0x2b, + 0xdb, 0x61, 0x75, 0xd8, 0xb6, 0x96, 0xed, 0xd4, 0x95, 0x6c, 0xd7, 0x6d, 0xb3, 0x6e, 0x2b, 0x73, + 0xec, 0xd6, 0x39, 0x8a, 0xb6, 0x3f, 0x6d, 0xd5, 0x6d, 0x29, 0xda, 0xba, 0x45, 0xd8, 0x5a, 0xe4, + 0x2c, 0x29, 0xdb, 0xce, 0x38, 0x6d, 0xce, 0xf2, 0xe5, 0xba, 0x3c, 0xab, 0x03, 0x80, 0x75, 0x0e, + 0xab, 0x53, 0x70, 0x6c, 0x87, 0xc1, 0x9f, 0xb5, 0x3a, 0xca, 0x74, 0x9b, 0x77, 0x3b, 0xad, 0x15, + 0xba, 0xcd, 0x56, 0x5b, 0x99, 0xc3, 0xaa, 0x73, 0x42, 0xd7, 0x0a, 0x1b, 0xc0, 0x6c, 0x29, 0xdb, + 0x56, 0xbe, 0xd5, 0xea, 0xb4, 0x32, 0xd9, 0xc6, 0xb5, 0x4c, 0x9e, 0x75, 0x8b, 0xe0, 0x28, 0x71, + 0xee, 0x66, 0x36, 0x84, 0xe6, 0x62, 0xb6, 0x59, 0xb7, 0x0b, 0x8c, 0x51, 0x99, 0x6d, 0x5b, 0x51, + 0xb9, 0xce, 0xba, 0xcb, 0x5e, 0x24, 0x54, 0x00, 0xc2, 0x0b, 0x19, 0xeb, 0x2e, 0x67, 0x21, 0xe0, + 0x51, 0x58, 0xb4, 0x75, 0x6b, 0xd9, 0x96, 0xe5, 0x30, 0x90, 0xb0, 0xdd, 0x39, 0x8c, 0x64, 0x85, + 0x6e, 0xa7, 0xdd, 0xba, 0x5d, 0x57, 0xb4, 0xb5, 0xe4, 0xe9, 0xed, 0x25, 0xdb, 0x9f, 0x66, 0x4c, + 0x8f, 0xf3, 0xd9, 0x96, 0xf9, 0xcc, 0x9c, 0x0a, 0x18, 0x61, 0x8b, 0xb5, 0x1c, 0x71, 0xd5, 0x15, + 0x39, 0x75, 0x73, 0x76, 0x2d, 0xd4, 0xf1, 0x0e, 0x47, 0x19, 0xe2, 0x51, 0x6c, 0x5d, 0x0e, 0x65, + 0xc0, 0xe1, 0x69, 0x98, 0xd4, 0xa9, 0xdb, 0x5e, 0xe6, 0xd4, 0x95, 0x3b, 0xac, 0x15, 0xf0, 0x1c, + 0x46, 0x80, 0xce, 0x44, 0xd7, 0x39, 0x3c, 0xcf, 0x42, 0x06, 0xe8, 0xa4, 0x83, 0x42, 0x05, 0xd6, + 0x3a, 0xcb, 0xca, 0x74, 0x65, 0x5b, 0x8b, 0x99, 0xb5, 0xdb, 0x77, 0xc0, 0xcc, 0xc5, 0xba, 0xb2, + 0x72, 0x1c, 0x36, 0x44, 0x94, 0xac, 0x92, 0xad, 0xd6, 0xed, 0x45, 0xdb, 0xac, 0x14, 0x6a, 0x6b, + 0xd9, 0xf6, 0xa7, 0x75, 0x73, 0xb7, 0x15, 0xed, 0xd2, 0xe9, 0x17, 0x3f, 0xa2, 0xdb, 0x62, 0x2f, + 0x72, 0x54, 0xcc, 0x8b, 0x61, 0x36, 0x42, 0xcb, 0xb6, 0xa2, 0xed, 0xbb, 0x75, 0x7c, 0xf2, 0xe2, + 0x24, 0x1d, 0xcc, 0xec, 0x28, 0xb1, 0x56, 0xcc, 0x64, 0x32, 0xca, 0x84, 0xad, 0xc5, 0x14, 0x21, + 0x18, 0x60, 0xf3, 0x56, 0xab, 0x2e, 0x0d, 0x5a, 0xb7, 0x96, 0x6c, 0xb7, 0x32, 0x79, 0x6b, 0x8d, + 0x99, 0x0c, 0x93, 0x0e, 0x5c, 0x7b, 0xa6, 0xbc, 0xac, 0x04, 0x30, 0xb5, 0x15, 0x39, 0x97, 0x2c, + 0x06, 0x62, 0x6c, 0x45, 0x22, 0x39, 0x70, 0x60, 0xe0, 0x16, 0x32, 0x55, 0x67, 0x2b, 0x82, 0xf9, + 0x8b, 0x75, 0x73, 0xb7, 0x94, 0x39, 0x1c, 0x02, 0x65, 0xb9, 0x0d, 0x2a, 0x2a, 0x76, 0x03, 0xdc, + 0xb6, 0x55, 0xf3, 0x98, 0xd5, 0xd6, 0xed, 0x56, 0x47, 0xd1, 0x56, 0x58, 0x72, 0x99, 0xd3, 0xba, + 0x85, 0xae, 0xd1, 0x56, 0x24, 0x6c, 0x75, 0x32, 0x99, 0x25, 0x15, 0xcf, 0xe8, 0xac, 0x94, 0x46, + 0x48, 0xad, 0x4c, 0x47, 0xc9, 0x0e, 0x2b, 0xd2, 0x69, 0x6d, 0xde, 0x06, 0xc3, 0xc3, 0x0f, 0x27, + 0xa1, 0x7c, 0x28, 0x8b, 0x75, 0x94, 0x01, 0x82, 0xc5, 0x25, 0x0e, 0xe8, 0x8d, 0xc4, 0xaa, 0x28, + 0x79, 0xd6, 0xca, 0xf0, 0x59, 0x6b, 0x75, 0xa6, 0xb4, 0xdc, 0x8d, 0x48, 0x7f, 0x90, 0x9b, 0x0a, + 0x27, 0x90, 0x50, 0x21, 0xe0, 0x16, 0xbb, 0x75, 0xcb, 0x33, 0x21, 0xa4, 0x90, 0x86, 0x20, 0x34, + 0xc2, 0x96, 0x2d, 0xd6, 0x8a, 0x0a, 0x9b, 0xb0, 0x75, 0xeb, 0x6e, 0x80, 0x2d, 0x71, 0x96, 0xc0, + 0xb0, 0xcf, 0x5a, 0x8b, 0x63, 0xc6, 0x0a, 0x55, 0x49, 0x85, 0x0e, 0x78, 0x52, 0x0c, 0x4c, 0xd5, + 0x39, 0xed, 0x56, 0xba, 0x08, 0x94, 0xc8, 0x8a, 0x6d, 0x30, 0x34, 0x34, 0x97, 0x17, 0x6d, 0x79, + 0xc6, 0xea, 0xac, 0xd0, 0xcd, 0x2d, 0x71, 0x22, 0x1c, 0xb0, 0xb8, 0x58, 0x91, 0xbc, 0x79, 0x0b, + 0x74, 0xc5, 0x65, 0x3b, 0xb7, 0x6f, 0x2d, 0x03, 0x5a, 0x6c, 0x2b, 0x79, 0xda, 0xee, 0xd4, 0x39, + 0x8b, 0x9e, 0xb1, 0x52, 0x46, 0x58, 0x1d, 0x0b, 0x63, 0x98, 0xac, 0xb4, 0x8d, 0x4b, 0x16, 0x8f, + 0xac, 0x2a, 0x44, 0x2e, 0x67, 0x99, 0x42, 0xbd, 0xb1, 0x8b, 0x63, 0xb2, 0x86, 0x5b, 0xe9, 0x78, + 0xb0, 0x2e, 0xd0, 0x83, 0x25, 0x0b, 0x99, 0x45, 0x9b, 0x01, 0x6e, 0xd1, 0xd6, 0x92, 0x6d, 0xc0, + 0x9c, 0x87, 0x36, 0x97, 0x94, 0x55, 0x2c, 0x04, 0x02, 0x33, 0x77, 0x95, 0x29, 0x69, 0x00, 0x67, + 0xe4, 0x04, 0x8c, 0x07, 0x73, 0x97, 0x54, 0x94, 0x29, 0xb3, 0xd2, 0xb9, 0x36, 0x5b, 0x77, 0x97, + 0x6d, 0x2f, 0x06, 0x5e, 0x83, 0x00, 0xd9, 0xe8, 0x02, 0x99, 0x69, 0x4f, 0x2c, 0xd1, 0x6f, 0x33, + 0xa5, 0x65, 0xaf, 0xcd, 0x80, 0xa7, 0x47, 0x56, 0xe8, 0xb7, 0x4d, 0x7b, 0x22, 0x09, 0x54, 0x93, + 0x49, 0x03, 0xa9, 0xd8, 0xfe, 0x90, 0x50, 0x41, 0xa5, 0x62, 0xdb, 0x28, 0x35, 0x01, 0xd1, 0xd9, + 0x8d, 0xa4, 0x02, 0x9a, 0x97, 0x14, 0x5b, 0x75, 0x45, 0xba, 0x10, 0x4c, 0x85, 0xc2, 0xdb, 0x85, + 0xa3, 0x64, 0xaa, 0x18, 0xb4, 0xcf, 0x81, 0x08, 0xea, 0x36, 0xd3, 0x45, 0x22, 0x83, 0x19, 0x3a, + 0x17, 0x4c, 0x90, 0xb4, 0x8b, 0x49, 0x43, 0x1d, 0xa2, 0x2a, 0x11, 0x16, 0x7a, 0xc6, 0x04, 0x7a, + 0x51, 0x01, 0x83, 0x3e, 0x63, 0xdd, 0xad, 0x50, 0x08, 0xf5, 0x1c, 0x9f, 0xe6, 0x54, 0x2c, 0x0c, + 0x71, 0x2b, 0x63, 0x6b, 0x59, 0x85, 0x95, 0x52, 0x51, 0x70, 0x0c, 0x6b, 0xc0, 0x30, 0xd5, 0x9e, + 0xb6, 0x3a, 0x75, 0x99, 0x6b, 0x32, 0x4c, 0x60, 0x3b, 0x40, 0x10, 0x8a, 0x01, 0x4d, 0x5b, 0x19, + 0x48, 0xda, 0x8e, 0x12, 0x54, 0x23, 0x98, 0x34, 0x89, 0xc9, 0x73, 0x02, 0x23, 0xc1, 0x4a, 0x6c, + 0xb1, 0x2e, 0x8f, 0x61, 0x74, 0xba, 0x27, 0xe6, 0x94, 0x17, 0xc4, 0x30, 0x6b, 0x80, 0x6f, 0xe1, + 0x65, 0x86, 0x94, 0xb1, 0xcc, 0xb1, 0x5c, 0xb7, 0x41, 0x70, 0x22, 0xa5, 0x94, 0x06, 0x45, 0xd5, + 0x81, 0x25, 0x0e, 0x61, 0x0b, 0xa0, 0x05, 0x4b, 0x06, 0xf4, 0x8b, 0xe8, 0xd3, 0xb0, 0xe8, 0x87, + 0xf0, 0x09, 0x4b, 0xae, 0x71, 0xa3, 0x59, 0x37, 0x77, 0x8e, 0x00, 0x12, 0x82, 0xaa, 0x49, 0x25, + 0x49, 0x07, 0x56, 0x4a, 0xb7, 0x31, 0x6b, 0xa3, 0x49, 0x67, 0x07, 0x96, 0x80, 0x7a, 0xc7, 0x30, + 0xe9, 0x60, 0x60, 0x8a, 0x43, 0x26, 0x0f, 0x8d, 0x88, 0xb5, 0x18, 0x06, 0x32, 0x21, 0xe3, 0x15, + 0x45, 0xf9, 0x47, 0xa2, 0xa3, 0x58, 0x56, 0x20, 0x73, 0xc5, 0x16, 0x47, 0x49, 0x39, 0x20, 0xcc, + 0xac, 0x5a, 0xb5, 0x8a, 0xb1, 0x16, 0x97, 0xe0, 0x23, 0x48, 0x1d, 0xb3, 0x70, 0x11, 0x13, 0xc3, + 0x64, 0x6f, 0xcc, 0xca, 0xfb, 0x3b, 0x76, 0x26, 0x44, 0xc0, 0x85, 0xcc, 0x4c, 0x58, 0x16, 0x93, + 0x69, 0xdd, 0x51, 0xb2, 0xc5, 0x4a, 0xb9, 0x56, 0xb4, 0x03, 0x5a, 0x90, 0xa5, 0xc3, 0xc6, 0x66, + 0x63, 0x5e, 0x1e, 0x13, 0x33, 0x73, 0xa6, 0x2e, 0x4f, 0x11, 0x46, 0x45, 0x33, 0x10, 0xd4, 0x86, + 0x88, 0xcf, 0xc4, 0xa6, 0x35, 0x45, 0xa0, 0xbb, 0xbb, 0xcb, 0x04, 0xa0, 0x44, 0x79, 0x09, 0xa0, + 0x78, 0xb7, 0x60, 0x02, 0xca, 0xa8, 0x53, 0x28, 0xec, 0x0b, 0x74, 0x54, 0x96, 0xe1, 0x4b, 0x01, + 0x5a, 0xa0, 0x03, 0x82, 0x8c, 0x16, 0x6f, 0x1c, 0x2f, 0xac, 0x10, 0x60, 0xa5, 0x90, 0x01, 0x65, + 0x20, 0x43, 0xf0, 0x85, 0x43, 0x94, 0x17, 0x39, 0x9c, 0x25, 0xb8, 0x82, 0x0a, 0xdc, 0x4b, 0xb0, + 0x46, 0x11, 0x2e, 0xba, 0x80, 0x55, 0x31, 0x31, 0xcc, 0x77, 0x94, 0x44, 0x91, 0xa9, 0x8c, 0x8d, + 0xb9, 0x8f, 0xcd, 0x4f, 0x7b, 0x6c, 0xe3, 0xfc, 0x4c, 0xfe, 0x31, 0x85, 0x82, 0xd8, 0x6f, 0xa1, + 0x22, 0x0e, 0x0f, 0x55, 0x84, 0x6c, 0xb3, 0x42, 0xf0, 0x11, 0xc1, 0xa4, 0xc6, 0x84, 0x31, 0x82, + 0x2c, 0xa1, 0x18, 0x2b, 0xa5, 0xd0, 0x04, 0xdf, 0x99, 0x67, 0x21, 0x90, 0xfb, 0x3b, 0x74, 0xae, + 0x80, 0xa5, 0x54, 0x60, 0x71, 0xe7, 0xb0, 0x70, 0x8c, 0x08, 0x6b, 0x59, 0x39, 0xec, 0x24, 0x94, + 0x9a, 0x73, 0x76, 0x21, 0x15, 0x36, 0x03, 0x53, 0x15, 0x33, 0xa3, 0x18, 0xb9, 0xbb, 0xf6, 0xbc, + 0x1f, 0x09, 0x56, 0xdc, 0xa0, 0x46, 0x83, 0xe8, 0xe6, 0x08, 0x21, 0x91, 0x01, 0x72, 0x08, 0x0e, + 0x2a, 0x70, 0x73, 0x84, 0x98, 0x31, 0xe6, 0xe2, 0x7f, 0xb4, 0x1a, 0x9b, 0x85, 0x12, 0xd0, 0xd8, + 0xb5, 0x99, 0x60, 0xbd, 0x40, 0x44, 0x9d, 0x5b, 0xec, 0x60, 0x38, 0x86, 0x65, 0x2e, 0x2c, 0x90, + 0xa0, 0xfd, 0xbb, 0x4a, 0xb6, 0x09, 0xdb, 0xbe, 0x2b, 0x75, 0xa0, 0xfa, 0x45, 0x8e, 0x2d, 0x76, + 0xca, 0x73, 0x27, 0x43, 0xf5, 0xae, 0x70, 0x33, 0xac, 0xff, 0x99, 0xe5, 0x3a, 0xfa, 0xa5, 0x20, + 0x3a, 0xac, 0xe2, 0x36, 0x94, 0xdd, 0xe5, 0xb0, 0x47, 0x86, 0x1d, 0x84, 0x32, 0x45, 0xc9, 0x36, + 0xa3, 0x30, 0x55, 0x50, 0xc9, 0x66, 0x78, 0xc5, 0x42, 0x51, 0x2d, 0x5d, 0xa8, 0x03, 0x93, 0xb2, + 0x7d, 0x07, 0x70, 0x03, 0xc8, 0x09, 0xfb, 0xc8, 0xb6, 0xbf, 0x2b, 0xca, 0x40, 0xdd, 0xcc, 0x32, + 0x01, 0x0d, 0x91, 0xc2, 0xc2, 0x5d, 0xc9, 0x8f, 0x30, 0x96, 0x12, 0x87, 0x53, 0x00, 0x09, 0xae, + 0x50, 0x3c, 0x88, 0x61, 0x5b, 0x38, 0xbc, 0x5f, 0x52, 0xc4, 0x86, 0x35, 0x2e, 0x49, 0xbf, 0x78, + 0xc9, 0xd2, 0x65, 0x0f, 0x3f, 0x92, 0x6c, 0x28, 0xda, 0xbc, 0xa5, 0xd8, 0x6a, 0x1b, 0x4b, 0x7e, + 0x6a, 0xf2, 0xb7, 0xa1, 0x87, 0x51, 0x5c, 0xe4, 0x2c, 0x02, 0xc1, 0x2b, 0xda, 0x0e, 0x5d, 0xcb, + 0x41, 0x4a, 0xa1, 0xeb, 0xf0, 0xd0, 0x77, 0x69, 0x28, 0xe5, 0x2d, 0xc2, 0x87, 0x0c, 0x8d, 0x6e, + 0xe5, 0x9c, 0x8a, 0xf9, 0x73, 0xca, 0x1f, 0x1d, 0x45, 0xdf, 0xed, 0x65, 0xb0, 0x33, 0x96, 0x6c, + 0x2b, 0x82, 0x25, 0x7d, 0x57, 0x9f, 0x67, 0xa2, 0x0f, 0xf0, 0x8f, 0xcd, 0x4c, 0x6e, 0x78, 0xfb, + 0x45, 0x4b, 0x98, 0x69, 0xdd, 0x2c, 0x3c, 0x3d, 0xd6, 0x77, 0x29, 0xa4, 0xae, 0x8b, 0x15, 0xa9, + 0x3d, 0x42, 0xad, 0xb1, 0xdc, 0x30, 0x6f, 0x7f, 0x66, 0x3b, 0x6c, 0x5e, 0xcc, 0xe3, 0x59, 0x7c, + 0xee, 0xc8, 0x32, 0x4c, 0x45, 0x4e, 0x3b, 0x75, 0xa0, 0x40, 0xf1, 0x60, 0xd9, 0x61, 0x09, 0x0b, + 0x8b, 0x00, 0x90, 0xef, 0x69, 0xa7, 0x9d, 0x99, 0xbb, 0x1d, 0x76, 0xd4, 0x79, 0x77, 0x99, 0xbc, + 0xb5, 0xa6, 0x1d, 0x4b, 0x75, 0x45, 0xc5, 0xc5, 0xa8, 0x74, 0xcb, 0x75, 0xb3, 0xe6, 0x54, 0xcc, + 0x62, 0xa8, 0xd3, 0xa8, 0x02, 0x87, 0x51, 0xcb, 0x46, 0xa8, 0xd4, 0x5a, 0x5d, 0x6a, 0x25, 0x75, + 0x22, 0xc1, 0x79, 0x5c, 0x08, 0xff, 0xe1, 0x67, 0x11, 0x43, 0xb5, 0x87, 0x89, 0x59, 0xc0, 0x32, + 0x4f, 0x3c, 0xa4, 0x7c, 0x9e, 0x0d, 0x7d, 0x9f, 0x78, 0x68, 0xa4, 0x0e, 0xdb, 0xef, 0xcd, 0x65, + 0x99, 0x3b, 0x10, 0x7f, 0x4f, 0x81, 0x80, 0xc6, 0x04, 0x21, 0xd1, 0x2c, 0xf8, 0xde, 0x0f, 0x75, + 0x37, 0xe1, 0xdb, 0x90, 0xc7, 0x32, 0xdf, 0x9a, 0xf1, 0x6d, 0x2f, 0x96, 0xc9, 0x86, 0xcf, 0x9b, + 0x50, 0xb7, 0x64, 0x23, 0xcb, 0xbc, 0x06, 0x70, 0x27, 0x73, 0x95, 0xfa, 0x18, 0xe8, 0xbb, 0x1a, + 0xdf, 0xae, 0x85, 0xcf, 0x3a, 0xa8, 0x9f, 0x64, 0x51, 0xea, 0xff, 0xa7, 0x4f, 0x02, 0x8c, 0xf5, + 0xd4, 0x7a, 0x96, 0x29, 0x87, 0x4f, 0x25, 0x7c, 0x5e, 0x86, 0xcf, 0x5b, 0xf0, 0xd9, 0x07, 0x1f, + 0x2f, 0x7c, 0x5a, 0xe0, 0xd3, 0x06, 0x9f, 0x00, 0x7c, 0x98, 0xc7, 0x58, 0x46, 0x0b, 0x1f, 0x1d, + 0x7c, 0x92, 0xe0, 0x93, 0x0a, 0x1f, 0x13, 0x7c, 0x9e, 0x82, 0x4f, 0x39, 0x7c, 0x2a, 0xe1, 0xf3, + 0x32, 0x7c, 0xde, 0x82, 0xcf, 0x3e, 0xf8, 0x78, 0xe1, 0xd3, 0x02, 0x9f, 0x36, 0xf8, 0x04, 0xe0, + 0xc3, 0x18, 0xa1, 0x3f, 0x7c, 0x74, 0xf0, 0x49, 0x82, 0x4f, 0x2a, 0x7c, 0x4c, 0xf0, 0x41, 0xbf, + 0x3b, 0x0e, 0x3e, 0xf8, 0xbf, 0x34, 0x59, 0x9d, 0x6d, 0x66, 0xee, 0xed, 0xf8, 0x95, 0xe5, 0xe8, + 0xcf, 0x1b, 0x7a, 0xce, 0xfc, 0xfa, 0xaf, 0xbd, 0xd2, 0xf4, 0xa8, 0xe4, 0x27, 0xbe, 0x8a, 0x6d, + 0x4e, 0x85, 0x48, 0xad, 0xa2, 0xbc, 0x64, 0xbb, 0x50, 0xce, 0xdc, 0x77, 0x8b, 0x61, 0x0a, 0x0b, + 0x85, 0xe2, 0x92, 0x1d, 0xc5, 0x25, 0x4b, 0x98, 0x39, 0x7f, 0xa3, 0xa5, 0x6d, 0x65, 0xc5, 0x58, + 0xfa, 0x7e, 0x2f, 0xc3, 0x80, 0x69, 0x7a, 0x86, 0x3a, 0xe6, 0x85, 0x15, 0xd4, 0xda, 0x56, 0x30, + 0x93, 0xfa, 0x42, 0xb5, 0x5b, 0xa0, 0xda, 0x69, 0x2d, 0x2c, 0xd9, 0x5e, 0x6c, 0xdd, 0xc5, 0xcc, + 0xfe, 0x96, 0x61, 0xe8, 0xc6, 0xcf, 0x34, 0x0d, 0xc1, 0xe0, 0xb8, 0x0d, 0x2c, 0x29, 0x44, 0x47, + 0x8a, 0x39, 0x00, 0x41, 0x01, 0xf5, 0x0c, 0x0b, 0x61, 0xe3, 0x2d, 0x84, 0x6d, 0xc3, 0xba, 0x95, + 0x69, 0x1d, 0xae, 0x43, 0x10, 0x90, 0x41, 0x10, 0xc1, 0x5d, 0x4e, 0xa6, 0x30, 0x82, 0x0d, 0x55, + 0xa3, 0xd9, 0x63, 0xd6, 0xab, 0x46, 0x17, 0x01, 0x94, 0xb9, 0xa6, 0x66, 0x43, 0xd6, 0x23, 0xe4, + 0x64, 0x16, 0x52, 0x27, 0x93, 0xc1, 0x1f, 0x74, 0x55, 0x20, 0xa9, 0x6d, 0xc0, 0x1f, 0x76, 0x55, + 0x8a, 0x5b, 0xd0, 0x13, 0x60, 0x52, 0xa0, 0x4c, 0xd7, 0x30, 0xb6, 0xd7, 0xc6, 0x09, 0x77, 0x55, + 0xdb, 0x1c, 0x65, 0xdb, 0x0a, 0xc1, 0x85, 0x61, 0xde, 0xd6, 0xc0, 0x00, 0x15, 0xa3, 0x10, 0xfe, + 0xf5, 0x48, 0xc5, 0xd3, 0x42, 0x49, 0x31, 0xf3, 0x11, 0x96, 0x29, 0x92, 0x79, 0x13, 0xe1, 0x49, + 0x99, 0xe6, 0x6d, 0x7c, 0xa4, 0x08, 0xb0, 0x93, 0x42, 0x4f, 0xa0, 0x54, 0x4c, 0xfc, 0xa8, 0x42, + 0xe1, 0x36, 0xf4, 0xc9, 0x0f, 0x70, 0x6c, 0x58, 0x91, 0x94, 0x95, 0x66, 0x4c, 0x19, 0xa9, 0xd8, + 0x8e, 0xfa, 0xa9, 0x90, 0xf2, 0x8f, 0xa3, 0xaa, 0xe9, 0xb8, 0xf8, 0x1b, 0x2e, 0xe1, 0x0a, 0x65, + 0x4e, 0x1b, 0xad, 0x01, 0xf3, 0x00, 0xfe, 0xf7, 0x4e, 0x78, 0x76, 0x96, 0x09, 0xe5, 0xe5, 0x56, + 0x07, 0x23, 0xc1, 0x73, 0xd1, 0xe6, 0x0a, 0xe6, 0xa7, 0xf0, 0x0d, 0xee, 0xc8, 0x96, 0xf2, 0xdd, + 0xcc, 0xa7, 0xa1, 0xc7, 0x6d, 0xe5, 0x4c, 0x4f, 0xe8, 0xb1, 0x08, 0x98, 0x0a, 0xc5, 0x9d, 0xf1, + 0xb4, 0xb8, 0x1d, 0x9f, 0x0f, 0x84, 0x9f, 0x43, 0x6d, 0x73, 0x13, 0x68, 0x19, 0xf4, 0x99, 0x49, + 0x81, 0x47, 0xd8, 0x15, 0x9c, 0x85, 0x60, 0x78, 0xb6, 0x33, 0xfb, 0xa0, 0x04, 0x66, 0x04, 0x47, + 0x3e, 0xaf, 0x3c, 0x56, 0x58, 0x9d, 0xcc, 0x37, 0xca, 0xe3, 0x36, 0xb0, 0x1e, 0xcc, 0x92, 0xfb, + 0x14, 0x08, 0x18, 0xc5, 0x06, 0x8f, 0x60, 0x31, 0x0b, 0x9d, 0x65, 0x85, 0x88, 0xe9, 0x8f, 0xa1, + 0x58, 0x5c, 0xf2, 0x34, 0xb0, 0x3e, 0x54, 0x71, 0xe0, 0x3e, 0x3a, 0x0b, 0x60, 0x5f, 0xc2, 0x7c, + 0x3a, 0x8d, 0x65, 0x90, 0xd0, 0x80, 0x3e, 0x58, 0x3b, 0x90, 0xb0, 0x72, 0x30, 0x35, 0x8c, 0xed, + 0x7e, 0xd0, 0x8b, 0xa2, 0xed, 0x25, 0x5b, 0x18, 0xc3, 0x74, 0x96, 0x19, 0x15, 0x31, 0x32, 0x3d, + 0x3a, 0x80, 0x2f, 0x77, 0x8e, 0x30, 0xa7, 0x76, 0x26, 0xd2, 0xa4, 0x90, 0x1a, 0x9b, 0xc2, 0x6d, + 0x9b, 0x1d, 0xcc, 0xa3, 0x0f, 0x00, 0x22, 0x9b, 0x1d, 0x14, 0x02, 0xda, 0x5f, 0x78, 0x00, 0x87, + 0x72, 0xd0, 0x1e, 0xcc, 0xb8, 0xef, 0x0f, 0x8f, 0x86, 0xcd, 0x9b, 0x77, 0x2b, 0x63, 0x3c, 0xfb, + 0x9d, 0x6a, 0x5b, 0x85, 0x22, 0x0a, 0xcd, 0xdf, 0x69, 0xd9, 0x52, 0x56, 0xe6, 0x28, 0x66, 0x62, + 0xe6, 0xdf, 0x5d, 0x8f, 0xbb, 0x67, 0xa1, 0xe2, 0xd2, 0x2e, 0x83, 0x46, 0x85, 0x49, 0xd9, 0x08, + 0xa6, 0x3c, 0xfe, 0x79, 0x11, 0x56, 0x6e, 0x2f, 0x84, 0x85, 0x33, 0x2b, 0x93, 0x94, 0xe7, 0x12, + 0xa6, 0x27, 0xf4, 0x04, 0x94, 0xf8, 0x89, 0x5e, 0x79, 0xdc, 0xc5, 0x0c, 0xe9, 0x43, 0xfd, 0x01, + 0x38, 0xec, 0x9b, 0x32, 0x6f, 0x2d, 0x06, 0x6d, 0x80, 0x7d, 0x6f, 0xc4, 0x9a, 0x33, 0x1f, 0x2f, + 0x51, 0xc8, 0x5f, 0x54, 0x1e, 0x32, 0xef, 0xd4, 0x65, 0x64, 0xba, 0xa0, 0x1a, 0xe2, 0xe9, 0xc2, + 0x8a, 0x22, 0x0c, 0x6d, 0x2a, 0xac, 0x85, 0xa1, 0xf0, 0x8e, 0x59, 0x9a, 0xac, 0xd0, 0x5a, 0xe9, + 0xc3, 0x58, 0x93, 0x91, 0xc3, 0x25, 0xc3, 0xe5, 0x5f, 0x2f, 0x57, 0x9a, 0x1d, 0x45, 0x3b, 0xc3, + 0x55, 0xc7, 0x96, 0x2b, 0x43, 0x81, 0x44, 0x5b, 0x0b, 0x71, 0xa3, 0x28, 0x74, 0x32, 0x17, 0x46, + 0xd5, 0x31, 0xcb, 0x57, 0x28, 0x05, 0xe0, 0x0d, 0x45, 0xe9, 0xb7, 0x50, 0x1e, 0xb3, 0xe5, 0x30, + 0xcd, 0x77, 0xd7, 0x84, 0xc7, 0xf9, 0xf3, 0x77, 0x1a, 0x42, 0xbb, 0x13, 0xb3, 0x6e, 0xe5, 0xdd, + 0x2d, 0xce, 0xdd, 0xe5, 0xd6, 0x42, 0x1a, 0x62, 0x43, 0xb3, 0xf5, 0x9f, 0x36, 0x2b, 0x4a, 0xb7, + 0xfc, 0x51, 0x20, 0x0d, 0x12, 0x86, 0x4a, 0x01, 0xfa, 0xfc, 0x79, 0xab, 0x14, 0x4c, 0xa9, 0xcf, + 0x46, 0x7b, 0x30, 0x47, 0x56, 0xfd, 0x3d, 0xfa, 0xa1, 0xe9, 0xe9, 0x4d, 0x55, 0x80, 0xb7, 0x5b, + 0x77, 0x86, 0xb4, 0x53, 0x9d, 0xc1, 0x62, 0xf0, 0x08, 0x6c, 0xde, 0x5e, 0x5c, 0xa8, 0x70, 0x9e, + 0xb9, 0x3f, 0x54, 0x47, 0x2d, 0xdf, 0x17, 0x50, 0xc0, 0x9d, 0x4f, 0xd1, 0xf1, 0x67, 0xd7, 0x80, + 0x46, 0x2e, 0x4e, 0x52, 0x66, 0x63, 0x1a, 0x42, 0x25, 0x25, 0xa8, 0x66, 0xd4, 0xeb, 0xd0, 0xb0, + 0x6d, 0x2d, 0xd9, 0xec, 0x40, 0x93, 0xea, 0xac, 0xd8, 0xc2, 0x94, 0xac, 0x0b, 0xb1, 0xc2, 0x0a, + 0xe1, 0x38, 0x33, 0xb0, 0x0e, 0x17, 0x88, 0x87, 0x07, 0xcc, 0x83, 0xeb, 0x43, 0x0d, 0x25, 0xc5, + 0x4e, 0x06, 0x13, 0x27, 0x94, 0xff, 0x87, 0x15, 0x1b, 0xfe, 0x9f, 0x59, 0x69, 0xef, 0xfa, 0x7f, + 0x5b, 0x61, 0xfb, 0xcf, 0x42, 0xdf, 0xaf, 0x86, 0xcb, 0x67, 0x42, 0xe5, 0x33, 0x0a, 0xd0, 0xcf, + 0x74, 0xca, 0xf7, 0xab, 0xa1, 0x4e, 0x64, 0xe4, 0xff, 0x9a, 0xf6, 0xff, 0x00, 0x4a, 0x3d, 0xe6, + 0x68, 0x30, 0x6f, 0x00, 0x00, +}; diff --git a/limine/limine-bios-pxe.bin b/limine/limine-bios-pxe.bin new file mode 100644 index 0000000..e463d64 Binary files /dev/null and b/limine/limine-bios-pxe.bin differ diff --git a/limine/limine-bios.sys b/limine/limine-bios.sys new file mode 100644 index 0000000..ef5574d Binary files /dev/null and b/limine/limine-bios.sys differ diff --git a/limine/limine-uefi-cd.bin b/limine/limine-uefi-cd.bin new file mode 100644 index 0000000..77c49f5 Binary files /dev/null and b/limine/limine-uefi-cd.bin differ diff --git a/limine/limine.c b/limine/limine.c new file mode 100644 index 0000000..9995063 --- /dev/null +++ b/limine/limine.c @@ -0,0 +1,1448 @@ +#undef IS_WINDOWS +#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32)) && !defined(__CYGWIN__) +#define IS_WINDOWS 1 +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef LIMINE_NO_BIOS +#include "limine-bios-hdd.h" +#endif + +static char *program_name = NULL; + +static void perror_wrap(const char *fmt, ...) { + int old_errno = errno; + + fprintf(stderr, "%s: ", program_name); + + va_list args; + va_start(args, fmt); + + vfprintf(stderr, fmt, args); + + va_end(args); + + fprintf(stderr, ": %s\n", strerror(old_errno)); +} + +static void remove_arg(int *argc, char *argv[], int index) { + for (int i = index; i < *argc - 1; i++) { + argv[i] = argv[i + 1]; + } + + (*argc)--; + + argv[*argc] = NULL; +} + +static inline bool mul_u64_overflow(uint64_t a, uint64_t b, uint64_t *res) { + *res = a * b; + return a != 0 && b > UINT64_MAX / a; +} + +static inline bool add_u64_overflow(uint64_t a, uint64_t b, uint64_t *res) { + *res = a + b; + return a > UINT64_MAX - b; +} + +#ifndef LIMINE_NO_BIOS + +static bool quiet = false; + +static int set_pos(FILE *stream, uint64_t pos) { + if (sizeof(long) >= 8) { + return fseek(stream, (long)pos, SEEK_SET); + } + + long jump_size = (LONG_MAX / 2) + 1; + long last_jump = pos % jump_size; + uint64_t jumps = pos / jump_size; + + rewind(stream); + + for (uint64_t i = 0; i < jumps; i++) { + if (fseek(stream, jump_size, SEEK_CUR) != 0) { + return -1; + } + } + if (fseek(stream, last_jump, SEEK_CUR) != 0) { + return -1; + } + + return 0; +} + +#define SIZEOF_ARRAY(array) (sizeof(array) / sizeof(array[0])) +#define DIV_ROUNDUP(a, b) (((a) + ((b) - 1)) / (b)) + +struct gpt_table_header { + // the head + char signature[8]; + uint32_t revision; + uint32_t header_size; + uint32_t crc32; + uint32_t _reserved0; + + // the partitioning info + uint64_t my_lba; + uint64_t alternate_lba; + uint64_t first_usable_lba; + uint64_t last_usable_lba; + + // the guid + uint64_t disk_guid[2]; + + // entries related + uint64_t partition_entry_lba; + uint32_t number_of_partition_entries; + uint32_t size_of_partition_entry; + uint32_t partition_entry_array_crc32; +}; + +struct gpt_entry { + uint64_t partition_type_guid[2]; + + uint64_t unique_partition_guid[2]; + + uint64_t starting_lba; + uint64_t ending_lba; + + uint64_t attributes; + + uint16_t partition_name[36]; +}; + +struct gpt2mbr_type_conv { + uint64_t gpt_type1; + uint64_t gpt_type2; + uint8_t mbr_type; +}; + +// This table is very incomplete, but it should be enough for covering +// all that matters for ISOHYBRIDs. +// Of course, though, expansion is welcome. +static struct gpt2mbr_type_conv gpt2mbr_type_conv_table[] = { + { 0x11d2f81fc12a7328, 0x3bc93ec9a0004bba, 0xef }, // EFI system partition + { 0x4433b9e5ebd0a0a2, 0xc79926b7b668c087, 0x07 }, // Microsoft basic data + { 0x11aa000048465300, 0xacec4365300011aa, 0xaf }, // HFS/HFS+ +}; + +static int gpt2mbr_type(uint64_t gpt_type1, uint64_t gpt_type2) { + for (size_t i = 0; i < SIZEOF_ARRAY(gpt2mbr_type_conv_table); i++) { + if (gpt2mbr_type_conv_table[i].gpt_type1 == gpt_type1 + && gpt2mbr_type_conv_table[i].gpt_type2 == gpt_type2) { + return gpt2mbr_type_conv_table[i].mbr_type; + } + } + return -1; +} + +static void lba2chs(uint8_t *chs, uint64_t lba) { + // If LBA is too big to express, use a standard value for CHS. + if (lba > 63 * 255 * 1024) { + goto lba_too_big; + } + + uint64_t cylinder = lba / (255 * 63); + if (cylinder >= 1024) { +lba_too_big: + chs[0] = 0xfe; + chs[1] = 0xff; + chs[2] = 0xff; + return; + } + uint64_t head = (lba / 63) % 255; + uint64_t sector = (lba % 63) + 1; + + chs[0] = head; + chs[1] = (cylinder >> 2) & 0xc0; // high 2 bits + chs[1] |= sector & 0x3f; + chs[2] = cylinder; // low 8 bits +} + +static uint16_t endswap16(uint16_t value) { + uint16_t ret = 0; + ret |= (value >> 8) & 0x00ff; + ret |= (value << 8) & 0xff00; + return ret; +} + +static uint32_t endswap32(uint32_t value) { + uint32_t ret = 0; + ret |= (value >> 24) & 0x000000ff; + ret |= (value >> 8) & 0x0000ff00; + ret |= (value << 8) & 0x00ff0000; + ret |= (value << 24) & 0xff000000; + return ret; +} + +static uint64_t endswap64(uint64_t value) { + uint64_t ret = 0; + ret |= (value >> 56) & 0x00000000000000ff; + ret |= (value >> 40) & 0x000000000000ff00; + ret |= (value >> 24) & 0x0000000000ff0000; + ret |= (value >> 8) & 0x00000000ff000000; + ret |= (value << 8) & 0x000000ff00000000; + ret |= (value << 24) & 0x0000ff0000000000; + ret |= (value << 40) & 0x00ff000000000000; + ret |= (value << 56) & 0xff00000000000000; + return ret; +} + +#ifdef __BYTE_ORDER__ + +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +#define bigendian true +#else +#define bigendian false +#endif + +#else /* !__BYTE_ORDER__ */ + +static bool bigendian = false; + +#endif /* !__BYTE_ORDER__ */ + +#define ENDSWAP(VALUE) (bigendian ? ( \ + sizeof(VALUE) == 1 ? (VALUE) : \ + sizeof(VALUE) == 2 ? endswap16(VALUE) : \ + sizeof(VALUE) == 4 ? endswap32(VALUE) : \ + sizeof(VALUE) == 8 ? endswap64(VALUE) : (abort(), 1) \ +) : (VALUE)) + +static enum { + CACHE_CLEAN, + CACHE_DIRTY +} cache_state; +static uint64_t cached_block; +static uint8_t *cache = NULL; +static FILE *device = NULL; +static size_t block_size; + +static bool device_init(void) { + size_t guesses[] = { 512, 2048, 4096 }; + + for (size_t i = 0; i < SIZEOF_ARRAY(guesses); i++) { + void *tmp = realloc(cache, guesses[i]); + if (tmp == NULL) { + perror_wrap("error: device_init(): realloc()"); + return false; + } + cache = tmp; + + rewind(device); + + size_t ret = fread(cache, guesses[i], 1, device); + if (ret != 1) { + continue; + } + + block_size = guesses[i]; + + if (!quiet) { + fprintf(stderr, "Physical block size of %zu bytes.\n", block_size); + } + + cache_state = CACHE_CLEAN; + cached_block = 0; + return true; + } + + fprintf(stderr, "error: device_init(): Couldn't determine block size of device.\n"); + return false; +} + +static bool device_flush_cache(void) { + if (cache_state == CACHE_CLEAN) + return true; + + if (set_pos(device, cached_block * block_size) != 0) { + perror_wrap("error: device_flush_cache(): set_pos()"); + return false; + } + + size_t ret = fwrite(cache, block_size, 1, device); + if (ret != 1) { + if (ferror(device)) { + perror_wrap("error: device_flush_cache(): fwrite()"); + } + return false; + } + + cache_state = CACHE_CLEAN; + return true; +} + +static bool device_cache_block(uint64_t block) { + if (cached_block == block) + return true; + + if (cache_state == CACHE_DIRTY) { + if (!device_flush_cache()) + return false; + } + + if (set_pos(device, block * block_size) != 0) { + perror_wrap("error: device_cache_block(): set_pos()"); + return false; + } + + size_t ret = fread(cache, block_size, 1, device); + if (ret != 1) { + if (ferror(device)) { + perror_wrap("error: device_cache_block(): fread()"); + } + return false; + } + + cached_block = block; + + return true; +} + +struct uninstall_data { + void *data; + uint64_t loc; + uint64_t count; +}; + +#define UNINSTALL_DATA_MAX 256 + +static bool uninstalling = false; +static struct uninstall_data uninstall_data[UNINSTALL_DATA_MAX]; +static struct uninstall_data uninstall_data_rev[UNINSTALL_DATA_MAX]; +static uint64_t uninstall_data_i = 0; +static const char *uninstall_file = NULL; + +static void reverse_uninstall_data(void) { + for (size_t i = 0, j = uninstall_data_i - 1; i < uninstall_data_i; i++, j--) { + uninstall_data_rev[j] = uninstall_data[i]; + } + + memcpy(uninstall_data, uninstall_data_rev, uninstall_data_i * sizeof(struct uninstall_data)); +} + +static void free_uninstall_data(void) { + for (size_t i = 0; i < uninstall_data_i; i++) { + free(uninstall_data[i].data); + } +} + +static bool store_uninstall_data(const char *filename) { + if (!quiet) { + fprintf(stderr, "Storing uninstall data to file: `%s`...\n", filename); + } + + FILE *udfile = fopen(filename, "wb"); + if (udfile == NULL) { + perror_wrap("error: `%s`", filename); + goto error; + } + + if (fwrite(&uninstall_data_i, sizeof(uint64_t), 1, udfile) != 1) { + goto fwrite_error; + } + + for (size_t i = 0; i < uninstall_data_i; i++) { + if (fwrite(&uninstall_data[i].loc, sizeof(uint64_t), 1, udfile) != 1) { + goto fwrite_error; + } + if (fwrite(&uninstall_data[i].count, sizeof(uint64_t), 1, udfile) != 1) { + goto fwrite_error; + } + if (fwrite(uninstall_data[i].data, uninstall_data[i].count, 1, udfile) != 1) { + goto fwrite_error; + } + } + + fclose(udfile); + return true; + +fwrite_error: + perror_wrap("error: store_uninstall_data(): fwrite()"); + +error: + if (udfile != NULL) { + fclose(udfile); + } + return false; +} + +static bool load_uninstall_data(const char *filename) { + size_t loaded_count = 0; + + if (!quiet) { + fprintf(stderr, "Loading uninstall data from file: `%s`...\n", filename); + } + + FILE *udfile = fopen(filename, "rb"); + if (udfile == NULL) { + perror_wrap("error: `%s`", filename); + goto error; + } + + if (fread(&uninstall_data_i, sizeof(uint64_t), 1, udfile) != 1) { + goto fread_error; + } + + if (uninstall_data_i > UNINSTALL_DATA_MAX) { + fprintf(stderr, "error: load_uninstall_data(): too many entries (%zu > %d)\n", + (size_t)uninstall_data_i, UNINSTALL_DATA_MAX); + goto error; + } + + for (size_t i = 0; i < uninstall_data_i; i++) { + if (fread(&uninstall_data[i].loc, sizeof(uint64_t), 1, udfile) != 1) { + goto fread_error; + } + if (fread(&uninstall_data[i].count, sizeof(uint64_t), 1, udfile) != 1) { + goto fread_error; + } + if (uninstall_data[i].count > SIZE_MAX) { + fprintf(stderr, "error: load_uninstall_data(): entry size too large\n"); + goto error; + } + uninstall_data[i].data = malloc((size_t)uninstall_data[i].count); + if (uninstall_data[i].data == NULL) { + perror_wrap("error: load_uninstall_data(): malloc()"); + goto error; + } + if (fread(uninstall_data[i].data, uninstall_data[i].count, 1, udfile) != 1) { + free(uninstall_data[i].data); + goto fread_error; + } + loaded_count++; + } + + fclose(udfile); + return true; + +fread_error: + perror_wrap("error: load_uninstall_data(): fread()"); + +error: + // Free any previously allocated uninstall data + for (size_t j = 0; j < loaded_count; j++) { + free(uninstall_data[j].data); + } + if (udfile != NULL) { + fclose(udfile); + } + return false; +} + +static bool _device_read(void *_buffer, uint64_t loc, size_t count) { + uint8_t *buffer = _buffer; + uint64_t progress = 0; + while (progress < count) { + uint64_t block = (loc + progress) / block_size; + + if (!device_cache_block(block)) { + return false; + } + + uint64_t chunk = count - progress; + uint64_t offset = (loc + progress) % block_size; + if (chunk > block_size - offset) + chunk = block_size - offset; + + memcpy(buffer + progress, &cache[offset], chunk); + progress += chunk; + } + + return true; +} + +static bool _device_write(const void *_buffer, uint64_t loc, size_t count) { + struct uninstall_data *ud = NULL; + + if (uninstalling) { + goto skip_save; + } + + if (uninstall_data_i >= UNINSTALL_DATA_MAX) { + fprintf(stderr, "error: Too many uninstall data entries! Please report this bug upstream.\n"); + return false; + } + + ud = &uninstall_data[uninstall_data_i]; + + ud->data = malloc(count); + if (ud->data == NULL) { + perror_wrap("error: _device_write(): malloc()"); + return false; + } + + if (!_device_read(ud->data, loc, count)) { + free(ud->data); + return false; + } + + ud->loc = loc; + ud->count = count; + +skip_save:; + const uint8_t *buffer = _buffer; + uint64_t progress = 0; + while (progress < count) { + uint64_t block = (loc + progress) / block_size; + + if (!device_cache_block(block)) { + if (!uninstalling) { + free(ud->data); + } + return false; + } + + uint64_t chunk = count - progress; + uint64_t offset = (loc + progress) % block_size; + if (chunk > block_size - offset) + chunk = block_size - offset; + + memcpy(&cache[offset], buffer + progress, chunk); + cache_state = CACHE_DIRTY; + progress += chunk; + } + + if (!uninstalling) { + uninstall_data_i++; + } + return true; +} + +static bool uninstall(bool quiet_arg) { + bool print_cache_flush_fail = false; + bool print_write_fail = false; + bool ret = true; + + uninstalling = true; + + cache_state = CACHE_CLEAN; + cached_block = (uint64_t)-1; + + for (size_t i = 0; i < uninstall_data_i; i++) { + struct uninstall_data *ud = &uninstall_data[i]; + bool retry = false; + while (!_device_write(ud->data, ud->loc, ud->count)) { + if (retry) { + fprintf(stderr, "warning: Retry failed.\n"); + print_write_fail = true; + break; + } + if (!quiet) { + fprintf(stderr, "warning: Uninstall data index %zu failed to write, retrying...\n", i); + } + if (!device_flush_cache()) { + print_cache_flush_fail = true; + } + cache_state = CACHE_CLEAN; + cached_block = (uint64_t)-1; + retry = true; + } + } + + if (!device_flush_cache()) { + print_cache_flush_fail = true; + } + + if (print_write_fail) { + fprintf(stderr, "error: Some data failed to be uninstalled correctly.\n"); + ret = false; + } + + if (print_cache_flush_fail) { + fprintf(stderr, "error: Device cache flush failure. Uninstall may be incomplete.\n"); + ret = false; + } + + if (ret == true && !quiet && !quiet_arg) { + fprintf(stderr, "Uninstall data restored successfully.\n"); + } + + return ret; +} + +#define device_read(BUFFER, LOC, COUNT) \ + do { \ + if (!_device_read(BUFFER, LOC, COUNT)) \ + goto cleanup; \ + } while (0) + +#define device_write(BUFFER, LOC, COUNT) \ + do { \ + if (!_device_write(BUFFER, LOC, COUNT)) \ + goto cleanup; \ + } while (0) + +static void bios_install_usage(void) { + printf("usage: %s bios-install [GPT partition index]\n", program_name); + printf("\n"); + printf(" --force Force installation even if the safety checks fail\n"); + printf(" (DANGEROUS!)\n"); + printf("\n"); + printf(" --uninstall Reverse the entire install procedure\n"); + printf("\n"); + printf(" --uninstall-data-file=\n"); + printf(" Set the input (for --uninstall) or output file\n"); + printf(" name of the file which contains uninstall data\n"); + printf("\n"); + printf(" --no-gpt-to-mbr-isohybrid-conversion\n"); + printf(" Do not automatically convert a GUID partition table (GPT)\n"); + printf(" found on an ISOHYBRID image into an MBR partition table\n"); + printf(" (which is done for better hardware compatibility)\n"); + printf("\n"); + printf(" --quiet Do not print verbose diagnostic messages\n"); + printf("\n"); + printf(" --help | -h Display this help message\n"); + printf("\n"); +} + +static bool validate_or_force(uint64_t offset, bool force, bool *err) { + *err = false; + + char hintc[64]; + device_read(hintc, offset + 3, 4); + if (memcmp(hintc, "NTFS", 4) == 0) { + if (!force) { + return false; + } else { + memset(hintc, 0, 4); + device_write(hintc, offset + 3, 4); + } + } + device_read(hintc, offset + 54, 3); + if (memcmp(hintc, "FAT", 3) == 0) { + if (!force) { + return false; + } else { + memset(hintc, 0, 5); + device_write(hintc, offset + 54, 5); + } + } + device_read(hintc, offset + 82, 3); + if (memcmp(hintc, "FAT", 3) == 0) { + if (!force) { + return false; + } else { + memset(hintc, 0, 5); + device_write(hintc, offset + 82, 5); + } + } + device_read(hintc, offset + 3, 5); + if (memcmp(hintc, "FAT32", 5) == 0) { + if (!force) { + return false; + } else { + memset(hintc, 0, 5); + device_write(hintc, offset + 3, 5); + } + } + uint16_t hint16 = 0; + device_read(&hint16, offset + 1080, sizeof(uint16_t)); + hint16 = ENDSWAP(hint16); + if (hint16 == 0xef53) { + if (!force) { + return false; + } else { + hint16 = 0; + hint16 = ENDSWAP(hint16); + device_write(&hint16, offset + 1080, sizeof(uint16_t)); + } + } + + return true; + +cleanup: + *err = true; + return false; +} + +static int bios_install(int argc, char *argv[]) { + int ok = EXIT_FAILURE; + bool force = false; + bool gpt2mbr_allowed = true; + bool uninstall_mode = false; + const uint8_t *bootloader_img = binary_limine_hdd_bin_data; + size_t bootloader_file_size = sizeof(binary_limine_hdd_bin_data); + uint8_t orig_mbr[70], timestamp[6]; + const char *part_ndx = NULL; + +#ifndef __BYTE_ORDER__ + uint32_t endcheck = 0x12345678; + uint8_t endbyte = *((uint8_t *)&endcheck); + bigendian = endbyte == 0x12; +#endif + + if (argc < 2) { + bios_install_usage(); +#ifdef IS_WINDOWS + system("pause"); +#endif + return EXIT_FAILURE; + } + + for (int i = 1; i < argc; i++) { + if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-h") == 0) { + bios_install_usage(); + return EXIT_SUCCESS; + } else if (strcmp(argv[i], "--quiet") == 0) { + quiet = true; + } else if (strcmp(argv[i], "--force") == 0) { + if (force && !quiet) { + fprintf(stderr, "warning: --force already set.\n"); + } + force = true; + } else if (strcmp(argv[i], "--no-gpt-to-mbr-isohybrid-conversion") == 0) { + gpt2mbr_allowed = false; + } else if (strcmp(argv[i], "--uninstall") == 0) { + if (uninstall_mode && !quiet) { + fprintf(stderr, "warning: --uninstall already set.\n"); + } + uninstall_mode = true; + } else if (memcmp(argv[i], "--uninstall-data-file=", 22) == 0) { + if (uninstall_file != NULL && !quiet) { + fprintf(stderr, "warning: --uninstall-data-file already set. Overriding...\n"); + } + uninstall_file = argv[i] + 22; + if (strlen(uninstall_file) == 0) { + fprintf(stderr, "error: Uninstall data file has a zero-length name!\n"); + return EXIT_FAILURE; + } + } else { + if (device != NULL) { // [GPT partition index] + part_ndx = argv[i]; // TODO: Make this non-positional? + } else if ((device = fopen(argv[i], "r+b")) == NULL) { // + perror_wrap("error: `%s`", argv[i]); + return EXIT_FAILURE; + } + } + } + + if (device == NULL) { + fprintf(stderr, "error: No device specified\n"); + bios_install_usage(); + return EXIT_FAILURE; + } + + if (!device_init()) { + goto uninstall_mode_cleanup; + } + + if (uninstall_mode) { + if (uninstall_file == NULL) { + fprintf(stderr, "error: Uninstall mode set but no --uninstall-data-file=... passed.\n"); + goto uninstall_mode_cleanup; + } + + if (!load_uninstall_data(uninstall_file)) { + goto uninstall_mode_cleanup; + } + + if (uninstall(false) == false) { + ok = EXIT_FAILURE; + } else { + ok = EXIT_SUCCESS; + } + goto uninstall_mode_cleanup; + } + + // Probe for GPT and logical block size + int gpt = 0; + struct gpt_table_header gpt_header; + uint64_t lb_guesses[] = { 512, 4096 }; + uint64_t lb_size = 0; + for (size_t i = 0; i < SIZEOF_ARRAY(lb_guesses); i++) { + device_read(&gpt_header, lb_guesses[i], sizeof(struct gpt_table_header)); + if (!strncmp(gpt_header.signature, "EFI PART", 8)) { + lb_size = lb_guesses[i]; + gpt = 1; + if (!quiet) { + fprintf(stderr, "Installing to GPT. Logical block size of %" PRIu64 " bytes.\n", + lb_guesses[i]); + } + break; + } + } + + struct gpt_table_header secondary_gpt_header; + if (gpt) { + if (!quiet) { + fprintf(stderr, "Secondary header at LBA 0x%" PRIx64 ".\n", + ENDSWAP(gpt_header.alternate_lba)); + } + device_read(&secondary_gpt_header, lb_size * ENDSWAP(gpt_header.alternate_lba), + sizeof(struct gpt_table_header)); + if (!strncmp(secondary_gpt_header.signature, "EFI PART", 8)) { + if (!quiet) { + fprintf(stderr, "Secondary header valid.\n"); + } + } else { + fprintf(stderr, "error: Secondary header not valid, aborting.\n"); + goto cleanup; + } + } + + // Check if this is an ISO w/ a GPT, in which case try converting it + // to MBR for improved compatibility with a whole range of hardware that + // does not like booting off of GPT in BIOS or CSM mode, and other + // broken hardware. + if (gpt && gpt2mbr_allowed == true) { + char iso_signature[5]; + device_read(iso_signature, 32769, 5); + + if (strncmp(iso_signature, "CD001", 5) != 0) { + goto no_mbr_conv; + } + + if (!quiet) { + fprintf(stderr, "Detected ISOHYBRID with a GUID partition table (GPT).\n"); + fprintf(stderr, "Converting to MBR for improved compatibility...\n"); + } + + // Gather the (up to 4) GPT partition to convert. + struct { + uint64_t lba_start; + uint64_t lba_end; + uint8_t chs_start[3]; + uint8_t chs_end[3]; + uint8_t type; + } part_to_conv[4]; + size_t part_to_conv_i = 0; + + uint64_t part_entry_base; + if (mul_u64_overflow(ENDSWAP(gpt_header.partition_entry_lba), lb_size, &part_entry_base)) { + goto no_mbr_conv; + } + + for (int64_t i = 0; i < (int64_t)ENDSWAP(gpt_header.number_of_partition_entries); i++) { + struct gpt_entry gpt_entry; + uint64_t entry_offset = (uint64_t)i * ENDSWAP(gpt_header.size_of_partition_entry); + if (add_u64_overflow(part_entry_base, entry_offset, &entry_offset)) { + goto no_mbr_conv; + } + device_read(&gpt_entry, entry_offset, sizeof(struct gpt_entry)); + + if (gpt_entry.unique_partition_guid[0] == 0 && + gpt_entry.unique_partition_guid[1] == 0) { + continue; + } + + if (part_to_conv_i == 4) { + if (!quiet) { + fprintf(stderr, "GPT contains more than 4 partitions, will not convert.\n"); + } + goto no_mbr_conv; + } + + if (ENDSWAP(gpt_entry.starting_lba) > UINT32_MAX) { + if (!quiet) { + fprintf(stderr, "Starting LBA of partition %" PRIi64 " is greater than UINT32_MAX, will not convert GPT.\n", i + 1); + } + goto no_mbr_conv; + } + part_to_conv[part_to_conv_i].lba_start = ENDSWAP(gpt_entry.starting_lba); + lba2chs(part_to_conv[part_to_conv_i].chs_start, part_to_conv[part_to_conv_i].lba_start); + + if (ENDSWAP(gpt_entry.ending_lba) > UINT32_MAX) { + if (!quiet) { + fprintf(stderr, "Ending LBA of partition %" PRIi64 " is greater than UINT32_MAX, will not convert GPT.\n", i + 1); + } + goto no_mbr_conv; + } + part_to_conv[part_to_conv_i].lba_end = ENDSWAP(gpt_entry.ending_lba); + lba2chs(part_to_conv[part_to_conv_i].chs_end, part_to_conv[part_to_conv_i].lba_end); + + if (part_to_conv[part_to_conv_i].lba_end - part_to_conv[part_to_conv_i].lba_start + 1 > UINT32_MAX) { + if (!quiet) { + fprintf(stderr, "Sector count of partition %" PRIi64 " is greater than UINT32_MAX, will not convert GPT.\n", i + 1); + } + goto no_mbr_conv; + } + + int type = gpt2mbr_type(ENDSWAP(gpt_entry.partition_type_guid[0]), + ENDSWAP(gpt_entry.partition_type_guid[1])); + if (type == -1) { + if (!quiet) { + fprintf(stderr, "Cannot convert partition type for partition %" PRIi64 ", will not convert GPT.\n", i + 1); + } + goto no_mbr_conv; + } + + part_to_conv[part_to_conv_i].type = type; + + part_to_conv_i++; + } + + // Nuke the GPTs. + void *empty_lba = calloc(1, lb_size); + if (empty_lba == NULL) { + perror_wrap("error: bios_install(): malloc()"); + goto cleanup; + } + + // ... nuke primary GPT + protective MBR. + for (size_t i = 0; i < 34; i++) { + device_write(empty_lba, i * lb_size, lb_size); + } + + // ... nuke secondary GPT. + uint64_t alt_lba = ENDSWAP(gpt_header.alternate_lba); + if (alt_lba >= 32) { + for (size_t i = 0; i < 33; i++) { + device_write(empty_lba, (alt_lba - 32 + i) * lb_size, lb_size); + } + } + + free(empty_lba); + + // We're no longer GPT. + gpt = 0; + + // Generate pseudorandom MBR disk ID. + srand(time(NULL)); + for (size_t i = 0; i < 4; i++) { + uint8_t r = rand(); + device_write(&r, 0x1b8 + i, 1); + } + + // Write out the partition entries. + for (size_t i = 0; i < part_to_conv_i; i++) { + device_write(&part_to_conv[i].type, 0x1be + i * 16 + 0x04, 1); + uint32_t lba_start = ENDSWAP((uint32_t)part_to_conv[i].lba_start); + device_write(&lba_start, 0x1be + i * 16 + 0x08, 4); + uint32_t sect_count = ENDSWAP((uint32_t)((part_to_conv[i].lba_end - part_to_conv[i].lba_start) + 1)); + device_write(§_count, 0x1be + i * 16 + 0x0c, 4); + + device_write(part_to_conv[i].chs_start, 0x1be + i * 16 + 1, 3); + device_write(part_to_conv[i].chs_end, 0x1be + i * 16 + 5, 3); + } + + if (!quiet) { + fprintf(stderr, "Conversion successful.\n"); + } + } + +no_mbr_conv:; + + int mbr = 0; + if (gpt == 0) { + // Do all sanity checks on MBR + mbr = 1; + + uint8_t hint8 = 0; + uint32_t hint32 = 0; + + bool any_active = false; + + device_read(&hint8, 446, sizeof(uint8_t)); + if (hint8 != 0x00 && hint8 != 0x80) { + if (!force) { + mbr = 0; + } else { + hint8 &= 0x80; + device_write(&hint8, 446, sizeof(uint8_t)); + } + } + any_active = any_active || (hint8 & 0x80) != 0; + device_read(&hint8, 446 + 4, sizeof(uint8_t)); + if (hint8 != 0x00) { + device_read(&hint32, 446 + 8, sizeof(uint32_t)); + hint32 = ENDSWAP(hint32); + if (hint32 < 63) { + goto part_too_low; + } + } + device_read(&hint8, 462, sizeof(uint8_t)); + if (hint8 != 0x00 && hint8 != 0x80) { + if (!force) { + mbr = 0; + } else { + hint8 &= 0x80; + device_write(&hint8, 462, sizeof(uint8_t)); + } + } + any_active = any_active || (hint8 & 0x80) != 0; + device_read(&hint8, 462 + 4, sizeof(uint8_t)); + if (hint8 != 0x00) { + device_read(&hint32, 462 + 8, sizeof(uint32_t)); + hint32 = ENDSWAP(hint32); + if (hint32 < 63) { + goto part_too_low; + } + } + device_read(&hint8, 478, sizeof(uint8_t)); + if (hint8 != 0x00 && hint8 != 0x80) { + if (!force) { + mbr = 0; + } else { + hint8 &= 0x80; + device_write(&hint8, 478, sizeof(uint8_t)); + } + } + any_active = any_active || (hint8 & 0x80) != 0; + device_read(&hint8, 478 + 4, sizeof(uint8_t)); + if (hint8 != 0x00) { + device_read(&hint32, 478 + 8, sizeof(uint32_t)); + hint32 = ENDSWAP(hint32); + if (hint32 < 63) { + goto part_too_low; + } + } + device_read(&hint8, 494, sizeof(uint8_t)); + if (hint8 != 0x00 && hint8 != 0x80) { + if (!force) { + mbr = 0; + } else { + hint8 &= 0x80; + device_write(&hint8, 494, sizeof(uint8_t)); + } + } + any_active = any_active || (hint8 & 0x80) != 0; + device_read(&hint8, 494 + 4, sizeof(uint8_t)); + if (hint8 != 0x00) { + device_read(&hint32, 494 + 8, sizeof(uint32_t)); + hint32 = ENDSWAP(hint32); + if (hint32 < 63) { + goto part_too_low; + } + } + + if (0) { +part_too_low: + fprintf(stderr, "error: A partition's start sector is less than 63, aborting.\n"); + goto cleanup; + } + + if (mbr) { + bool err; + mbr = validate_or_force(0, force, &err); + if (err) { + goto cleanup; + } + } + + if (mbr && !any_active) { + if (!quiet) { + fprintf(stderr, "No active partition found, some systems may not boot.\n"); + fprintf(stderr, "Setting partition 1 as active to work around the issue...\n"); + } + hint8 = 0x80; + device_write(&hint8, 446, sizeof(uint8_t)); + } + } + + if (gpt == 0 && mbr == 0) { + fprintf(stderr, "error: Could not determine if the device has a valid partition table.\n"); + fprintf(stderr, " Please ensure the device has a valid MBR or GPT.\n"); + fprintf(stderr, " Alternatively, pass `--force` to override these checks.\n"); + fprintf(stderr, " **ONLY DO THIS AT YOUR OWN RISK, DATA LOSS MAY OCCUR!**\n"); + goto cleanup; + } + + // Default location of stage2 for MBR (in post MBR gap) + uint64_t stage2_loc = 512; + + if (gpt) { + struct gpt_entry gpt_entry; + uint32_t partition_num; + + uint64_t gpt_part_entry_base; + if (mul_u64_overflow(ENDSWAP(gpt_header.partition_entry_lba), lb_size, &gpt_part_entry_base)) { + fprintf(stderr, "error: GPT partition entry LBA overflows.\n"); + goto cleanup; + } + + if (part_ndx != NULL) { + if (sscanf(part_ndx, "%" SCNu32, &partition_num) != 1) { + fprintf(stderr, "error: Invalid partition number format.\n"); + goto cleanup; + } + partition_num--; + if (partition_num >= ENDSWAP(gpt_header.number_of_partition_entries)) { + fprintf(stderr, "error: Partition number is too large.\n"); + goto cleanup; + } + + uint64_t entry_off = (uint64_t)partition_num * ENDSWAP(gpt_header.size_of_partition_entry); + if (add_u64_overflow(gpt_part_entry_base, entry_off, &entry_off)) { + fprintf(stderr, "error: GPT partition entry offset overflows.\n"); + goto cleanup; + } + device_read(&gpt_entry, entry_off, sizeof(struct gpt_entry)); + + if (gpt_entry.unique_partition_guid[0] == 0 && + gpt_entry.unique_partition_guid[1] == 0) { + fprintf(stderr, "error: No such partition: %" PRIu32 ".\n", partition_num + 1); + goto cleanup; + } + + if (!force && memcmp("Hah!IdontNeedEFI", &gpt_entry.partition_type_guid, 16) != 0) { + fprintf(stderr, "error: Chosen partition for BIOS boot code is not of BIOS boot partition type.\n"); + fprintf(stderr, " Pass `--force` to override this check.\n"); + fprintf(stderr, " **ONLY DO THIS AT YOUR OWN RISK, DATA LOSS MAY OCCUR!**\n"); + goto cleanup; + } + } else { + // Try to autodetect the BIOS boot partition + for (partition_num = 0; partition_num < ENDSWAP(gpt_header.number_of_partition_entries); partition_num++) { + uint64_t entry_off = (uint64_t)partition_num * ENDSWAP(gpt_header.size_of_partition_entry); + if (add_u64_overflow(gpt_part_entry_base, entry_off, &entry_off)) { + fprintf(stderr, "error: GPT partition entry offset overflows.\n"); + goto cleanup; + } + device_read(&gpt_entry, entry_off, sizeof(struct gpt_entry)); + + if (memcmp("Hah!IdontNeedEFI", &gpt_entry.partition_type_guid, 16) == 0) { + if (!quiet) { + fprintf(stderr, "Autodetected partition %" PRIu32 " as BIOS boot partition.\n", partition_num + 1); + } + goto bios_boot_autodetected; + } + } + + fprintf(stderr, "error: Installing to a GPT device, but no BIOS boot partition specified or\n"); + fprintf(stderr, " detected.\n"); + goto cleanup; + } + +bios_boot_autodetected:; + uint64_t starting_lba = ENDSWAP(gpt_entry.starting_lba); + uint64_t ending_lba = ENDSWAP(gpt_entry.ending_lba); + + if (ending_lba < starting_lba) { + fprintf(stderr, "error: Partition %" PRIu32 " has ending LBA less than starting LBA.\n", partition_num + 1); + goto cleanup; + } + + uint64_t part_size; + if (mul_u64_overflow(ending_lba - starting_lba + 1, lb_size, &part_size)) { + fprintf(stderr, "error: Partition %" PRIu32 " size overflows.\n", partition_num + 1); + goto cleanup; + } + + if (part_size < 32768) { + fprintf(stderr, "error: Partition %" PRIu32 " is smaller than 32KiB.\n", partition_num + 1); + goto cleanup; + } + + if (mul_u64_overflow(starting_lba, lb_size, &stage2_loc)) { + fprintf(stderr, "error: Partition %" PRIu32 " starting LBA overflows.\n", partition_num + 1); + goto cleanup; + } + + bool err; + bool valid = validate_or_force(stage2_loc, force, &err); + if (err) { + goto cleanup; + } + + if (!valid) { + fprintf(stderr, "error: The partition selected to install the BIOS boot code to contains\n"); + fprintf(stderr, " a recognised filesystem.\n"); + fprintf(stderr, " Pass `--force` to override these checks.\n"); + fprintf(stderr, " **ONLY DO THIS AT YOUR OWN RISK, DATA LOSS MAY OCCUR!**\n"); + goto cleanup; + } + + if (!quiet) { + fprintf(stderr, "Installing BIOS boot code to partition %" PRIu32 ".\n", partition_num + 1); + } + } else { + if (!quiet) { + fprintf(stderr, "Installing to MBR.\n"); + } + } + + if (!quiet) { + fprintf(stderr, "Stage 2 to be located at byte offset 0x%" PRIx64 ".\n", stage2_loc); + } + + // Save original timestamp + device_read(timestamp, 218, 6); + + // Save the original partition table of the device + device_read(orig_mbr, 440, 70); + + // Write the bootsector from the bootloader to the device + device_write(&bootloader_img[0], 0, 512); + + // Write the rest of stage 2 to the device + device_write(&bootloader_img[512], stage2_loc, bootloader_file_size - 512); + + // Hardcode in the bootsector the location of stage 2 + stage2_loc = ENDSWAP(stage2_loc); + device_write(&stage2_loc, 0x1a4, sizeof(uint64_t)); + + // Write back timestamp + device_write(timestamp, 218, 6); + + // Write back the saved partition table to the device + device_write(orig_mbr, 440, 70); + + if (!device_flush_cache()) + goto cleanup; + + if (!quiet) { + fprintf(stderr, "Reminder: Remember to copy the limine-bios.sys file in either\n" + " the root, /boot, /limine, or /boot/limine directories of\n" + " one of the partitions on the device, or boot will fail!\n"); + + fprintf(stderr, "Limine BIOS stages installed successfully.\n"); + } + + ok = EXIT_SUCCESS; + +cleanup: + reverse_uninstall_data(); + if (ok != EXIT_SUCCESS) { + // If we failed, attempt to reverse install process + fprintf(stderr, "Install failed, undoing work...\n"); + uninstall(true); + } else if (uninstall_file != NULL) { + store_uninstall_data(uninstall_file); + } +uninstall_mode_cleanup: + free_uninstall_data(); + if (cache) + free(cache); + if (device != NULL) + fclose(device); + + return ok; +} +#endif + +#define CONFIG_B2SUM_SIGNATURE "++CONFIG_B2SUM_SIGNATURE++" + +static void enroll_config_usage(void) { + printf("usage: %s enroll-config \n", program_name); + printf("\n"); + printf(" --reset Remove enrolled BLAKE2B, will not check config integrity\n"); + printf("\n"); + printf(" --quiet Do not print verbose diagnostic messages\n"); + printf("\n"); + printf(" --help | -h Display this help message\n"); + printf("\n"); +} + +static int enroll_config(int argc, char *argv[]) { + int ret = EXIT_FAILURE; + + char *bootloader = NULL; + FILE *bootloader_file = NULL; + bool quiet = false; + bool reset = false; + + for (int i = 1; i < argc; i++) { + if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-h") == 0) { + enroll_config_usage(); + return EXIT_SUCCESS; + } else if (strcmp(argv[i], "--quiet") == 0) { + remove_arg(&argc, argv, i--); + quiet = true; + } else if (strcmp(argv[i], "--reset") == 0) { + remove_arg(&argc, argv, i--); + reset = true; + } + } + + if (argc <= (reset ? 1 : 2)) { + enroll_config_usage(); +#ifdef IS_WINDOWS + system("pause"); +#endif + return EXIT_FAILURE; + } + + if (!reset && strlen(argv[2]) != 128) { + fprintf(stderr, "error: BLAKE2B specified is not 128 characters long.\n"); + goto cleanup; + } + + bootloader_file = fopen(argv[1], "r+b"); + if (bootloader_file == NULL) { + perror_wrap("error: `%s`", argv[1]); + goto cleanup; + } + + if (fseek(bootloader_file, 0, SEEK_END) != 0) { + perror_wrap("error: enroll_config(): fseek()"); + goto cleanup; + } + long ftell_result = ftell(bootloader_file); + if (ftell_result < 0) { + perror_wrap("error: enroll_config(): ftell()"); + goto cleanup; + } + size_t bootloader_size = (size_t)ftell_result; + rewind(bootloader_file); + + size_t min_size = (sizeof(CONFIG_B2SUM_SIGNATURE) - 1) + 128; + if (bootloader_size < min_size) { + fprintf(stderr, "error: Bootloader file too small (need at least %zu bytes)\n", min_size); + goto cleanup; + } + + bootloader = malloc(bootloader_size); + if (bootloader == NULL) { + perror_wrap("error: enroll_config(): malloc()"); + goto cleanup; + } + + if (fread(bootloader, bootloader_size, 1, bootloader_file) != 1) { + perror_wrap("error: enroll_config(): fread()"); + goto cleanup; + } + + char *checksum_loc = NULL; + size_t checked_count = 0; + const char *config_b2sum_sign = CONFIG_B2SUM_SIGNATURE; + for (size_t i = 0; i < bootloader_size - min_size + 1; i++) { + if (bootloader[i] != config_b2sum_sign[checked_count]) { + if (checked_count > 0) { + i -= checked_count; // restart after first byte of failed match + checked_count = 0; + } + continue; + } + + checked_count++; + + if (checked_count == sizeof(CONFIG_B2SUM_SIGNATURE) - 1) { + checksum_loc = &bootloader[i + 1]; + break; + } + } + + if (checksum_loc == NULL) { + fprintf(stderr, "error: Checksum location not found in provided executable.\n"); + goto cleanup; + } + + if (!reset) { + memcpy(checksum_loc, argv[2], 128); + } else { + memset(checksum_loc, '0', 128); + } + + if (fseek(bootloader_file, 0, SEEK_SET) != 0) { + perror_wrap("error: enroll_config(): fseek()"); + goto cleanup; + } + if (fwrite(bootloader, bootloader_size, 1, bootloader_file) != 1) { + perror_wrap("error: enroll_config(): fwrite()"); + goto cleanup; + } + + if (!quiet) { + fprintf(stderr, "Config file BLAKE2B successfully %s.\n", reset ? "reset" : "enrolled"); + } + ret = EXIT_SUCCESS; + +cleanup: + if (bootloader != NULL) { + free(bootloader); + } + if (bootloader_file != NULL) { + fclose(bootloader_file); + } + return ret; +} + +#define LIMINE_VERSION "11.2.1" +#define LIMINE_COPYRIGHT "Copyright (C) 2019-2026 Mintsuki and contributors." + +static void version_usage(void) { + printf("usage: %s version [options...]\n", program_name); + printf("\n"); + printf(" --version-only Only print the version number without licensing info\n"); + printf(" and other distractions\n"); + printf("\n"); + printf(" --help | -h Display this help message\n"); + printf("\n"); +} + +static int version(int argc, char *argv[]) { + if (argc >= 2) { + if (strcmp(argv[1], "--help") == 0) { + version_usage(); + return EXIT_SUCCESS; + } else if (strcmp(argv[1], "--version-only") == 0) { + puts(LIMINE_VERSION); + return EXIT_SUCCESS; + } + } + + puts("Limine " LIMINE_VERSION); + puts(LIMINE_COPYRIGHT); + puts("Limine is distributed under the terms of the BSD-2-Clause license."); + puts("There is ABSOLUTELY NO WARRANTY, to the extent permitted by law."); + return EXIT_SUCCESS; +} + +static void general_usage(void) { + printf("usage: %s \n", program_name); + printf("\n"); + printf(" --print-datadir Print the directory containing the bootloader files\n"); + printf("\n"); + printf(" --version Print the Limine version (like the `version` command)\n"); + printf("\n"); + printf(" --help | -h Display this help message\n"); + printf("\n"); + printf("Commands: `help`, `version`, `bios-install`, `enroll-config`\n"); + printf("Use `--help` after specifying the command for command-specific help.\n"); +} + +static int print_datadir(void) { +#ifdef LIMINE_DATADIR + puts(LIMINE_DATADIR); + return EXIT_SUCCESS; +#else + fprintf(stderr, "error: Cannot print datadir for `limine` built standalone.\n"); + return EXIT_FAILURE; +#endif +} + +int main(int argc, char *argv[]) { + program_name = argv[0]; + + if (argc <= 1) { + general_usage(); + return EXIT_FAILURE; + } + + if (strcmp(argv[1], "help") == 0 + || strcmp(argv[1], "--help") == 0 + || strcmp(argv[1], "-h") == 0) { + general_usage(); + return EXIT_SUCCESS; + } else if (strcmp(argv[1], "bios-install") == 0) { +#ifndef LIMINE_NO_BIOS + return bios_install(argc - 1, &argv[1]); +#else + fprintf(stderr, "error: Limine has been compiled without BIOS support.\n"); + return EXIT_FAILURE; +#endif + } else if (strcmp(argv[1], "enroll-config") == 0) { + return enroll_config(argc - 1, &argv[1]); + } else if (strcmp(argv[1], "--print-datadir") == 0) { + return print_datadir(); + } else if (strcmp(argv[1], "version") == 0 + || strcmp(argv[1], "--version") == 0) { + return version(argc - 1, &argv[1]); + } + + general_usage(); + return EXIT_FAILURE; +} diff --git a/linker.lds b/linker.lds new file mode 100644 index 0000000..04121ea --- /dev/null +++ b/linker.lds @@ -0,0 +1,81 @@ +/* Tell the linker that we want an x86_64 ELF64 output file */ +OUTPUT_FORMAT(elf64-x86-64) + +/* We want the symbol kmain to be our entry point */ +ENTRY(kmain) + +/* Define the program headers we want so the bootloader gives us the right */ +/* MMU permissions; this also allows us to exert more control over the linking */ +/* process. */ +PHDRS +{ + limine_requests PT_LOAD; + text PT_LOAD; + rodata PT_LOAD; + data PT_LOAD; +} + +SECTIONS +{ + /* We want to be placed in the topmost 2GiB of the address space, for optimisations */ + /* and because that is what the Limine spec mandates. */ + /* Any address in this region will do, but often 0xffffffff80000000 is chosen as */ + /* that is the beginning of the region. */ + . = 0xffffffff80000000; + + /* Define a section to contain the Limine requests and assign it to its own PHDR */ + .limine_requests : { + KEEP(*(.limine_requests_start)) + KEEP(*(.limine_requests)) + KEEP(*(.limine_requests_end)) + } :limine_requests + + /* Move to the next memory page for .text */ + . = ALIGN(CONSTANT(MAXPAGESIZE)); + __text_start_addr = .; + .text : { + *(.text .text.*) + } :text + __text_end_addr = .; + + /* Move to the next memory page for .rodata */ + . = ALIGN(CONSTANT(MAXPAGESIZE)); + __rodata_start_addr = .; + .rodata : { + *(.rodata .rodata.*) + } :rodata + __rodata_end_addr = .; + + /* Add a .note.gnu.build-id output section in case a build ID flag is added to the */ + /* linker command. */ + .note.gnu.build-id : { + *(.note.gnu.build-id) + } :rodata + + /* Move to the next memory page for .data */ + . = ALIGN(CONSTANT(MAXPAGESIZE)); + __data_start_addr = .; + .data : { + *(.data .data.*) + } :data + __data_end_addr = .; + + /* NOTE: .bss needs to be the last thing mapped to :data, otherwise lots of */ + /* unnecessary zeros will be written to the binary. */ + /* If you need, for example, .init_array and .fini_array, those should be placed */ + /* above this. */ + __bss_start_addr = .; + .bss : { + *(.bss .bss.*) + *(COMMON) + } :data + __bss_end_addr = .; + + __kernel_end = .; + + /* Discard .note.* and .eh_frame* since they may cause issues on some hosts. */ + /DISCARD/ : { + *(.eh_frame*) + *(.note .note.*) + } +} \ No newline at end of file diff --git a/obj/src/arch/x86_64/ata.c.d b/obj/src/arch/x86_64/ata.c.d new file mode 100644 index 0000000..11e0d83 --- /dev/null +++ b/obj/src/arch/x86_64/ata.c.d @@ -0,0 +1,5 @@ +obj/src/arch/x86_64/ata.c.o: src/arch/x86_64/ata.c src/arch/x86_64/ata.h \ + src/arch/x86_64/io.h src/stdio.h +src/arch/x86_64/ata.h: +src/arch/x86_64/io.h: +src/stdio.h: diff --git a/obj/src/arch/x86_64/ata.c.o b/obj/src/arch/x86_64/ata.c.o new file mode 100644 index 0000000..c1b1e47 Binary files /dev/null and b/obj/src/arch/x86_64/ata.c.o differ diff --git a/obj/src/arch/x86_64/e9.c.d b/obj/src/arch/x86_64/e9.c.d new file mode 100644 index 0000000..2c70332 --- /dev/null +++ b/obj/src/arch/x86_64/e9.c.d @@ -0,0 +1,4 @@ +obj/src/arch/x86_64/e9.c.o: src/arch/x86_64/e9.c src/arch/x86_64/e9.h \ + src/arch/x86_64/io.h +src/arch/x86_64/e9.h: +src/arch/x86_64/io.h: diff --git a/obj/src/arch/x86_64/e9.c.o b/obj/src/arch/x86_64/e9.c.o new file mode 100644 index 0000000..d23b8f3 Binary files /dev/null and b/obj/src/arch/x86_64/e9.c.o differ diff --git a/obj/src/arch/x86_64/gdt.c.d b/obj/src/arch/x86_64/gdt.c.d new file mode 100644 index 0000000..466a3e6 --- /dev/null +++ b/obj/src/arch/x86_64/gdt.c.d @@ -0,0 +1,6 @@ +obj/src/arch/x86_64/gdt.c.o: src/arch/x86_64/gdt.c src/arch/x86_64/gdt.h \ + src/mm/memory.h src/mm/slab.h src/mp/spinlock.h +src/arch/x86_64/gdt.h: +src/mm/memory.h: +src/mm/slab.h: +src/mp/spinlock.h: diff --git a/obj/src/arch/x86_64/gdt.c.o b/obj/src/arch/x86_64/gdt.c.o new file mode 100644 index 0000000..9c0523a Binary files /dev/null and b/obj/src/arch/x86_64/gdt.c.o differ diff --git a/obj/src/arch/x86_64/gdt_asm.S.d b/obj/src/arch/x86_64/gdt_asm.S.d new file mode 100644 index 0000000..91f03d7 --- /dev/null +++ b/obj/src/arch/x86_64/gdt_asm.S.d @@ -0,0 +1 @@ +obj/src/arch/x86_64/gdt_asm.S.o: src/arch/x86_64/gdt_asm.S diff --git a/obj/src/arch/x86_64/gdt_asm.S.o b/obj/src/arch/x86_64/gdt_asm.S.o new file mode 100644 index 0000000..cf3451c Binary files /dev/null and b/obj/src/arch/x86_64/gdt_asm.S.o differ diff --git a/obj/src/arch/x86_64/i8259.c.d b/obj/src/arch/x86_64/i8259.c.d new file mode 100644 index 0000000..6e24e2b --- /dev/null +++ b/obj/src/arch/x86_64/i8259.c.d @@ -0,0 +1,4 @@ +obj/src/arch/x86_64/i8259.c.o: src/arch/x86_64/i8259.c \ + src/arch/x86_64/pic.h src/arch/x86_64/io.h +src/arch/x86_64/pic.h: +src/arch/x86_64/io.h: diff --git a/obj/src/arch/x86_64/i8259.c.o b/obj/src/arch/x86_64/i8259.c.o new file mode 100644 index 0000000..edaf9f4 Binary files /dev/null and b/obj/src/arch/x86_64/i8259.c.o differ diff --git a/obj/src/arch/x86_64/idt.c.d b/obj/src/arch/x86_64/idt.c.d new file mode 100644 index 0000000..9c8281b --- /dev/null +++ b/obj/src/arch/x86_64/idt.c.d @@ -0,0 +1,4 @@ +obj/src/arch/x86_64/idt.c.o: src/arch/x86_64/idt.c src/arch/x86_64/idt.h \ + src/util/binary.h +src/arch/x86_64/idt.h: +src/util/binary.h: diff --git a/obj/src/arch/x86_64/idt.c.o b/obj/src/arch/x86_64/idt.c.o new file mode 100644 index 0000000..051b31f Binary files /dev/null and b/obj/src/arch/x86_64/idt.c.o differ diff --git a/obj/src/arch/x86_64/idt_asm.S.d b/obj/src/arch/x86_64/idt_asm.S.d new file mode 100644 index 0000000..2a065a2 --- /dev/null +++ b/obj/src/arch/x86_64/idt_asm.S.d @@ -0,0 +1 @@ +obj/src/arch/x86_64/idt_asm.S.o: src/arch/x86_64/idt_asm.S diff --git a/obj/src/arch/x86_64/idt_asm.S.o b/obj/src/arch/x86_64/idt_asm.S.o new file mode 100644 index 0000000..ad54bfb Binary files /dev/null and b/obj/src/arch/x86_64/idt_asm.S.o differ diff --git a/obj/src/arch/x86_64/io_asm.S.d b/obj/src/arch/x86_64/io_asm.S.d new file mode 100644 index 0000000..f6ca986 --- /dev/null +++ b/obj/src/arch/x86_64/io_asm.S.d @@ -0,0 +1 @@ +obj/src/arch/x86_64/io_asm.S.o: src/arch/x86_64/io_asm.S diff --git a/obj/src/arch/x86_64/io_asm.S.o b/obj/src/arch/x86_64/io_asm.S.o new file mode 100644 index 0000000..207b60f Binary files /dev/null and b/obj/src/arch/x86_64/io_asm.S.o differ diff --git a/obj/src/arch/x86_64/ioapic.c.d b/obj/src/arch/x86_64/ioapic.c.d new file mode 100644 index 0000000..4d98a5c --- /dev/null +++ b/obj/src/arch/x86_64/ioapic.c.d @@ -0,0 +1,6 @@ +obj/src/arch/x86_64/ioapic.c.o: src/arch/x86_64/ioapic.c \ + src/arch/x86_64/ioapic.h src/stdio.h src/mm/vmm.h src/limine.h +src/arch/x86_64/ioapic.h: +src/stdio.h: +src/mm/vmm.h: +src/limine.h: diff --git a/obj/src/arch/x86_64/irq.c.d b/obj/src/arch/x86_64/irq.c.d new file mode 100644 index 0000000..652b16d --- /dev/null +++ b/obj/src/arch/x86_64/irq.c.d @@ -0,0 +1,11 @@ +obj/src/arch/x86_64/irq.c.o: src/arch/x86_64/irq.c src/arch/x86_64/irq.h \ + src/arch/x86_64/isr.h src/arch/x86_64/i8259.h src/arch/x86_64/pic.h \ + src/arch/x86_64/io.h src/util/arrays.h src/stdio.h src/debug.h +src/arch/x86_64/irq.h: +src/arch/x86_64/isr.h: +src/arch/x86_64/i8259.h: +src/arch/x86_64/pic.h: +src/arch/x86_64/io.h: +src/util/arrays.h: +src/stdio.h: +src/debug.h: diff --git a/obj/src/arch/x86_64/irq.c.o b/obj/src/arch/x86_64/irq.c.o new file mode 100644 index 0000000..b6230b6 Binary files /dev/null and b/obj/src/arch/x86_64/irq.c.o differ diff --git a/obj/src/arch/x86_64/isr.c.d b/obj/src/arch/x86_64/isr.c.d new file mode 100644 index 0000000..1af6bbe --- /dev/null +++ b/obj/src/arch/x86_64/isr.c.d @@ -0,0 +1,7 @@ +obj/src/arch/x86_64/isr.c.o: src/arch/x86_64/isr.c src/arch/x86_64/io.h \ + src/debug.h src/stdio.h src/arch/x86_64/isr.h src/arch/x86_64/idt.h +src/arch/x86_64/io.h: +src/debug.h: +src/stdio.h: +src/arch/x86_64/isr.h: +src/arch/x86_64/idt.h: diff --git a/obj/src/arch/x86_64/isr.c.o b/obj/src/arch/x86_64/isr.c.o new file mode 100644 index 0000000..b0e53f9 Binary files /dev/null and b/obj/src/arch/x86_64/isr.c.o differ diff --git a/obj/src/arch/x86_64/isr_asm.S.d b/obj/src/arch/x86_64/isr_asm.S.d new file mode 100644 index 0000000..7574909 --- /dev/null +++ b/obj/src/arch/x86_64/isr_asm.S.d @@ -0,0 +1 @@ +obj/src/arch/x86_64/isr_asm.S.o: src/arch/x86_64/isr_asm.S diff --git a/obj/src/arch/x86_64/isr_asm.S.o b/obj/src/arch/x86_64/isr_asm.S.o new file mode 100644 index 0000000..927e0a6 Binary files /dev/null and b/obj/src/arch/x86_64/isr_asm.S.o differ diff --git a/obj/src/arch/x86_64/isrs_gen.c.d b/obj/src/arch/x86_64/isrs_gen.c.d new file mode 100644 index 0000000..a24818b --- /dev/null +++ b/obj/src/arch/x86_64/isrs_gen.c.d @@ -0,0 +1,4 @@ +obj/src/arch/x86_64/isrs_gen.c.o: src/arch/x86_64/isrs_gen.c \ + src/arch/x86_64/idt.h src/arch/x86_64/gdt.h +src/arch/x86_64/idt.h: +src/arch/x86_64/gdt.h: diff --git a/obj/src/arch/x86_64/isrs_gen.c.o b/obj/src/arch/x86_64/isrs_gen.c.o new file mode 100644 index 0000000..00255d9 Binary files /dev/null and b/obj/src/arch/x86_64/isrs_gen.c.o differ diff --git a/obj/src/arch/x86_64/lapic.c.d b/obj/src/arch/x86_64/lapic.c.d new file mode 100644 index 0000000..e74734d --- /dev/null +++ b/obj/src/arch/x86_64/lapic.c.d @@ -0,0 +1,21 @@ +obj/src/arch/x86_64/lapic.c.o: src/arch/x86_64/lapic.c \ + src/arch/x86_64/lapic.h src/arch/x86_64/ioapic.h src/arch/x86_64/i8259.h \ + src/arch/x86_64/pic.h src/mm/vmm.h src/limine.h src/arch/x86_64/pit.h \ + src/arch/x86_64/irq.h src/arch/x86_64/isr.h src/arch/x86_64/io.h \ + src/stdio.h src/arch/x86_64/e9.h src/arch/x86_64/rtc.h \ + src/sched/scheduler.h src/sched/thread.h +src/arch/x86_64/lapic.h: +src/arch/x86_64/ioapic.h: +src/arch/x86_64/i8259.h: +src/arch/x86_64/pic.h: +src/mm/vmm.h: +src/limine.h: +src/arch/x86_64/pit.h: +src/arch/x86_64/irq.h: +src/arch/x86_64/isr.h: +src/arch/x86_64/io.h: +src/stdio.h: +src/arch/x86_64/e9.h: +src/arch/x86_64/rtc.h: +src/sched/scheduler.h: +src/sched/thread.h: diff --git a/obj/src/arch/x86_64/lapic.c.o b/obj/src/arch/x86_64/lapic.c.o new file mode 100644 index 0000000..d7ac4c6 Binary files /dev/null and b/obj/src/arch/x86_64/lapic.c.o differ diff --git a/obj/src/arch/x86_64/pit.c.d b/obj/src/arch/x86_64/pit.c.d new file mode 100644 index 0000000..4cfccc9 --- /dev/null +++ b/obj/src/arch/x86_64/pit.c.d @@ -0,0 +1,13 @@ +obj/src/arch/x86_64/pit.c.o: src/arch/x86_64/pit.c src/arch/x86_64/pit.h \ + src/arch/x86_64/irq.h src/arch/x86_64/isr.h src/arch/x86_64/io.h \ + src/stdio.h src/arch/x86_64/e9.h src/arch/x86_64/rtc.h \ + src/sched/scheduler.h src/sched/thread.h +src/arch/x86_64/pit.h: +src/arch/x86_64/irq.h: +src/arch/x86_64/isr.h: +src/arch/x86_64/io.h: +src/stdio.h: +src/arch/x86_64/e9.h: +src/arch/x86_64/rtc.h: +src/sched/scheduler.h: +src/sched/thread.h: diff --git a/obj/src/arch/x86_64/pit.c.o b/obj/src/arch/x86_64/pit.c.o new file mode 100644 index 0000000..caaf439 Binary files /dev/null and b/obj/src/arch/x86_64/pit.c.o differ diff --git a/obj/src/arch/x86_64/rtc.c.d b/obj/src/arch/x86_64/rtc.c.d new file mode 100644 index 0000000..a03608c --- /dev/null +++ b/obj/src/arch/x86_64/rtc.c.d @@ -0,0 +1,4 @@ +obj/src/arch/x86_64/rtc.c.o: src/arch/x86_64/rtc.c src/arch/x86_64/rtc.h \ + src/arch/x86_64/io.h +src/arch/x86_64/rtc.h: +src/arch/x86_64/io.h: diff --git a/obj/src/arch/x86_64/rtc.c.o b/obj/src/arch/x86_64/rtc.c.o new file mode 100644 index 0000000..f00ab0d Binary files /dev/null and b/obj/src/arch/x86_64/rtc.c.o differ diff --git a/obj/src/arch/x86_64/usermode.c.d b/obj/src/arch/x86_64/usermode.c.d new file mode 100644 index 0000000..1cea3f7 --- /dev/null +++ b/obj/src/arch/x86_64/usermode.c.d @@ -0,0 +1,12 @@ +obj/src/arch/x86_64/usermode.c.o: src/arch/x86_64/usermode.c src/string.h \ + src/mm/pmm.h src/limine.h src/mm/vmm.h src/mp/spinlock.h src/mm/memory.h \ + src/mm/slab.h src/stdio.h src/fs/elf.h +src/string.h: +src/mm/pmm.h: +src/limine.h: +src/mm/vmm.h: +src/mp/spinlock.h: +src/mm/memory.h: +src/mm/slab.h: +src/stdio.h: +src/fs/elf.h: diff --git a/obj/src/arch/x86_64/usermode.c.o b/obj/src/arch/x86_64/usermode.c.o new file mode 100644 index 0000000..e009068 Binary files /dev/null and b/obj/src/arch/x86_64/usermode.c.o differ diff --git a/obj/src/debug.c.d b/obj/src/debug.c.d new file mode 100644 index 0000000..6220998 --- /dev/null +++ b/obj/src/debug.c.d @@ -0,0 +1,3 @@ +obj/src/debug.c.o: src/debug.c src/debug.h src/stdio.h +src/debug.h: +src/stdio.h: diff --git a/obj/src/debug.c.o b/obj/src/debug.c.o new file mode 100644 index 0000000..016b6ad Binary files /dev/null and b/obj/src/debug.c.o differ diff --git a/obj/src/fs/elf.c.d b/obj/src/fs/elf.c.d new file mode 100644 index 0000000..ad3d096 --- /dev/null +++ b/obj/src/fs/elf.c.d @@ -0,0 +1,13 @@ +obj/src/fs/elf.c.o: src/fs/elf.c src/fs/elf.h src/stdio.h src/string.h \ + src/mm/pmm.h src/limine.h src/mm/vmm.h src/mp/spinlock.h src/mm/memory.h \ + src/mm/slab.h src/fs/ext2.h +src/fs/elf.h: +src/stdio.h: +src/string.h: +src/mm/pmm.h: +src/limine.h: +src/mm/vmm.h: +src/mp/spinlock.h: +src/mm/memory.h: +src/mm/slab.h: +src/fs/ext2.h: diff --git a/obj/src/fs/elf.c.o b/obj/src/fs/elf.c.o new file mode 100644 index 0000000..3d5bc0e Binary files /dev/null and b/obj/src/fs/elf.c.o differ diff --git a/obj/src/fs/ext2.c.d b/obj/src/fs/ext2.c.d new file mode 100644 index 0000000..47f8916 --- /dev/null +++ b/obj/src/fs/ext2.c.d @@ -0,0 +1,9 @@ +obj/src/fs/ext2.c.o: src/fs/ext2.c src/fs/ext2.h src/arch/x86_64/ata.h \ + src/mm/memory.h src/mm/slab.h src/stdio.h src/string.h src/mp/spinlock.h +src/fs/ext2.h: +src/arch/x86_64/ata.h: +src/mm/memory.h: +src/mm/slab.h: +src/stdio.h: +src/string.h: +src/mp/spinlock.h: diff --git a/obj/src/fs/ext2.c.o b/obj/src/fs/ext2.c.o new file mode 100644 index 0000000..38d0669 Binary files /dev/null and b/obj/src/fs/ext2.c.o differ diff --git a/obj/src/fs/vfs.c.d b/obj/src/fs/vfs.c.d new file mode 100644 index 0000000..e42eefa --- /dev/null +++ b/obj/src/fs/vfs.c.d @@ -0,0 +1,7 @@ +obj/src/fs/vfs.c.o: src/fs/vfs.c src/fs/vfs.h src/fs/ext2.h \ + src/video/render.h src/arch/x86_64/e9.h src/mp/spinlock.h +src/fs/vfs.h: +src/fs/ext2.h: +src/video/render.h: +src/arch/x86_64/e9.h: +src/mp/spinlock.h: diff --git a/obj/src/fs/vfs.c.o b/obj/src/fs/vfs.c.o new file mode 100644 index 0000000..861024f Binary files /dev/null and b/obj/src/fs/vfs.c.o differ diff --git a/obj/src/main.c.d b/obj/src/main.c.d new file mode 100644 index 0000000..d2a5989 --- /dev/null +++ b/obj/src/main.c.d @@ -0,0 +1,26 @@ +obj/src/main.c.o: src/main.c src/limine.h src/video/render.h \ + src/video/tga.h src/stdio.h src/arch/x86_64/gdt.h src/arch/x86_64/idt.h \ + src/arch/x86_64/isr.h src/arch/x86_64/irq.h src/mm/memory.h \ + src/mm/slab.h src/mm/pmm.h src/mm/vmm.h src/mp/spinlock.h \ + src/arch/x86_64/ata.h src/fs/ext2.h src/string.h src/arch/x86_64/io.h \ + src/arch/x86_64/usermode.h src/syscall/syscall.h src/fs/vfs.h +src/limine.h: +src/video/render.h: +src/video/tga.h: +src/stdio.h: +src/arch/x86_64/gdt.h: +src/arch/x86_64/idt.h: +src/arch/x86_64/isr.h: +src/arch/x86_64/irq.h: +src/mm/memory.h: +src/mm/slab.h: +src/mm/pmm.h: +src/mm/vmm.h: +src/mp/spinlock.h: +src/arch/x86_64/ata.h: +src/fs/ext2.h: +src/string.h: +src/arch/x86_64/io.h: +src/arch/x86_64/usermode.h: +src/syscall/syscall.h: +src/fs/vfs.h: diff --git a/obj/src/main.c.o b/obj/src/main.c.o new file mode 100644 index 0000000..0b123e4 Binary files /dev/null and b/obj/src/main.c.o differ diff --git a/obj/src/mm/memory.c.d b/obj/src/mm/memory.c.d new file mode 100644 index 0000000..73b3534 --- /dev/null +++ b/obj/src/mm/memory.c.d @@ -0,0 +1,7 @@ +obj/src/mm/memory.c.o: src/mm/memory.c src/mm/pmm.h src/limine.h \ + src/stdio.h src/mm/vmm.h src/mp/spinlock.h +src/mm/pmm.h: +src/limine.h: +src/stdio.h: +src/mm/vmm.h: +src/mp/spinlock.h: diff --git a/obj/src/mm/memory.c.o b/obj/src/mm/memory.c.o new file mode 100644 index 0000000..e21a3f4 Binary files /dev/null and b/obj/src/mm/memory.c.o differ diff --git a/obj/src/mm/pmm.c.d b/obj/src/mm/pmm.c.d new file mode 100644 index 0000000..1abf9a1 --- /dev/null +++ b/obj/src/mm/pmm.c.d @@ -0,0 +1,9 @@ +obj/src/mm/pmm.c.o: src/mm/pmm.c src/mm/pmm.h src/limine.h src/mm/vmm.h \ + src/mp/spinlock.h src/mm/memory.h src/mm/slab.h src/stdio.h +src/mm/pmm.h: +src/limine.h: +src/mm/vmm.h: +src/mp/spinlock.h: +src/mm/memory.h: +src/mm/slab.h: +src/stdio.h: diff --git a/obj/src/mm/pmm.c.o b/obj/src/mm/pmm.c.o new file mode 100644 index 0000000..5c29f2d Binary files /dev/null and b/obj/src/mm/pmm.c.o differ diff --git a/obj/src/mm/slab.c.d b/obj/src/mm/slab.c.d new file mode 100644 index 0000000..13a1ca2 --- /dev/null +++ b/obj/src/mm/slab.c.d @@ -0,0 +1,11 @@ +obj/src/mm/slab.c.o: src/mm/slab.c src/mm/memory.h src/mm/slab.h \ + src/mp/spinlock.h src/mm/pmm.h src/limine.h src/mm/slab.h src/mm/vmm.h \ + src/stdio.h +src/mm/memory.h: +src/mm/slab.h: +src/mp/spinlock.h: +src/mm/pmm.h: +src/limine.h: +src/mm/slab.h: +src/mm/vmm.h: +src/stdio.h: diff --git a/obj/src/mm/slab.c.o b/obj/src/mm/slab.c.o new file mode 100644 index 0000000..cd27e8d Binary files /dev/null and b/obj/src/mm/slab.c.o differ diff --git a/obj/src/mm/vmm.c.d b/obj/src/mm/vmm.c.d new file mode 100644 index 0000000..f1a6921 --- /dev/null +++ b/obj/src/mm/vmm.c.d @@ -0,0 +1,9 @@ +obj/src/mm/vmm.c.o: src/mm/vmm.c src/mm/vmm.h src/limine.h \ + src/mp/spinlock.h src/mm/pmm.h src/mm/memory.h src/mm/slab.h src/stdio.h +src/mm/vmm.h: +src/limine.h: +src/mp/spinlock.h: +src/mm/pmm.h: +src/mm/memory.h: +src/mm/slab.h: +src/stdio.h: diff --git a/obj/src/mm/vmm.c.o b/obj/src/mm/vmm.c.o new file mode 100644 index 0000000..ef49c39 Binary files /dev/null and b/obj/src/mm/vmm.c.o differ diff --git a/obj/src/mp/mp.c.d b/obj/src/mp/mp.c.d new file mode 100644 index 0000000..ccf32fc --- /dev/null +++ b/obj/src/mp/mp.c.d @@ -0,0 +1,12 @@ +obj/src/mp/mp.c.o: src/mp/mp.c src/mp/mp.h src/mp/percpu.h \ + src/sched/thread.h src/arch/x86_64/gdt.h src/arch/x86_64/lapic.h \ + src/limine.h src/arch/x86_64/idt.h src/mm/memory.h src/stdio.h +src/mp/mp.h: +src/mp/percpu.h: +src/sched/thread.h: +src/arch/x86_64/gdt.h: +src/arch/x86_64/lapic.h: +src/limine.h: +src/arch/x86_64/idt.h: +src/mm/memory.h: +src/stdio.h: diff --git a/obj/src/mp/mp.c.o b/obj/src/mp/mp.c.o new file mode 100644 index 0000000..1cb4578 Binary files /dev/null and b/obj/src/mp/mp.c.o differ diff --git a/obj/src/mp/mp_asm.S.d b/obj/src/mp/mp_asm.S.d new file mode 100644 index 0000000..a3e5028 --- /dev/null +++ b/obj/src/mp/mp_asm.S.d @@ -0,0 +1 @@ +obj/src/mp/mp_asm.S.o: src/mp/mp_asm.S diff --git a/obj/src/mp/mp_asm.S.o b/obj/src/mp/mp_asm.S.o new file mode 100644 index 0000000..e591fbf Binary files /dev/null and b/obj/src/mp/mp_asm.S.o differ diff --git a/obj/src/mp/mutex.c.d b/obj/src/mp/mutex.c.d new file mode 100644 index 0000000..24ab261 --- /dev/null +++ b/obj/src/mp/mutex.c.d @@ -0,0 +1,6 @@ +obj/src/mp/mutex.c.o: src/mp/mutex.c src/mp/mutex.h src/mp/spinlock.h \ + src/sched/scheduler.h src/sched/thread.h +src/mp/mutex.h: +src/mp/spinlock.h: +src/sched/scheduler.h: +src/sched/thread.h: diff --git a/obj/src/mp/mutex.c.o b/obj/src/mp/mutex.c.o new file mode 100644 index 0000000..933d2eb Binary files /dev/null and b/obj/src/mp/mutex.c.o differ diff --git a/obj/src/mp/percpu.c.d b/obj/src/mp/percpu.c.d new file mode 100644 index 0000000..bc6c659 --- /dev/null +++ b/obj/src/mp/percpu.c.d @@ -0,0 +1,5 @@ +obj/src/mp/percpu.c.o: src/mp/percpu.c src/mp/percpu.h src/sched/thread.h \ + src/arch/x86_64/gdt.h +src/mp/percpu.h: +src/sched/thread.h: +src/arch/x86_64/gdt.h: diff --git a/obj/src/mp/percpu.c.o b/obj/src/mp/percpu.c.o new file mode 100644 index 0000000..397bf7e Binary files /dev/null and b/obj/src/mp/percpu.c.o differ diff --git a/obj/src/mp/semaphore.c.d b/obj/src/mp/semaphore.c.d new file mode 100644 index 0000000..680c314 --- /dev/null +++ b/obj/src/mp/semaphore.c.d @@ -0,0 +1,6 @@ +obj/src/mp/semaphore.c.o: src/mp/semaphore.c src/mp/semaphore.h \ + src/mp/spinlock.h src/sched/scheduler.h src/sched/thread.h +src/mp/semaphore.h: +src/mp/spinlock.h: +src/sched/scheduler.h: +src/sched/thread.h: diff --git a/obj/src/mp/semaphore.c.o b/obj/src/mp/semaphore.c.o new file mode 100644 index 0000000..e046a93 Binary files /dev/null and b/obj/src/mp/semaphore.c.o differ diff --git a/obj/src/mp/spinlock.c.d b/obj/src/mp/spinlock.c.d new file mode 100644 index 0000000..4b39d0d --- /dev/null +++ b/obj/src/mp/spinlock.c.d @@ -0,0 +1,2 @@ +obj/src/mp/spinlock.c.o: src/mp/spinlock.c src/mp/spinlock.h +src/mp/spinlock.h: diff --git a/obj/src/mp/spinlock.c.o b/obj/src/mp/spinlock.c.o new file mode 100644 index 0000000..684833c Binary files /dev/null and b/obj/src/mp/spinlock.c.o differ diff --git a/obj/src/sched/context.S.d b/obj/src/sched/context.S.d new file mode 100644 index 0000000..8b8a980 --- /dev/null +++ b/obj/src/sched/context.S.d @@ -0,0 +1 @@ +obj/src/sched/context.S.o: src/sched/context.S diff --git a/obj/src/sched/context.S.o b/obj/src/sched/context.S.o new file mode 100644 index 0000000..3e4f4b4 Binary files /dev/null and b/obj/src/sched/context.S.o differ diff --git a/obj/src/sched/scheduler.c.d b/obj/src/sched/scheduler.c.d new file mode 100644 index 0000000..7545681 --- /dev/null +++ b/obj/src/sched/scheduler.c.d @@ -0,0 +1,9 @@ +obj/src/sched/scheduler.c.o: src/sched/scheduler.c src/sched/scheduler.h \ + src/sched/thread.h src/mp/spinlock.h src/mm/memory.h src/stdio.h \ + src/string.h +src/sched/scheduler.h: +src/sched/thread.h: +src/mp/spinlock.h: +src/mm/memory.h: +src/stdio.h: +src/string.h: diff --git a/obj/src/sched/scheduler.c.o b/obj/src/sched/scheduler.c.o new file mode 100644 index 0000000..b2bd9a5 Binary files /dev/null and b/obj/src/sched/scheduler.c.o differ diff --git a/obj/src/sched/thread.c.d b/obj/src/sched/thread.c.d new file mode 100644 index 0000000..25139f5 --- /dev/null +++ b/obj/src/sched/thread.c.d @@ -0,0 +1,7 @@ +obj/src/sched/thread.c.o: src/sched/thread.c src/sched/thread.h \ + src/sched/scheduler.h src/mm/memory.h src/string.h src/stdio.h +src/sched/thread.h: +src/sched/scheduler.h: +src/mm/memory.h: +src/string.h: +src/stdio.h: diff --git a/obj/src/sched/thread.c.o b/obj/src/sched/thread.c.o new file mode 100644 index 0000000..3886f1f Binary files /dev/null and b/obj/src/sched/thread.c.o differ diff --git a/obj/src/stdio.c.d b/obj/src/stdio.c.d new file mode 100644 index 0000000..84b2fa1 --- /dev/null +++ b/obj/src/stdio.c.d @@ -0,0 +1,7 @@ +obj/src/stdio.c.o: src/stdio.c src/stdio.h src/debug.h src/video/render.h \ + src/arch/x86_64/e9.h src/mp/spinlock.h +src/stdio.h: +src/debug.h: +src/video/render.h: +src/arch/x86_64/e9.h: +src/mp/spinlock.h: diff --git a/obj/src/stdio.c.o b/obj/src/stdio.c.o new file mode 100644 index 0000000..baf4354 Binary files /dev/null and b/obj/src/stdio.c.o differ diff --git a/obj/src/string.c.d b/obj/src/string.c.d new file mode 100644 index 0000000..7cd0498 --- /dev/null +++ b/obj/src/string.c.d @@ -0,0 +1,2 @@ +obj/src/string.c.o: src/string.c src/string.h +src/string.h: diff --git a/obj/src/string.c.o b/obj/src/string.c.o new file mode 100644 index 0000000..8bfda33 Binary files /dev/null and b/obj/src/string.c.o differ diff --git a/obj/src/syscall/syscall.c.d b/obj/src/syscall/syscall.c.d new file mode 100644 index 0000000..a68b70d --- /dev/null +++ b/obj/src/syscall/syscall.c.d @@ -0,0 +1,5 @@ +obj/src/syscall/syscall.c.o: src/syscall/syscall.c src/stdio.h \ + src/fs/vfs.h src/fs/ext2.h +src/stdio.h: +src/fs/vfs.h: +src/fs/ext2.h: diff --git a/obj/src/syscall/syscall.c.o b/obj/src/syscall/syscall.c.o new file mode 100644 index 0000000..684a265 Binary files /dev/null and b/obj/src/syscall/syscall.c.o differ diff --git a/obj/src/syscall/syscall_entry.S.d b/obj/src/syscall/syscall_entry.S.d new file mode 100644 index 0000000..73c129a --- /dev/null +++ b/obj/src/syscall/syscall_entry.S.d @@ -0,0 +1 @@ +obj/src/syscall/syscall_entry.S.o: src/syscall/syscall_entry.S diff --git a/obj/src/syscall/syscall_entry.S.o b/obj/src/syscall/syscall_entry.S.o new file mode 100644 index 0000000..c9f0c37 Binary files /dev/null and b/obj/src/syscall/syscall_entry.S.o differ diff --git a/obj/src/video/render.c.d b/obj/src/video/render.c.d new file mode 100644 index 0000000..c55ebe6 --- /dev/null +++ b/obj/src/video/render.c.d @@ -0,0 +1,6 @@ +obj/src/video/render.c.o: src/video/render.c src/video/font.h \ + src/video/render.h src/mm/memory.h src/mm/slab.h +src/video/font.h: +src/video/render.h: +src/mm/memory.h: +src/mm/slab.h: diff --git a/obj/src/video/render.c.o b/obj/src/video/render.c.o new file mode 100644 index 0000000..6e9796a Binary files /dev/null and b/obj/src/video/render.c.o differ diff --git a/obj/src/video/tga.c.d b/obj/src/video/tga.c.d new file mode 100644 index 0000000..38bb729 --- /dev/null +++ b/obj/src/video/tga.c.d @@ -0,0 +1,3 @@ +obj/src/video/tga.c.o: src/video/tga.c src/mm/memory.h src/mm/slab.h +src/mm/memory.h: +src/mm/slab.h: diff --git a/obj/src/video/tga.c.o b/obj/src/video/tga.c.o new file mode 100644 index 0000000..2965283 Binary files /dev/null and b/obj/src/video/tga.c.o differ diff --git a/src/arch/x86_64/ata.c b/src/arch/x86_64/ata.c new file mode 100644 index 0000000..cf78383 --- /dev/null +++ b/src/arch/x86_64/ata.c @@ -0,0 +1,159 @@ +#include "ata.h" +#include "io.h" // your existing inb/outb/insw +#include "stdio.h" +#include "memory.h" +#include + + + + + +#define ATA_PRIMARY_DATA 0x1F0 +#define ATA_PRIMARY_ERROR 0x1F1 +#define ATA_PRIMARY_SECCOUNT 0x1F2 +#define ATA_PRIMARY_LBALOW 0x1F3 +#define ATA_PRIMARY_LBAMID 0x1F4 +#define ATA_PRIMARY_LBAHIGH 0x1F5 +#define ATA_PRIMARY_DRIVE 0x1F6 +#define ATA_PRIMARY_STATUS 0x1F7 +#define ATA_PRIMARY_COMMAND 0x1F7 + +#define ATA_STATUS_BSY 0x80 +#define ATA_STATUS_DRDY 0x40 +#define ATA_STATUS_DRQ 0x08 +#define ATA_STATUS_ERR 0x01 + +#define ATA_CMD_IDENTIFY 0xEC +#define ATA_CMD_READ_SECTORS 0x20 + +static void ata_wait_ready(void) +{ + while (x86_64_inb(ATA_PRIMARY_STATUS) & ATA_STATUS_BSY) {} + while (!(x86_64_inb(ATA_PRIMARY_STATUS) & ATA_STATUS_DRDY)) {} +} + +static bool ata_poll(void) +{ + // 400 ns delay + for (int i = 0; i < 4; i++) + x86_64_inb(ATA_PRIMARY_STATUS); + + uint8_t status; + + while ((status = x86_64_inb(ATA_PRIMARY_STATUS)) & ATA_STATUS_BSY); + if (status & ATA_STATUS_ERR) return false; + + while (!(status & ATA_STATUS_DRQ)) { + status = x86_64_inb(ATA_PRIMARY_STATUS); + if (status & ATA_STATUS_ERR) return false; + } + + return true; +} + +void ata_init(void) +{ + x86_64_outb(0x3F6, 0x02); // disable interrupts on primary controller + ata_wait_ready(); + x86_64_outb(ATA_PRIMARY_DRIVE, 0xA0); // select master + ata_wait_ready(); + printf("ATA: Primary master (hda) initialized\n"); +} + +void ata_identify(void) +{ + static uint16_t buffer[256]; + + x86_64_outb(ATA_PRIMARY_DRIVE, 0xA0); + x86_64_outb(ATA_PRIMARY_SECCOUNT, 0); + x86_64_outb(ATA_PRIMARY_LBALOW, 0); + x86_64_outb(ATA_PRIMARY_LBAMID, 0); + x86_64_outb(ATA_PRIMARY_LBAHIGH, 0); + x86_64_outb(ATA_PRIMARY_COMMAND, ATA_CMD_IDENTIFY); + + if (x86_64_inb(ATA_PRIMARY_STATUS) == 0) { + printf("ATA: No primary master drive detected\n"); + return; + } + + if (!ata_poll()) { + printf("ATA poll failed at ATA_IDENTIFY\n"); + } + + if (x86_64_inb(ATA_PRIMARY_STATUS) & ATA_STATUS_ERR) { + printf("ATA: Identify error\n"); + return; + } + + x86_64_insw(ATA_PRIMARY_DATA, buffer, 256); + + printf("ATA: Disk model: "); + for (int i = 27; i <= 46; i++) { + uint16_t w = buffer[i]; + char high = w >> 8; + char low = w & 0xFF; + printf("%c%c", high, low); // swap bytes + } + printf("\n"); + printf("ATA: Total sectors: %lu\n", (uint64_t)buffer[60] | ((uint64_t)buffer[61] << 16)); +} + +bool ata_read_sectors(uint64_t lba, uint8_t sector_count, void* buffer) +{ + if (sector_count == 0) return true; + + ata_wait_ready(); + + x86_64_outb(ATA_PRIMARY_DRIVE, 0xE0 | ((lba >> 24) & 0x0F)); + x86_64_outb(ATA_PRIMARY_SECCOUNT, sector_count); + x86_64_outb(ATA_PRIMARY_LBALOW, (uint8_t)lba); + x86_64_outb(ATA_PRIMARY_LBAMID, (uint8_t)(lba >> 8)); + x86_64_outb(ATA_PRIMARY_LBAHIGH, (uint8_t)(lba >> 16)); + + x86_64_outb(ATA_PRIMARY_COMMAND, ATA_CMD_READ_SECTORS); + + uint16_t* buf = buffer; + for (uint8_t i = 0; i < sector_count; i++) { + if (!ata_poll()) { + printf("ATA poll failed at ATA_read_sectors\n"); + } + + if (x86_64_inb(ATA_PRIMARY_STATUS) & ATA_STATUS_ERR) { + printf("ATA read error at LBA %lu\n", lba + i); + return false; + } + + x86_64_insw(ATA_PRIMARY_DATA, buf, 256); // 512 bytes + buf += 256; + } + + return true; +} + +bool ata_write_sectors(uint64_t lba, uint8_t sector_count, const void* buffer) { + if (sector_count == 0) return true; + + + + ata_wait_ready(); + x86_64_outb(ATA_PRIMARY_DRIVE, 0xE0 | ((lba >> 24) & 0x0F)); + x86_64_outb(ATA_PRIMARY_SECCOUNT, sector_count); + x86_64_outb(ATA_PRIMARY_LBALOW, (uint8_t)lba); + x86_64_outb(ATA_PRIMARY_LBAMID, (uint8_t)(lba >> 8)); + x86_64_outb(ATA_PRIMARY_LBAHIGH, (uint8_t)(lba >> 16)); + x86_64_outb(ATA_PRIMARY_COMMAND, 0x30); // write sectors + + const uint16_t* buf = buffer; + for (uint8_t i = 0; i < sector_count; i++) { + if (!ata_poll()) { + + return false; + } + x86_64_outsw(ATA_PRIMARY_DATA, buf, 256); + buf += 256; + } + + + + return true; +} diff --git a/src/arch/x86_64/ata.h b/src/arch/x86_64/ata.h new file mode 100644 index 0000000..a6f1b82 --- /dev/null +++ b/src/arch/x86_64/ata.h @@ -0,0 +1,13 @@ +#pragma once + +#include +#include + +void ata_init(void); +void ata_identify(void); + +// Read `sector_count` 512-byte sectors starting at LBA `lba` into `buffer`. +// Buffer must be large enough (sector_count * 512). +bool ata_read_sectors(uint64_t lba, uint8_t sector_count, void* buffer); + +bool ata_write_sectors(uint64_t lba, uint8_t sector_count, const void* buffer); \ No newline at end of file diff --git a/src/arch/x86_64/e9.c b/src/arch/x86_64/e9.c new file mode 100644 index 0000000..ec5ee00 --- /dev/null +++ b/src/arch/x86_64/e9.c @@ -0,0 +1,13 @@ +#include "e9.h" +#include + +void e9_putc(char c) +{ + x86_64_outb(0xE9, c); +} + +void e9_puts(const char* str) { + while (*str) { + e9_putc(*str++); + } +} \ No newline at end of file diff --git a/src/arch/x86_64/e9.h b/src/arch/x86_64/e9.h new file mode 100644 index 0000000..ba125a9 --- /dev/null +++ b/src/arch/x86_64/e9.h @@ -0,0 +1,3 @@ +#pragma once + +void e9_putc(char c); \ No newline at end of file diff --git a/src/arch/x86_64/gdt.c b/src/arch/x86_64/gdt.c new file mode 100644 index 0000000..7610028 --- /dev/null +++ b/src/arch/x86_64/gdt.c @@ -0,0 +1,88 @@ +#include "gdt.h" +#include "mm/memory.h" +#include "mp/spinlock.h" +#include + + + +struct gdt_desc { + uint16_t limit; + uint16_t base_low; + uint8_t base_mid; + uint8_t access; + uint8_t granularity; + uint8_t base_hi; +} __attribute__((packed)); + +struct tss_desc { + uint16_t length; + uint16_t base_low; + uint8_t base_mid; + uint8_t flags1; + uint8_t flags2; + uint8_t base_hi; + uint32_t base_upper32; + uint32_t reserved; +} __attribute__((packed)); + +struct gdt_ptr { + uint16_t limit; + uint64_t ptr; +} __attribute__((packed)); + +struct gdtr { + struct gdt_desc entries[5]; + struct tss_desc tss; +} __attribute__((packed)); + +struct gdtr gdt = {0}; +struct gdt_ptr gdt_pointer = {0}; +struct tss kernel_tss = {0}; +spinlock_t s_gdt_lock = SPINLOCK_INIT; + +extern void gdt_reload(void); +extern void tss_reload(void); + + +void x86_64_GDT_Initialize(void) { + uint64_t flags; + spinlock_acquire_irqsave(&s_gdt_lock, &flags); + // Kernel code + gdt.entries[1].access = 0b10011010; + gdt.entries[1].granularity = 0b00100000; + + // Kernel data + gdt.entries[2].access = 0b10010010; + + // User data + gdt.entries[3].access = 0b11110010; + + // User code + gdt.entries[4].access = 0b11111010; + gdt.entries[4].granularity = 0b00100000; + + // TSS + gdt.tss.length = sizeof(struct tss); + gdt.tss.flags1 = 0b10001001; + + // Set the pointer + gdt_pointer.limit = sizeof(gdt) - 1; + gdt_pointer.ptr = (uint64_t)&gdt; + + gdt_reload(); + tss_reload(); + spinlock_release_irqrestore(&s_gdt_lock, flags); +} + +void gdt_load_tss(size_t addr) { + uint64_t flags; + spinlock_acquire_irqsave(&s_gdt_lock, &flags); + gdt.tss.base_low = (uint16_t)addr; + gdt.tss.base_mid = (uint8_t)(addr >> 16); + gdt.tss.flags1 = 0b10001001; + gdt.tss.base_hi = (uint8_t)(addr >> 24); + gdt.tss.base_upper32 = (uint32_t)(addr >> 32); + + tss_reload(); + spinlock_release_irqrestore(&s_gdt_lock, flags); +} diff --git a/src/arch/x86_64/gdt.h b/src/arch/x86_64/gdt.h new file mode 100644 index 0000000..d94d59e --- /dev/null +++ b/src/arch/x86_64/gdt.h @@ -0,0 +1,34 @@ +#pragma once +#include +#include + + + +#define GDT_KERNEL_BASE 0x0 +#define GDT_KERNEL_CODE64 0x8 +#define GDT_KERNEL_DATA64 0x10 +#define GDT_USER_BASE 0x18 +#define GDT_USER_DATA64 0x18 +#define GDT_USER_CODE64 0x20 +#define GDT_TSS 0x28 + +struct tss { + uint32_t reserved; + uint64_t rsp0; + uint64_t rsp1; + uint64_t rsp2; + uint64_t reserved2; + uint64_t ist1; + uint64_t ist2; + uint64_t ist3; + uint64_t ist4; + uint64_t ist5; + uint64_t ist6; + uint64_t ist7; + uint64_t reserved3; + uint16_t reserved4; + uint16_t iomap_base; +} __attribute__((packed)); + +void x86_64_GDT_Initialize(void); +void gdt_load_tss(size_t addr); \ No newline at end of file diff --git a/src/arch/x86_64/gdt_asm.S b/src/arch/x86_64/gdt_asm.S new file mode 100644 index 0000000..c73ea11 --- /dev/null +++ b/src/arch/x86_64/gdt_asm.S @@ -0,0 +1,27 @@ +.intel_syntax noprefix +.global x86_64_GDT_Load +.extern gdt_pointer + +.global gdt_reload +gdt_reload: + lgdt [rip + gdt_pointer] + + push 8 + lea rax, [rip + .flush] + push rax + lretq + +.flush: + mov eax, 0x10 + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + mov ss, ax + ret + +.global tss_reload +tss_reload: + mov ax, 0x2B + ltr ax + ret \ No newline at end of file diff --git a/src/arch/x86_64/i8259.c b/src/arch/x86_64/i8259.c new file mode 100644 index 0000000..a5a7d9b --- /dev/null +++ b/src/arch/x86_64/i8259.c @@ -0,0 +1,167 @@ +#include "pic.h" +#include "io.h" +#include +#include + +#define PIC1_COMMAND_PORT 0x20 +#define PIC1_DATA_PORT 0x21 +#define PIC2_COMMAND_PORT 0xA0 +#define PIC2_DATA_PORT 0xA1 + +// Initialization Control Word 1 +// ----------------------------- +// 0 IC4 if set, the PIC expects to receive ICW4 during initialization +// 1 SGNL if set, only 1 PIC in the system; if unset, the PIC is cascaded with slave PICs +// and ICW3 must be sent to controller +// 2 ADI call address interval, set: 4, not set: 8; ignored on x86, set to 0 +// 3 LTIM if set, operate in level triggered mode; if unset, operate in edge triggered mode +// 4 INIT set to 1 to initialize PIC +// 5-7 ignored on x86, set to 0 + +enum { + PIC_ICW1_ICW4 = 0x01, + PIC_ICW1_SINGLE = 0x02, + PIC_ICW1_INTERVAL4 = 0x04, + PIC_ICW1_LEVEL = 0x08, + PIC_ICW1_INITIALIZE = 0x10 +} PIC_ICW1; + + +// Initialization Control Word 4 +// ----------------------------- +// 0 uPM if set, PIC is in 80x86 mode; if cleared, in MCS-80/85 mode +// 1 AEOI if set, on last interrupt acknowledge pulse, controller automatically performs +// end of interrupt operation +// 2 M/S only use if BUF is set; if set, selects buffer master; otherwise, selects buffer slave +// 3 BUF if set, controller operates in buffered mode +// 4 SFNM specially fully nested mode; used in systems with large number of cascaded controllers +// 5-7 reserved, set to 0 +enum { + PIC_ICW4_8086 = 0x1, + PIC_ICW4_AUTO_EOI = 0x2, + PIC_ICW4_BUFFER_MASTER = 0x4, + PIC_ICW4_BUFFER_SLAVE = 0x0, + PIC_ICW4_BUFFERRED = 0x8, + PIC_ICW4_SFNM = 0x10, +} PIC_ICW4; + + +enum { + PIC_CMD_END_OF_INTERRUPT = 0x20, + PIC_CMD_READ_IRR = 0x0A, + PIC_CMD_READ_ISR = 0x0B, +} PIC_CMD; + + +static uint16_t g_PicMask = 0xffff; +static bool g_AutoEoi = false; + +void i8259_SetMask(uint16_t newMask) +{ + g_PicMask = newMask; + x86_64_outb(PIC1_DATA_PORT, g_PicMask & 0xFF); + x86_64_iowait(); + x86_64_outb(PIC2_DATA_PORT, g_PicMask >> 8); + x86_64_iowait(); +} + +uint16_t i8259_GetMask() +{ + return x86_64_inb(PIC1_DATA_PORT) | (x86_64_inb(PIC2_DATA_PORT) << 8); +} + +void i8259_Configure(uint8_t offsetPic1, uint8_t offsetPic2, bool autoEoi) +{ + // Mask everything + i8259_SetMask(0xFFFF); + + // initialization control word 1 + x86_64_outb(PIC1_COMMAND_PORT, PIC_ICW1_ICW4 | PIC_ICW1_INITIALIZE); + x86_64_iowait(); + x86_64_outb(PIC2_COMMAND_PORT, PIC_ICW1_ICW4 | PIC_ICW1_INITIALIZE); + x86_64_iowait(); + + // initialization control word 2 - the offsets + x86_64_outb(PIC1_DATA_PORT, offsetPic1); + x86_64_iowait(); + x86_64_outb(PIC2_DATA_PORT, offsetPic2); + x86_64_iowait(); + + // initialization control word 3 + x86_64_outb(PIC1_DATA_PORT, 0x4); // tell PIC1 that it has a slave at IRQ2 (0000 0100) + x86_64_iowait(); + x86_64_outb(PIC2_DATA_PORT, 0x2); // tell PIC2 its cascade identity (0000 0010) + x86_64_iowait(); + + // initialization control word 4 + uint8_t icw4 = PIC_ICW4_8086; + if (autoEoi) { + icw4 |= PIC_ICW4_AUTO_EOI; + } + + x86_64_outb(PIC1_DATA_PORT, icw4); + x86_64_iowait(); + x86_64_outb(PIC2_DATA_PORT, icw4); + x86_64_iowait(); + + // mask all interrupts until they are enabled by the device driver + i8259_SetMask(0xFFFF); +} + +void i8259_SendEndOfInterrupt(int irq) +{ + if (irq >= 8) + x86_64_outb(PIC2_COMMAND_PORT, PIC_CMD_END_OF_INTERRUPT); + x86_64_outb(PIC1_COMMAND_PORT, PIC_CMD_END_OF_INTERRUPT); +} + +void i8259_Disable() +{ + i8259_SetMask(0xFFFF); +} + +void i8259_Mask(int irq) +{ + i8259_SetMask(g_PicMask | (1 << irq)); +} + +void i8259_Unmask(int irq) +{ + i8259_SetMask(g_PicMask & ~(1 << irq)); +} + +uint16_t i8259_ReadIrqRequestRegister() +{ + x86_64_outb(PIC1_COMMAND_PORT, PIC_CMD_READ_IRR); + x86_64_outb(PIC2_COMMAND_PORT, PIC_CMD_READ_IRR); + return ((uint16_t)x86_64_inb(PIC2_COMMAND_PORT)) | (((uint16_t)x86_64_inb(PIC2_COMMAND_PORT)) << 8); +} + +uint16_t i8259_ReadInServiceRegister() +{ + x86_64_outb(PIC1_COMMAND_PORT, PIC_CMD_READ_ISR); + x86_64_outb(PIC2_COMMAND_PORT, PIC_CMD_READ_ISR); + return ((uint16_t)x86_64_inb(PIC2_COMMAND_PORT)) | (((uint16_t)x86_64_inb(PIC2_COMMAND_PORT)) << 8); +} + +bool i8259_Probe() +{ + i8259_Disable(); + i8259_SetMask(0x1337); + return i8259_GetMask() == 0x1337; +} + +static const PICDriver g_PicDriver = { + .Name = "8259 PIC", + .Probe = &i8259_Probe, + .Initialize = &i8259_Configure, + .Disable = &i8259_Disable, + .SendEndOfInterrupt = &i8259_SendEndOfInterrupt, + .Mask = &i8259_Mask, + .Unmask = &i8259_Unmask, +}; + +const PICDriver* i8259_GetDriver() +{ + return &g_PicDriver; +} \ No newline at end of file diff --git a/src/arch/x86_64/i8259.h b/src/arch/x86_64/i8259.h new file mode 100644 index 0000000..ef6748b --- /dev/null +++ b/src/arch/x86_64/i8259.h @@ -0,0 +1,9 @@ +#pragma once + +#include "pic.h" + +const PICDriver* i8259_GetDriver(); +uint16_t i8259_GetMask(); +void i8259_SetMask(uint16_t newMask); + +void i8259_Configure(uint8_t offsetPic1, uint8_t offsetPic2, bool autoEoi); \ No newline at end of file diff --git a/src/arch/x86_64/idt.c b/src/arch/x86_64/idt.c new file mode 100644 index 0000000..0aedfc5 --- /dev/null +++ b/src/arch/x86_64/idt.c @@ -0,0 +1,35 @@ +#include "idt.h" +#include "util/binary.h" + + +IDTEntry g_IDT[256]; +IDTDescriptor g_IDTDescriptor = { sizeof(g_IDT) - 1, g_IDT }; + +extern void x86_64_IDT_Load(IDTDescriptor* descriptor); + +void x86_64_IDT_SetGate(int interrupt, void* base, uint16_t segmentDescriptor, uint8_t flags) +{ + uintptr_t addr = (uintptr_t)base; + g_IDT[interrupt].BaseLow = addr & 0xFFFF; + g_IDT[interrupt].SegmentSelector = segmentDescriptor; + g_IDT[interrupt].IST = 0; + g_IDT[interrupt].Flags = flags; + g_IDT[interrupt].BaseMid = (addr >> 16) & 0xFFFF; + g_IDT[interrupt].BaseHigh = (addr >> 32) & 0xFFFFFFFF; + g_IDT[interrupt].Reserved = 0; +} +void x86_64_IDT_EnableGate(int interrupt) +{ + FLAG_SET(g_IDT[interrupt].Flags, IDT_FLAG_PRESENT); +} + +void x86_64_IDT_DisableGate(int interrupt) +{ + FLAG_UNSET(g_IDT[interrupt].Flags, IDT_FLAG_PRESENT); +} + + +void x86_64_IDT_Initialize(void) +{ + x86_64_IDT_Load(&g_IDTDescriptor); +} \ No newline at end of file diff --git a/src/arch/x86_64/idt.h b/src/arch/x86_64/idt.h new file mode 100644 index 0000000..c033f0a --- /dev/null +++ b/src/arch/x86_64/idt.h @@ -0,0 +1,44 @@ +#pragma once +#include + + + +typedef enum +{ + IDT_FLAG_GATE_TASK = 0x5, + IDT_FLAG_GATE_16BIT_INT = 0x6, + IDT_FLAG_GATE_16BIT_TRAP = 0x7, + IDT_FLAG_GATE_32BIT_INT = 0xE, + IDT_FLAG_GATE_32BIT_TRAP = 0xF, + + IDT_FLAG_RING0 = (0 << 5), + IDT_FLAG_RING1 = (1 << 5), + IDT_FLAG_RING2 = (2 << 5), + IDT_FLAG_RING3 = (3 << 5), + + IDT_FLAG_PRESENT = 0x80, + +} IDT_FLAGS; + +typedef struct +{ + uint16_t BaseLow; + uint16_t SegmentSelector; + uint8_t IST; // Interrupt Stack Table (0 = default) + uint8_t Flags; + uint16_t BaseMid; + uint32_t BaseHigh; + uint32_t Reserved; +} __attribute__((packed)) IDTEntry; + +typedef struct +{ + uint16_t Limit; + IDTEntry* Ptr; +} __attribute__((packed)) IDTDescriptor; + + +void x86_64_IDT_Initialize(void); +void x86_64_IDT_SetGate(int interrupt, void* base, uint16_t segmentDescriptor, uint8_t flags); +void x86_64_IDT_EnableGate(int interrupt); +void x86_64_IDT_DisableGate(int interrupt); \ No newline at end of file diff --git a/src/arch/x86_64/idt_asm.S b/src/arch/x86_64/idt_asm.S new file mode 100644 index 0000000..574134c --- /dev/null +++ b/src/arch/x86_64/idt_asm.S @@ -0,0 +1,6 @@ +.intel_syntax noprefix +.global x86_64_IDT_Load + +x86_64_IDT_Load: + lidt [rdi] # descriptor in RDI + ret \ No newline at end of file diff --git a/src/arch/x86_64/io.h b/src/arch/x86_64/io.h new file mode 100644 index 0000000..39b64f0 --- /dev/null +++ b/src/arch/x86_64/io.h @@ -0,0 +1,16 @@ +#pragma once +#include + +void x86_64_outb(uint16_t port, uint8_t value); +uint8_t x86_64_inb(uint16_t port); +uint16_t x86_64_inw(uint16_t port); +void x86_64_outw(uint16_t port, uint16_t value); +void x86_64_insw(uint16_t port, uint16_t* buffer, uint32_t count); +void x86_64_outl(uint16_t port, uint32_t value); +uint32_t x86_64_inl(uint16_t port); +void x86_64_outsw(uint16_t port, uint16_t* buffer, uint32_t count); +void x86_64_iowait(void); +void x86_64_Panic(void) __attribute__((noreturn)); +void x86_64_EnableInterrupts(void); +void x86_64_DisableInterrupts(void); +void x86_64_crashme(void); \ No newline at end of file diff --git a/src/arch/x86_64/io_asm.S b/src/arch/x86_64/io_asm.S new file mode 100644 index 0000000..be7eb23 --- /dev/null +++ b/src/arch/x86_64/io_asm.S @@ -0,0 +1,96 @@ +.intel_syntax noprefix + +.global x86_64_outb +x86_64_outb: + mov dx, di + mov al, sil + out dx, al + ret + +.global x86_64_inb +x86_64_inb: + mov dx, di + xor eax, eax + in al, dx + ret + +.global x86_64_inw +x86_64_inw: + mov dx, di + xor eax, eax + in ax, dx + ret + +.global x86_64_outw +x86_64_outw: + mov dx, di + mov ax, si + out dx, ax + ret + +.global x86_64_outl +x86_64_outl: + mov dx, di + mov eax, esi + out dx, eax + ret + +.global x86_64_inl +x86_64_inl: + mov dx, di + xor eax, eax + in eax, dx + ret + +.global x86_64_insw +x86_64_insw: + test rdx, rdx + jz .inswdone + mov rcx, rdx + mov dx, di + mov rdi, rsi + cld + rep insw +.inswdone: + ret + +.global x86_64_outsw +x86_64_outsw: + test rdx, rdx + jz .outswdone + mov rcx, rdx + mov dx, di + mov rsi, rsi + cld + rep outsw +.outswdone: + ret + +.global x86_64_Panic +x86_64_Panic: + cli + hlt +1: jmp 1b + +.global x86_64_EnableInterrupts +x86_64_EnableInterrupts: + sti + ret + +.global x86_64_DisableInterrupts +x86_64_DisableInterrupts: + cli + ret + +.global x86_64_iowait +x86_64_iowait: + out 0x80, al // classic I/O wait + ret + +.global x86_64_crashme +x86_64_crashme: + xor rdx, rdx + mov rax, 1 + mov rbx, 0 + div rbx + ret \ No newline at end of file diff --git a/src/arch/x86_64/irq.c b/src/arch/x86_64/irq.c new file mode 100644 index 0000000..6416eb6 --- /dev/null +++ b/src/arch/x86_64/irq.c @@ -0,0 +1,65 @@ +#include "irq.h" +#include "i8259.h" +#include "io.h" +#include +#include +#include "stdio.h" +#include + +#define PIC_REMAP_OFFSET 0x20 +#define MODULE "PIC" + +IRQHandler g_IRQHandlers[16]; +static const PICDriver* g_Driver = NULL; + +void x86_64_IRQ_Handler(Registers *regs) +{ + int irq = regs->interrupt - PIC_REMAP_OFFSET; + + if (g_IRQHandlers[irq] != NULL) + { + // handle IRQ + g_IRQHandlers[irq](regs); + } + else + { + log_warn(MODULE, "Unhandled IRQ %d...", irq); + } + + // send EOI + g_Driver->SendEndOfInterrupt(irq); + +} + + +void x86_64_IRQ_Initialize(void) +{ + const PICDriver* drivers[] = { + i8259_GetDriver(), + }; + + for (int i = 0; i < SIZE(drivers); i++) { + if (drivers[i]->Probe()) { + g_Driver = drivers[i]; + } + } + + if (g_Driver == NULL) { + log_warn(MODULE, "No PIC found!"); + return; + } + + log_info(MODULE, "Found %s PIC.", g_Driver->Name); + g_Driver->Initialize(PIC_REMAP_OFFSET, PIC_REMAP_OFFSET + 8, false); + + // register ISR handlers for each of the 16 irq lines + for (int i = 0; i < 16; i++) + x86_64_ISR_RegisterHandler(PIC_REMAP_OFFSET + i, x86_64_IRQ_Handler); + + x86_64_EnableInterrupts(); +} + +void x86_64_IRQ_RegisterHandler(int irq, IRQHandler handler) +{ + g_IRQHandlers[irq] = handler; +} \ No newline at end of file diff --git a/src/arch/x86_64/irq.h b/src/arch/x86_64/irq.h new file mode 100644 index 0000000..ea5e046 --- /dev/null +++ b/src/arch/x86_64/irq.h @@ -0,0 +1,8 @@ +#pragma once +#include "isr.h" + + +typedef void (*IRQHandler)(Registers* regs); + +void x86_64_IRQ_Initialize(); +void x86_64_IRQ_RegisterHandler(int irq, IRQHandler handler); \ No newline at end of file diff --git a/src/arch/x86_64/isr.c b/src/arch/x86_64/isr.c new file mode 100644 index 0000000..daa2623 --- /dev/null +++ b/src/arch/x86_64/isr.c @@ -0,0 +1,82 @@ +// ... includes ... +#include "io.h" +#include "debug.h" +#include "arch/x86_64/isr.h" +#include "idt.h" +#define MODULE "ISR" + + +ISRHandler g_ISRHandlers[256]; +static const char* const g_Exceptions[] = { + "Divide by zero error", + "Debug", + "Non-maskable Interrupt", + "Breakpoint", + "Overflow", + "Bound Range Exceeded", + "Invalid Opcode", + "Device Not Available", + "Double Fault", + "Coprocessor Segment Overrun", + "Invalid TSS", + "Segment Not Present", + "Stack-Segment Fault", + "General Protection Fault", + "Page Fault", + "", + "x87 Floating-Point Exception", + "Alignment Check", + "Machine Check", + "SIMD Floating-Point Exception", + "Virtualization Exception", + "Control Protection Exception ", + "", + "", + "", + "", + "", + "", + "Hypervisor Injection Exception", + "VMM Communication Exception", + "Security Exception", + "" +}; + +extern void x86_64_ISR_InitializeGates(void); // defined in isrs_gen.c + +void x86_64_ISR_Initialize(void) +{ + x86_64_ISR_InitializeGates(); + for (int i = 0; i < 256; i++) + x86_64_IDT_EnableGate(i); + x86_64_IDT_DisableGate(0x80); // syscall gate if you want +} + +void __attribute__((used)) x86_64_ISR_Handler(Registers* regs) +{ + if (g_ISRHandlers[regs->interrupt]) + g_ISRHandlers[regs->interrupt](regs); + else if (regs->interrupt >= 32) + log_err(MODULE, "Unhandled interrupt %d!", regs->interrupt); + else { + // panic log (use regs->rax etc. now) + log_crit(MODULE, "KERNEL PANIC! Exception %d (%s)", regs->interrupt, g_Exceptions[regs->interrupt]); + // ... print registers with rax/rbx etc. ... + log_crit(MODULE, " rax=%x rbx=%x rcx=%x rdx=%x rsi=%x rdi=%x", + regs->rax, regs->rbx, regs->rcx, regs->rdx, regs->rsi, regs->rdi); + + log_crit(MODULE, " rsp=%x rbp=%x rip=%x rflags=%x cs=%x ss=%x", + regs->rsp, regs->rbp, regs->rip, regs->rflags, regs->cs, regs->ss); + + log_crit(MODULE, " interrupt=%x errorcode=%x", regs->interrupt, regs->error); + + log_crit(MODULE, "KERNEL PANIC!"); + x86_64_Panic(); + } +} + +void x86_64_ISR_RegisterHandler(int interrupt, ISRHandler handler) +{ + g_ISRHandlers[interrupt] = handler; + x86_64_IDT_EnableGate(interrupt); +} \ No newline at end of file diff --git a/src/arch/x86_64/isr.h b/src/arch/x86_64/isr.h new file mode 100644 index 0000000..f12ea68 --- /dev/null +++ b/src/arch/x86_64/isr.h @@ -0,0 +1,15 @@ +#pragma once +#include + +typedef struct +{ + uint64_t r15, r14, r13, r12, r11, r10, r9, r8; + uint64_t rdi, rsi, rbp, rdx, rcx, rbx, rax; + uint64_t interrupt, error; + uint64_t rip, cs, rflags, rsp, ss; +} __attribute__((packed)) Registers; + +typedef void (*ISRHandler)(Registers* regs); + +void x86_64_ISR_Initialize(void); +void x86_64_ISR_RegisterHandler(int interrupt, ISRHandler handler); \ No newline at end of file diff --git a/src/arch/x86_64/isr_asm.S b/src/arch/x86_64/isr_asm.S new file mode 100644 index 0000000..e6ce249 --- /dev/null +++ b/src/arch/x86_64/isr_asm.S @@ -0,0 +1,58 @@ +.intel_syntax noprefix +.extern x86_64_ISR_Handler + +.macro ISR_NOERRORCODE num + .global x86_64_ISR\num +x86_64_ISR\num: + push 0 + push \num + jmp isr_common +.endm + +.macro ISR_ERRORCODE num + .global x86_64_ISR\num +x86_64_ISR\num: + push \num + jmp isr_common +.endm + +.include "arch/x86_64/isrs_gen.inc" // ← update path if needed + +isr_common: + push rax + push rbx + push rcx + push rdx + push rbp + push rsi + push rdi + push r8 + push r9 + push r10 + push r11 + push r12 + push r13 + push r14 + push r15 + + mov rdi, rsp // Registers* in RDI + call x86_64_ISR_Handler + + pop r15 + pop r14 + pop r13 + pop r12 + pop r11 + pop r10 + pop r9 + pop r8 + pop rdi + pop rsi + pop rbp + pop rdx + pop rcx + pop rbx + pop rax + + add rsp, 16 // pop interrupt + error code + iretq \ No newline at end of file diff --git a/src/arch/x86_64/isrs_gen.c b/src/arch/x86_64/isrs_gen.c new file mode 100644 index 0000000..82f3a07 --- /dev/null +++ b/src/arch/x86_64/isrs_gen.c @@ -0,0 +1,520 @@ +// !!! THIS FILE IS AUTOGENERATED !!! +#include "idt.h" +#include "gdt.h" + +void x86_64_ISR0(); +void x86_64_ISR1(); +void x86_64_ISR2(); +void x86_64_ISR3(); +void x86_64_ISR4(); +void x86_64_ISR5(); +void x86_64_ISR6(); +void x86_64_ISR7(); +void x86_64_ISR8(); +void x86_64_ISR9(); +void x86_64_ISR10(); +void x86_64_ISR11(); +void x86_64_ISR12(); +void x86_64_ISR13(); +void x86_64_ISR14(); +void x86_64_ISR15(); +void x86_64_ISR16(); +void x86_64_ISR17(); +void x86_64_ISR18(); +void x86_64_ISR19(); +void x86_64_ISR20(); +void x86_64_ISR21(); +void x86_64_ISR22(); +void x86_64_ISR23(); +void x86_64_ISR24(); +void x86_64_ISR25(); +void x86_64_ISR26(); +void x86_64_ISR27(); +void x86_64_ISR28(); +void x86_64_ISR29(); +void x86_64_ISR30(); +void x86_64_ISR31(); +void x86_64_ISR32(); +void x86_64_ISR33(); +void x86_64_ISR34(); +void x86_64_ISR35(); +void x86_64_ISR36(); +void x86_64_ISR37(); +void x86_64_ISR38(); +void x86_64_ISR39(); +void x86_64_ISR40(); +void x86_64_ISR41(); +void x86_64_ISR42(); +void x86_64_ISR43(); +void x86_64_ISR44(); +void x86_64_ISR45(); +void x86_64_ISR46(); +void x86_64_ISR47(); +void x86_64_ISR48(); +void x86_64_ISR49(); +void x86_64_ISR50(); +void x86_64_ISR51(); +void x86_64_ISR52(); +void x86_64_ISR53(); +void x86_64_ISR54(); +void x86_64_ISR55(); +void x86_64_ISR56(); +void x86_64_ISR57(); +void x86_64_ISR58(); +void x86_64_ISR59(); +void x86_64_ISR60(); +void x86_64_ISR61(); +void x86_64_ISR62(); +void x86_64_ISR63(); +void x86_64_ISR64(); +void x86_64_ISR65(); +void x86_64_ISR66(); +void x86_64_ISR67(); +void x86_64_ISR68(); +void x86_64_ISR69(); +void x86_64_ISR70(); +void x86_64_ISR71(); +void x86_64_ISR72(); +void x86_64_ISR73(); +void x86_64_ISR74(); +void x86_64_ISR75(); +void x86_64_ISR76(); +void x86_64_ISR77(); +void x86_64_ISR78(); +void x86_64_ISR79(); +void x86_64_ISR80(); +void x86_64_ISR81(); +void x86_64_ISR82(); +void x86_64_ISR83(); +void x86_64_ISR84(); +void x86_64_ISR85(); +void x86_64_ISR86(); +void x86_64_ISR87(); +void x86_64_ISR88(); +void x86_64_ISR89(); +void x86_64_ISR90(); +void x86_64_ISR91(); +void x86_64_ISR92(); +void x86_64_ISR93(); +void x86_64_ISR94(); +void x86_64_ISR95(); +void x86_64_ISR96(); +void x86_64_ISR97(); +void x86_64_ISR98(); +void x86_64_ISR99(); +void x86_64_ISR100(); +void x86_64_ISR101(); +void x86_64_ISR102(); +void x86_64_ISR103(); +void x86_64_ISR104(); +void x86_64_ISR105(); +void x86_64_ISR106(); +void x86_64_ISR107(); +void x86_64_ISR108(); +void x86_64_ISR109(); +void x86_64_ISR110(); +void x86_64_ISR111(); +void x86_64_ISR112(); +void x86_64_ISR113(); +void x86_64_ISR114(); +void x86_64_ISR115(); +void x86_64_ISR116(); +void x86_64_ISR117(); +void x86_64_ISR118(); +void x86_64_ISR119(); +void x86_64_ISR120(); +void x86_64_ISR121(); +void x86_64_ISR122(); +void x86_64_ISR123(); +void x86_64_ISR124(); +void x86_64_ISR125(); +void x86_64_ISR126(); +void x86_64_ISR127(); +void x86_64_ISR128(); +void x86_64_ISR129(); +void x86_64_ISR130(); +void x86_64_ISR131(); +void x86_64_ISR132(); +void x86_64_ISR133(); +void x86_64_ISR134(); +void x86_64_ISR135(); +void x86_64_ISR136(); +void x86_64_ISR137(); +void x86_64_ISR138(); +void x86_64_ISR139(); +void x86_64_ISR140(); +void x86_64_ISR141(); +void x86_64_ISR142(); +void x86_64_ISR143(); +void x86_64_ISR144(); +void x86_64_ISR145(); +void x86_64_ISR146(); +void x86_64_ISR147(); +void x86_64_ISR148(); +void x86_64_ISR149(); +void x86_64_ISR150(); +void x86_64_ISR151(); +void x86_64_ISR152(); +void x86_64_ISR153(); +void x86_64_ISR154(); +void x86_64_ISR155(); +void x86_64_ISR156(); +void x86_64_ISR157(); +void x86_64_ISR158(); +void x86_64_ISR159(); +void x86_64_ISR160(); +void x86_64_ISR161(); +void x86_64_ISR162(); +void x86_64_ISR163(); +void x86_64_ISR164(); +void x86_64_ISR165(); +void x86_64_ISR166(); +void x86_64_ISR167(); +void x86_64_ISR168(); +void x86_64_ISR169(); +void x86_64_ISR170(); +void x86_64_ISR171(); +void x86_64_ISR172(); +void x86_64_ISR173(); +void x86_64_ISR174(); +void x86_64_ISR175(); +void x86_64_ISR176(); +void x86_64_ISR177(); +void x86_64_ISR178(); +void x86_64_ISR179(); +void x86_64_ISR180(); +void x86_64_ISR181(); +void x86_64_ISR182(); +void x86_64_ISR183(); +void x86_64_ISR184(); +void x86_64_ISR185(); +void x86_64_ISR186(); +void x86_64_ISR187(); +void x86_64_ISR188(); +void x86_64_ISR189(); +void x86_64_ISR190(); +void x86_64_ISR191(); +void x86_64_ISR192(); +void x86_64_ISR193(); +void x86_64_ISR194(); +void x86_64_ISR195(); +void x86_64_ISR196(); +void x86_64_ISR197(); +void x86_64_ISR198(); +void x86_64_ISR199(); +void x86_64_ISR200(); +void x86_64_ISR201(); +void x86_64_ISR202(); +void x86_64_ISR203(); +void x86_64_ISR204(); +void x86_64_ISR205(); +void x86_64_ISR206(); +void x86_64_ISR207(); +void x86_64_ISR208(); +void x86_64_ISR209(); +void x86_64_ISR210(); +void x86_64_ISR211(); +void x86_64_ISR212(); +void x86_64_ISR213(); +void x86_64_ISR214(); +void x86_64_ISR215(); +void x86_64_ISR216(); +void x86_64_ISR217(); +void x86_64_ISR218(); +void x86_64_ISR219(); +void x86_64_ISR220(); +void x86_64_ISR221(); +void x86_64_ISR222(); +void x86_64_ISR223(); +void x86_64_ISR224(); +void x86_64_ISR225(); +void x86_64_ISR226(); +void x86_64_ISR227(); +void x86_64_ISR228(); +void x86_64_ISR229(); +void x86_64_ISR230(); +void x86_64_ISR231(); +void x86_64_ISR232(); +void x86_64_ISR233(); +void x86_64_ISR234(); +void x86_64_ISR235(); +void x86_64_ISR236(); +void x86_64_ISR237(); +void x86_64_ISR238(); +void x86_64_ISR239(); +void x86_64_ISR240(); +void x86_64_ISR241(); +void x86_64_ISR242(); +void x86_64_ISR243(); +void x86_64_ISR244(); +void x86_64_ISR245(); +void x86_64_ISR246(); +void x86_64_ISR247(); +void x86_64_ISR248(); +void x86_64_ISR249(); +void x86_64_ISR250(); +void x86_64_ISR251(); +void x86_64_ISR252(); +void x86_64_ISR253(); +void x86_64_ISR254(); +void x86_64_ISR255(); + +void x86_64_ISR_InitializeGates() +{ + x86_64_IDT_SetGate(0, x86_64_ISR0, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(1, x86_64_ISR1, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(2, x86_64_ISR2, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(3, x86_64_ISR3, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(4, x86_64_ISR4, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(5, x86_64_ISR5, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(6, x86_64_ISR6, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(7, x86_64_ISR7, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(8, x86_64_ISR8, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(9, x86_64_ISR9, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(10, x86_64_ISR10, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(11, x86_64_ISR11, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(12, x86_64_ISR12, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(13, x86_64_ISR13, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(14, x86_64_ISR14, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(15, x86_64_ISR15, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(16, x86_64_ISR16, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(17, x86_64_ISR17, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(18, x86_64_ISR18, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(19, x86_64_ISR19, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(20, x86_64_ISR20, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(21, x86_64_ISR21, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(22, x86_64_ISR22, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(23, x86_64_ISR23, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(24, x86_64_ISR24, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(25, x86_64_ISR25, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(26, x86_64_ISR26, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(27, x86_64_ISR27, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(28, x86_64_ISR28, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(29, x86_64_ISR29, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(30, x86_64_ISR30, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(31, x86_64_ISR31, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(32, x86_64_ISR32, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(33, x86_64_ISR33, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(34, x86_64_ISR34, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(35, x86_64_ISR35, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(36, x86_64_ISR36, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(37, x86_64_ISR37, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(38, x86_64_ISR38, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(39, x86_64_ISR39, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(40, x86_64_ISR40, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(41, x86_64_ISR41, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(42, x86_64_ISR42, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(43, x86_64_ISR43, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(44, x86_64_ISR44, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(45, x86_64_ISR45, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(46, x86_64_ISR46, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(47, x86_64_ISR47, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(48, x86_64_ISR48, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(49, x86_64_ISR49, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(50, x86_64_ISR50, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(51, x86_64_ISR51, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(52, x86_64_ISR52, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(53, x86_64_ISR53, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(54, x86_64_ISR54, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(55, x86_64_ISR55, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(56, x86_64_ISR56, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(57, x86_64_ISR57, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(58, x86_64_ISR58, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(59, x86_64_ISR59, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(60, x86_64_ISR60, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(61, x86_64_ISR61, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(62, x86_64_ISR62, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(63, x86_64_ISR63, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(64, x86_64_ISR64, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(65, x86_64_ISR65, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(66, x86_64_ISR66, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(67, x86_64_ISR67, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(68, x86_64_ISR68, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(69, x86_64_ISR69, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(70, x86_64_ISR70, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(71, x86_64_ISR71, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(72, x86_64_ISR72, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(73, x86_64_ISR73, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(74, x86_64_ISR74, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(75, x86_64_ISR75, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(76, x86_64_ISR76, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(77, x86_64_ISR77, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(78, x86_64_ISR78, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(79, x86_64_ISR79, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(80, x86_64_ISR80, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(81, x86_64_ISR81, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(82, x86_64_ISR82, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(83, x86_64_ISR83, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(84, x86_64_ISR84, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(85, x86_64_ISR85, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(86, x86_64_ISR86, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(87, x86_64_ISR87, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(88, x86_64_ISR88, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(89, x86_64_ISR89, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(90, x86_64_ISR90, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(91, x86_64_ISR91, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(92, x86_64_ISR92, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(93, x86_64_ISR93, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(94, x86_64_ISR94, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(95, x86_64_ISR95, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(96, x86_64_ISR96, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(97, x86_64_ISR97, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(98, x86_64_ISR98, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(99, x86_64_ISR99, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(100, x86_64_ISR100, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(101, x86_64_ISR101, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(102, x86_64_ISR102, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(103, x86_64_ISR103, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(104, x86_64_ISR104, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(105, x86_64_ISR105, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(106, x86_64_ISR106, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(107, x86_64_ISR107, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(108, x86_64_ISR108, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(109, x86_64_ISR109, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(110, x86_64_ISR110, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(111, x86_64_ISR111, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(112, x86_64_ISR112, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(113, x86_64_ISR113, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(114, x86_64_ISR114, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(115, x86_64_ISR115, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(116, x86_64_ISR116, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(117, x86_64_ISR117, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(118, x86_64_ISR118, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(119, x86_64_ISR119, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(120, x86_64_ISR120, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(121, x86_64_ISR121, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(122, x86_64_ISR122, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(123, x86_64_ISR123, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(124, x86_64_ISR124, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(125, x86_64_ISR125, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(126, x86_64_ISR126, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(127, x86_64_ISR127, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(128, x86_64_ISR128, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(129, x86_64_ISR129, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(130, x86_64_ISR130, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(131, x86_64_ISR131, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(132, x86_64_ISR132, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(133, x86_64_ISR133, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(134, x86_64_ISR134, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(135, x86_64_ISR135, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(136, x86_64_ISR136, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(137, x86_64_ISR137, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(138, x86_64_ISR138, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(139, x86_64_ISR139, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(140, x86_64_ISR140, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(141, x86_64_ISR141, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(142, x86_64_ISR142, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(143, x86_64_ISR143, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(144, x86_64_ISR144, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(145, x86_64_ISR145, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(146, x86_64_ISR146, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(147, x86_64_ISR147, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(148, x86_64_ISR148, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(149, x86_64_ISR149, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(150, x86_64_ISR150, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(151, x86_64_ISR151, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(152, x86_64_ISR152, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(153, x86_64_ISR153, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(154, x86_64_ISR154, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(155, x86_64_ISR155, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(156, x86_64_ISR156, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(157, x86_64_ISR157, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(158, x86_64_ISR158, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(159, x86_64_ISR159, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(160, x86_64_ISR160, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(161, x86_64_ISR161, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(162, x86_64_ISR162, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(163, x86_64_ISR163, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(164, x86_64_ISR164, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(165, x86_64_ISR165, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(166, x86_64_ISR166, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(167, x86_64_ISR167, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(168, x86_64_ISR168, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(169, x86_64_ISR169, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(170, x86_64_ISR170, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(171, x86_64_ISR171, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(172, x86_64_ISR172, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(173, x86_64_ISR173, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(174, x86_64_ISR174, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(175, x86_64_ISR175, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(176, x86_64_ISR176, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(177, x86_64_ISR177, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(178, x86_64_ISR178, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(179, x86_64_ISR179, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(180, x86_64_ISR180, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(181, x86_64_ISR181, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(182, x86_64_ISR182, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(183, x86_64_ISR183, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(184, x86_64_ISR184, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(185, x86_64_ISR185, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(186, x86_64_ISR186, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(187, x86_64_ISR187, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(188, x86_64_ISR188, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(189, x86_64_ISR189, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(190, x86_64_ISR190, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(191, x86_64_ISR191, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(192, x86_64_ISR192, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(193, x86_64_ISR193, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(194, x86_64_ISR194, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(195, x86_64_ISR195, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(196, x86_64_ISR196, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(197, x86_64_ISR197, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(198, x86_64_ISR198, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(199, x86_64_ISR199, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(200, x86_64_ISR200, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(201, x86_64_ISR201, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(202, x86_64_ISR202, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(203, x86_64_ISR203, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(204, x86_64_ISR204, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(205, x86_64_ISR205, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(206, x86_64_ISR206, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(207, x86_64_ISR207, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(208, x86_64_ISR208, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(209, x86_64_ISR209, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(210, x86_64_ISR210, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(211, x86_64_ISR211, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(212, x86_64_ISR212, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(213, x86_64_ISR213, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(214, x86_64_ISR214, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(215, x86_64_ISR215, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(216, x86_64_ISR216, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(217, x86_64_ISR217, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(218, x86_64_ISR218, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(219, x86_64_ISR219, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(220, x86_64_ISR220, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(221, x86_64_ISR221, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(222, x86_64_ISR222, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(223, x86_64_ISR223, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(224, x86_64_ISR224, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(225, x86_64_ISR225, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(226, x86_64_ISR226, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(227, x86_64_ISR227, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(228, x86_64_ISR228, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(229, x86_64_ISR229, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(230, x86_64_ISR230, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(231, x86_64_ISR231, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(232, x86_64_ISR232, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(233, x86_64_ISR233, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(234, x86_64_ISR234, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(235, x86_64_ISR235, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(236, x86_64_ISR236, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(237, x86_64_ISR237, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(238, x86_64_ISR238, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(239, x86_64_ISR239, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(240, x86_64_ISR240, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(241, x86_64_ISR241, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(242, x86_64_ISR242, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(243, x86_64_ISR243, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(244, x86_64_ISR244, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(245, x86_64_ISR245, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(246, x86_64_ISR246, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(247, x86_64_ISR247, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(248, x86_64_ISR248, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(249, x86_64_ISR249, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(250, x86_64_ISR250, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(251, x86_64_ISR251, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(252, x86_64_ISR252, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(253, x86_64_ISR253, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(254, x86_64_ISR254, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); + x86_64_IDT_SetGate(255, x86_64_ISR255, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT); +} \ No newline at end of file diff --git a/src/arch/x86_64/isrs_gen.inc b/src/arch/x86_64/isrs_gen.inc new file mode 100644 index 0000000..38c018b --- /dev/null +++ b/src/arch/x86_64/isrs_gen.inc @@ -0,0 +1,256 @@ +ISR_NOERRORCODE 0 +ISR_NOERRORCODE 1 +ISR_NOERRORCODE 2 +ISR_NOERRORCODE 3 +ISR_NOERRORCODE 4 +ISR_NOERRORCODE 5 +ISR_NOERRORCODE 6 +ISR_NOERRORCODE 7 +ISR_ERRORCODE 8 +ISR_NOERRORCODE 9 +ISR_ERRORCODE 10 +ISR_ERRORCODE 11 +ISR_ERRORCODE 12 +ISR_ERRORCODE 13 +ISR_ERRORCODE 14 +ISR_NOERRORCODE 15 +ISR_NOERRORCODE 16 +ISR_ERRORCODE 17 +ISR_NOERRORCODE 18 +ISR_NOERRORCODE 19 +ISR_NOERRORCODE 20 +ISR_ERRORCODE 21 +ISR_NOERRORCODE 22 +ISR_NOERRORCODE 23 +ISR_NOERRORCODE 24 +ISR_NOERRORCODE 25 +ISR_NOERRORCODE 26 +ISR_NOERRORCODE 27 +ISR_NOERRORCODE 28 +ISR_NOERRORCODE 29 +ISR_NOERRORCODE 30 +ISR_NOERRORCODE 31 +ISR_NOERRORCODE 32 +ISR_NOERRORCODE 33 +ISR_NOERRORCODE 34 +ISR_NOERRORCODE 35 +ISR_NOERRORCODE 36 +ISR_NOERRORCODE 37 +ISR_NOERRORCODE 38 +ISR_NOERRORCODE 39 +ISR_NOERRORCODE 40 +ISR_NOERRORCODE 41 +ISR_NOERRORCODE 42 +ISR_NOERRORCODE 43 +ISR_NOERRORCODE 44 +ISR_NOERRORCODE 45 +ISR_NOERRORCODE 46 +ISR_NOERRORCODE 47 +ISR_NOERRORCODE 48 +ISR_NOERRORCODE 49 +ISR_NOERRORCODE 50 +ISR_NOERRORCODE 51 +ISR_NOERRORCODE 52 +ISR_NOERRORCODE 53 +ISR_NOERRORCODE 54 +ISR_NOERRORCODE 55 +ISR_NOERRORCODE 56 +ISR_NOERRORCODE 57 +ISR_NOERRORCODE 58 +ISR_NOERRORCODE 59 +ISR_NOERRORCODE 60 +ISR_NOERRORCODE 61 +ISR_NOERRORCODE 62 +ISR_NOERRORCODE 63 +ISR_NOERRORCODE 64 +ISR_NOERRORCODE 65 +ISR_NOERRORCODE 66 +ISR_NOERRORCODE 67 +ISR_NOERRORCODE 68 +ISR_NOERRORCODE 69 +ISR_NOERRORCODE 70 +ISR_NOERRORCODE 71 +ISR_NOERRORCODE 72 +ISR_NOERRORCODE 73 +ISR_NOERRORCODE 74 +ISR_NOERRORCODE 75 +ISR_NOERRORCODE 76 +ISR_NOERRORCODE 77 +ISR_NOERRORCODE 78 +ISR_NOERRORCODE 79 +ISR_NOERRORCODE 80 +ISR_NOERRORCODE 81 +ISR_NOERRORCODE 82 +ISR_NOERRORCODE 83 +ISR_NOERRORCODE 84 +ISR_NOERRORCODE 85 +ISR_NOERRORCODE 86 +ISR_NOERRORCODE 87 +ISR_NOERRORCODE 88 +ISR_NOERRORCODE 89 +ISR_NOERRORCODE 90 +ISR_NOERRORCODE 91 +ISR_NOERRORCODE 92 +ISR_NOERRORCODE 93 +ISR_NOERRORCODE 94 +ISR_NOERRORCODE 95 +ISR_NOERRORCODE 96 +ISR_NOERRORCODE 97 +ISR_NOERRORCODE 98 +ISR_NOERRORCODE 99 +ISR_NOERRORCODE 100 +ISR_NOERRORCODE 101 +ISR_NOERRORCODE 102 +ISR_NOERRORCODE 103 +ISR_NOERRORCODE 104 +ISR_NOERRORCODE 105 +ISR_NOERRORCODE 106 +ISR_NOERRORCODE 107 +ISR_NOERRORCODE 108 +ISR_NOERRORCODE 109 +ISR_NOERRORCODE 110 +ISR_NOERRORCODE 111 +ISR_NOERRORCODE 112 +ISR_NOERRORCODE 113 +ISR_NOERRORCODE 114 +ISR_NOERRORCODE 115 +ISR_NOERRORCODE 116 +ISR_NOERRORCODE 117 +ISR_NOERRORCODE 118 +ISR_NOERRORCODE 119 +ISR_NOERRORCODE 120 +ISR_NOERRORCODE 121 +ISR_NOERRORCODE 122 +ISR_NOERRORCODE 123 +ISR_NOERRORCODE 124 +ISR_NOERRORCODE 125 +ISR_NOERRORCODE 126 +ISR_NOERRORCODE 127 +ISR_NOERRORCODE 128 +ISR_NOERRORCODE 129 +ISR_NOERRORCODE 130 +ISR_NOERRORCODE 131 +ISR_NOERRORCODE 132 +ISR_NOERRORCODE 133 +ISR_NOERRORCODE 134 +ISR_NOERRORCODE 135 +ISR_NOERRORCODE 136 +ISR_NOERRORCODE 137 +ISR_NOERRORCODE 138 +ISR_NOERRORCODE 139 +ISR_NOERRORCODE 140 +ISR_NOERRORCODE 141 +ISR_NOERRORCODE 142 +ISR_NOERRORCODE 143 +ISR_NOERRORCODE 144 +ISR_NOERRORCODE 145 +ISR_NOERRORCODE 146 +ISR_NOERRORCODE 147 +ISR_NOERRORCODE 148 +ISR_NOERRORCODE 149 +ISR_NOERRORCODE 150 +ISR_NOERRORCODE 151 +ISR_NOERRORCODE 152 +ISR_NOERRORCODE 153 +ISR_NOERRORCODE 154 +ISR_NOERRORCODE 155 +ISR_NOERRORCODE 156 +ISR_NOERRORCODE 157 +ISR_NOERRORCODE 158 +ISR_NOERRORCODE 159 +ISR_NOERRORCODE 160 +ISR_NOERRORCODE 161 +ISR_NOERRORCODE 162 +ISR_NOERRORCODE 163 +ISR_NOERRORCODE 164 +ISR_NOERRORCODE 165 +ISR_NOERRORCODE 166 +ISR_NOERRORCODE 167 +ISR_NOERRORCODE 168 +ISR_NOERRORCODE 169 +ISR_NOERRORCODE 170 +ISR_NOERRORCODE 171 +ISR_NOERRORCODE 172 +ISR_NOERRORCODE 173 +ISR_NOERRORCODE 174 +ISR_NOERRORCODE 175 +ISR_NOERRORCODE 176 +ISR_NOERRORCODE 177 +ISR_NOERRORCODE 178 +ISR_NOERRORCODE 179 +ISR_NOERRORCODE 180 +ISR_NOERRORCODE 181 +ISR_NOERRORCODE 182 +ISR_NOERRORCODE 183 +ISR_NOERRORCODE 184 +ISR_NOERRORCODE 185 +ISR_NOERRORCODE 186 +ISR_NOERRORCODE 187 +ISR_NOERRORCODE 188 +ISR_NOERRORCODE 189 +ISR_NOERRORCODE 190 +ISR_NOERRORCODE 191 +ISR_NOERRORCODE 192 +ISR_NOERRORCODE 193 +ISR_NOERRORCODE 194 +ISR_NOERRORCODE 195 +ISR_NOERRORCODE 196 +ISR_NOERRORCODE 197 +ISR_NOERRORCODE 198 +ISR_NOERRORCODE 199 +ISR_NOERRORCODE 200 +ISR_NOERRORCODE 201 +ISR_NOERRORCODE 202 +ISR_NOERRORCODE 203 +ISR_NOERRORCODE 204 +ISR_NOERRORCODE 205 +ISR_NOERRORCODE 206 +ISR_NOERRORCODE 207 +ISR_NOERRORCODE 208 +ISR_NOERRORCODE 209 +ISR_NOERRORCODE 210 +ISR_NOERRORCODE 211 +ISR_NOERRORCODE 212 +ISR_NOERRORCODE 213 +ISR_NOERRORCODE 214 +ISR_NOERRORCODE 215 +ISR_NOERRORCODE 216 +ISR_NOERRORCODE 217 +ISR_NOERRORCODE 218 +ISR_NOERRORCODE 219 +ISR_NOERRORCODE 220 +ISR_NOERRORCODE 221 +ISR_NOERRORCODE 222 +ISR_NOERRORCODE 223 +ISR_NOERRORCODE 224 +ISR_NOERRORCODE 225 +ISR_NOERRORCODE 226 +ISR_NOERRORCODE 227 +ISR_NOERRORCODE 228 +ISR_NOERRORCODE 229 +ISR_NOERRORCODE 230 +ISR_NOERRORCODE 231 +ISR_NOERRORCODE 232 +ISR_NOERRORCODE 233 +ISR_NOERRORCODE 234 +ISR_NOERRORCODE 235 +ISR_NOERRORCODE 236 +ISR_NOERRORCODE 237 +ISR_NOERRORCODE 238 +ISR_NOERRORCODE 239 +ISR_NOERRORCODE 240 +ISR_NOERRORCODE 241 +ISR_NOERRORCODE 242 +ISR_NOERRORCODE 243 +ISR_NOERRORCODE 244 +ISR_NOERRORCODE 245 +ISR_NOERRORCODE 246 +ISR_NOERRORCODE 247 +ISR_NOERRORCODE 248 +ISR_NOERRORCODE 249 +ISR_NOERRORCODE 250 +ISR_NOERRORCODE 251 +ISR_NOERRORCODE 252 +ISR_NOERRORCODE 253 +ISR_NOERRORCODE 254 +ISR_NOERRORCODE 255 diff --git a/src/arch/x86_64/pic.h b/src/arch/x86_64/pic.h new file mode 100644 index 0000000..00a9fbd --- /dev/null +++ b/src/arch/x86_64/pic.h @@ -0,0 +1,14 @@ +#pragma once + +#include +#include + +typedef struct { + const char* Name; + bool (*Probe)(); + void (*Initialize)(uint8_t offsetPic1, uint8_t offsetPic2, bool autoEoi); + void (*Disable)(); + void (*SendEndOfInterrupt)(int irq); + void (*Mask)(int irq); + void (*Unmask)(int irq); +} PICDriver; \ No newline at end of file diff --git a/src/arch/x86_64/usermode.c b/src/arch/x86_64/usermode.c new file mode 100644 index 0000000..2a4004b --- /dev/null +++ b/src/arch/x86_64/usermode.c @@ -0,0 +1,104 @@ +#include +#include +#include "mm/pmm.h" +#include "mm/vmm.h" +#include "mm/memory.h" +#include "stdio.h" +#include "fs/elf.h" + +extern uintptr_t g_hhdm_offset; + +#define USER_STACK_TOP 0x00007FFFFFFFE000ULL +#define USER_STACK_PAGES 4 +#define USER_STACK_SIZE (USER_STACK_PAGES * PAGE_SIZE) + +#define PTE_PRESENT (1ULL << 0) +#define PTE_WRITABLE (1ULL << 1) +#define PTE_USER (1ULL << 2) + + + +static uint64_t user_stack_phys_base = 0; + +extern struct pagemap *kernel_pagemap; + +static void setup_user_stack() +{ + // Allocate contiguous physical pages for the stack + user_stack_phys_base = (uint64_t)pmm_alloc(USER_STACK_PAGES); + if (!user_stack_phys_base) { + printf("Failed to allocate user stack pages!\n"); + for (;;); + } + + // Map each page individually into the current pagemap + // Stack grows downward, so start from the bottom + uintptr_t virt = USER_STACK_TOP - USER_STACK_SIZE; + + for (int i = 0; i < USER_STACK_PAGES; i++) { + uint64_t phys = user_stack_phys_base + (i * PAGE_SIZE); + + bool success = vmm_map_page( + kernel_pagemap, // Use kernel_pagemap for now (later: process->process_pagemap) + virt, + phys, + PAGE_READ | PAGE_WRITE | PAGE_USER, // RW + User + Size4KiB + ); + + if (!success) { + printf("Failed to map user stack page at 0x%lx\n", virt); + // TODO: cleanup previous pages if partial failure + for (;;); + } + + virt += PAGE_SIZE; + } + + // Optional: zero the stack (good practice) + // memset((void*)(USER_STACK_TOP - USER_STACK_SIZE), 0, USER_STACK_SIZE); +} + + + +// usermode.c +__attribute__((naked)) +void enter_user_mode(uint64_t rip, uint64_t rsp) +{ + asm volatile( + "cli\n" + "mov $0x1B, %ax\n" // Use User Data Selector (0x1B) + "mov %ax, %ds\n" + "mov %ax, %es\n" + "mov %ax, %fs\n" + "mov %ax, %gs\n" + + "pushq $0x1B\n" // SS (User Data) + "pushq %rsi\n" // RSP + "pushfq\n" + // Optional: manually set IF bit in pushed RFLAGS if you want interrupts enabled + "pop %rax\n" + "or $0x200, %rax\n" + "push %rax\n" + "pushq $0x23\n" // CS (User Code) + "pushq %rdi\n" // RIP + "iretq\n" + ); +} + +void start_userspace(void) +{ + void *entry = NULL; + + if (!ELF_Read("init.elf", &entry)) { + printf("Failed to load init.elf\n"); + for(;;); + } + + setup_user_stack(); + + printf("Jumping to user entry: 0x%lx with stack top 0x%lx\n", + (uint64_t)entry, USER_STACK_TOP); + + enter_user_mode((uint64_t)entry, USER_STACK_TOP); +} \ No newline at end of file diff --git a/src/arch/x86_64/usermode.h b/src/arch/x86_64/usermode.h new file mode 100644 index 0000000..90d1725 --- /dev/null +++ b/src/arch/x86_64/usermode.h @@ -0,0 +1,4 @@ +#pragma once +#include + +void start_userspace(void); \ No newline at end of file diff --git a/src/debug.c b/src/debug.c new file mode 100644 index 0000000..a97e43a --- /dev/null +++ b/src/debug.c @@ -0,0 +1,34 @@ +#include "debug.h" +#include +#include "stdio.h" +#include + +static const uint32_t g_LogSeverityColors[] = +{ + [LVL_DEBUG] = 0xAAAAAA, // light gray + [LVL_INFO] = 0xFFFFFF, // white + [LVL_WARN] = 0xFFFF00, // yellow + [LVL_ERROR] = 0xFF0000, // red + [LVL_CRITICAL] = 0xFFFFFF, // white (can do red background separately if you want) +}; + + +static const char* const g_ColorReset = "\033[0m"; + +void logf(const char* module, DebugLevel level, const char* fmt, ...) { + va_list args; + va_start(args, fmt); + + uint32_t color = g_LogSeverityColors[level]; + + fputs_colored("[", color); + fputs_colored(module, color); + fputs_colored("] ", color); + + // print formatted text in same color + vfprintf(fmt, args); // or adapt vfprintf to take a color + + fputc('\n'); + + va_end(args); +} \ No newline at end of file diff --git a/src/debug.h b/src/debug.h new file mode 100644 index 0000000..27dcd23 --- /dev/null +++ b/src/debug.h @@ -0,0 +1,20 @@ +#include + +#define MIN_LOG_LEVEL LVL_DEBUG + +typedef enum { + LVL_DEBUG = 0, + LVL_INFO = 1, + LVL_WARN = 2, + LVL_ERROR = 3, + LVL_CRITICAL = 4 +} DebugLevel; + + + +void logf(const char* module, DebugLevel level, const char* fmt, ...); +#define log_debug(module, ...) logf(module, LVL_DEBUG, __VA_ARGS__) +#define log_info(module, ...) logf(module, LVL_INFO, __VA_ARGS__) +#define log_warn(module, ...) logf(module, LVL_WARN, __VA_ARGS__) +#define log_err(module, ...) logf(module, LVL_ERROR, __VA_ARGS__) +#define log_crit(module, ...) logf(module, LVL_CRITICAL, __VA_ARGS__) \ No newline at end of file diff --git a/src/fs/elf.c b/src/fs/elf.c new file mode 100644 index 0000000..5d229e6 --- /dev/null +++ b/src/fs/elf.c @@ -0,0 +1,146 @@ +#include "elf.h" +#include "stdio.h" +#include "string.h" +#include "mm/pmm.h" +#include "mm/vmm.h" +#include "mm/memory.h" +#include "fs/ext2.h" + +extern uintptr_t g_hhdm_offset; +extern struct pagemap *kernel_pagemap; + +#define ELF_BUFFER_SIZE (1024 * 1024) + + +#define PTE_PRESENT (1ULL << 0) +#define PTE_WRITABLE (1ULL << 1) +#define PTE_USER (1ULL << 2) + +bool ELF_Read(const char* path, void** entryPoint) +{ + uint32_t size; + + uint8_t* elf_buffer = kmalloc(ELF_BUFFER_SIZE); + if (!elf_buffer) { + printf("ELF: kmalloc failed\n"); + return false; + } + + // ── load file ───────────────────────────────────── + if (!ext2_read_file_from_root(path, elf_buffer, &size)) { + printf("ELF: failed to read file\n"); + kfree(elf_buffer); + return false; + } + + if (size < sizeof(ELFHeader)) { + printf("ELF: file too small\n"); + kfree(elf_buffer); + return false; + } + + ELFHeader* header = (ELFHeader*)elf_buffer; + + // ── validate ELF ────────────────────────────────── + if (memcmp(header->Magic, ELF_MAGIC, 4) != 0) { + printf("ELF: bad magic\n"); + kfree(elf_buffer); + return false; + } + + if (header->Bitness != ELF_BITNESS_64BIT) { + printf("ELF: not 64-bit\n"); + kfree(elf_buffer); + return false; + } + + if (header->Endianness != ELF_ENDIANNESS_LITTLE) { + printf("ELF: wrong endianness\n"); + kfree(elf_buffer); + return false; + } + + if (header->Type != ELF_TYPE_EXECUTABLE) { + printf("ELF: not executable\n"); + kfree(elf_buffer); + return false; + } + + if (header->InstructionSet != ELF_INSTRUCTION_SET_X64) { + printf("ELF: wrong arch\n"); + kfree(elf_buffer); + return false; + } + + *entryPoint = (void*)header->ProgramEntryPosition; + + // ── program headers ─────────────────────────────── + uint8_t* ph_table = elf_buffer + header->ProgramHeaderTablePosition; + + for (uint32_t i = 0; i < header->ProgramHeaderTableEntryCount; i++) + { + ELFProgramHeader* ph = (ELFProgramHeader*)(ph_table + + i * header->ProgramHeaderTableEntrySize); + + if (ph->Type != ELF_PROGRAM_TYPE_LOAD) + continue; + + uint64_t virt = ph->VirtualAddress; + uint64_t offset = ph->Offset; + uint64_t memsz = ph->MemorySize; + uint64_t filesz = ph->FileSize; + + if (memsz == 0) + continue; + + // ── align to page boundary ───────────────────── + uint64_t aligned_virt = ALIGN_DOWN(virt, PAGE_SIZE); + uint64_t page_offset = virt & 0xFFF; + uint64_t aligned_memsz = ALIGN_UP(memsz + page_offset, PAGE_SIZE); + + uint64_t pages = aligned_memsz / PAGE_SIZE; + + // Allocate physical pages + uint64_t phys_base = (uint64_t)pmm_alloc(pages); + if (!phys_base) { + printf("ELF: pmm_alloc failed for %lu pages\n", pages); + kfree(elf_buffer); + return false; + } + + // ── map each page individually using new vmm_map_page ───── + for (uint64_t p = 0; p < pages; p++) { + uint64_t virt_addr = aligned_virt + p * PAGE_SIZE; + uint64_t phys_addr = phys_base + p * PAGE_SIZE; + + bool success = vmm_map_page( + kernel_pagemap, + virt_addr, + phys_addr, + PAGE_READ | PAGE_WRITE | PAGE_USER, // RW + User mode + Size4KiB + ); + + if (!success) { + printf("ELF: failed to map page at 0x%lx\n", virt_addr); + // TODO: cleanup previously mapped pages + free phys + kfree(elf_buffer); + return false; + } + } + + // ── copy segment data ─────────────────────────────── + uint8_t* dst = (uint8_t*)(phys_base + MEM_PHYS_OFFSET); // via HHDM + uint8_t* src = elf_buffer + offset; + + memcpy(dst + page_offset, src, filesz); + + // ── zero BSS section ──────────────────────────────── + if (memsz > filesz) { + memset(dst + page_offset + filesz, 0, memsz - filesz); + } + } + + kfree(elf_buffer); + return true; +} \ No newline at end of file diff --git a/src/fs/elf.h b/src/fs/elf.h new file mode 100644 index 0000000..bec6d4f --- /dev/null +++ b/src/fs/elf.h @@ -0,0 +1,117 @@ +#pragma once +#include +#include + +#define ELF_MAGIC ("\x7F" "ELF") + +#include + +typedef struct +{ + uint8_t Magic[4]; + uint8_t Bitness; // 1 = 32-bit, 2 = 64-bit + uint8_t Endianness; // 1 = little, 2 = big + uint8_t ELFHeaderVersion; + uint8_t ABI; + uint8_t ABIVersion; + uint8_t _Padding[7]; + + uint16_t Type; // relocatable, executable, shared, core + uint16_t InstructionSet; // architecture (was too small for real ELF, but kept) + + uint32_t ELFVersion; + + uint64_t ProgramEntryPosition; // FIXED (was 32-bit) + uint64_t ProgramHeaderTablePosition; // FIXED + uint64_t SectionHeaderTablePosition; // FIXED + + uint32_t Flags; + + uint16_t HeaderSize; + uint16_t ProgramHeaderTableEntrySize; + uint16_t ProgramHeaderTableEntryCount; + uint16_t SectionHeaderTableEntrySize; + uint16_t SectionHeaderTableEntryCount; + uint16_t SectionNamesIndex; + +} __attribute__((packed)) ELFHeader; + +enum ELFBitness +{ + ELF_BITNESS_32BIT = 1, + ELF_BITNESS_64BIT = 2, +}; + +enum ELFEndianness +{ + ELF_ENDIANNESS_LITTLE = 1, + ELF_ENDIANNESS_BIG = 2, +}; + +enum ELFInstructionSet +{ + ELF_INSTRUCTION_SET_NONE = 0, + ELF_INSTRUCTION_SET_X86 = 3, + ELF_INSTRUCTION_SET_ARM = 0x28, + ELF_INSTRUCTION_SET_X64 = 0x3E, + ELF_INSTRUCTION_SET_ARM64 = 0xB7, + ELF_INSTRUCTION_SET_RISCV = 0xF3, +}; + +enum ELFType +{ + ELF_TYPE_RELOCATABLE = 1, + ELF_TYPE_EXECUTABLE = 2, + ELF_TYPE_SHARED = 3, + ELF_TYPE_CORE = 4, +}; + +typedef struct +{ + uint32_t Type; + uint64_t Offset; + uint64_t VirtualAddress; + uint64_t PhysicalAddress; + uint64_t FileSize; + uint64_t MemorySize; + uint32_t Flags; + uint64_t Align; + +} ELFProgramHeader; + +enum ELFProgramType { + // Program header table entry unused. + ELF_PROGRAM_TYPE_NULL = 0, + + // Loadable segment. + ELF_PROGRAM_TYPE_LOAD = 1, + + // Dynamic linking information. + ELF_PROGRAM_TYPE_DYNAMIC = 2, + + // Interpreter information. + ELF_PROGRAM_TYPE_INTERP = 3, + + // Auxiliary information. + ELF_PROGRAM_TYPE_NOTE = 4, + + // Reserved + ELF_PROGRAM_TYPE_SHLIB = 5, + + // Segment containing program header table itself. + ELF_PROGRAM_TYPE_PHDR = 6, + + // Thread-Local Storage template. + ELF_PROGRAM_TYPE_TLS = 7, + + // Reserved inclusive range. Operating system specific. + ELF_PROGRAM_TYPE_LOOS = 0x60000000, + ELF_PROGRAM_TYPE_HIOS = 0x6FFFFFFF, + + // Reserved inclusive range. Processor specific. + ELF_PROGRAM_TYPE_LOPROC = 0x70000000, + ELF_PROGRAM_TYPE_HIPROC = 0x7FFFFFFF, +}; + + +bool ELF_Read(const char* path, void** entryPoint); \ No newline at end of file diff --git a/src/fs/ext2.c b/src/fs/ext2.c new file mode 100644 index 0000000..2bc8ff0 --- /dev/null +++ b/src/fs/ext2.c @@ -0,0 +1,1398 @@ +#include "ext2.h" +#include "arch/x86_64/ata.h" +#include "mm/memory.h" +#include "stdio.h" +#include +#include "string.h" +#include "mp/spinlock.h" + +// ── module state ───────────────────────────────────────────────────────────── + +static spinlock_t s_ext2_lock = SPINLOCK_INIT; +static ext2_superblock_t sb; +static ext2_group_desc_t* gdt; +static uint32_t num_groups; +static uint32_t block_size; + +// ── utilities ──────────────────────────────────────────────────────────────── + +static inline uint32_t align4(uint32_t n) { return (n + 3u) & ~3u; } + +const char* ext2_file_type_string(uint8_t type) { + switch (type) { + case EXT2_FT_REG_FILE: return "File"; + case EXT2_FT_DIR: return "Directory"; + case EXT2_FT_CHRDEV: return "Char Device"; + case EXT2_FT_BLKDEV: return "Block Device"; + case EXT2_FT_FIFO: return "FIFO"; + case EXT2_FT_SOCK: return "Socket"; + case EXT2_FT_SYMLINK: return "Symlink"; + default: return "Unknown"; + } +} + +// ── low-level block I/O ────────────────────────────────────────────────────── + +// RAW — no lock. Called only from within _internal functions. +static bool ext2_read_block_raw(uint32_t block_num, void* buf) { + return ata_read_sectors(block_num * (block_size / 512), + block_size / 512, buf); +} + +static bool ext2_write_block_raw(uint32_t block_num, const void* buf) { + return ata_write_sectors(block_num * (block_size / 512), + block_size / 512, buf); +} + +// PUBLIC — acquires lock. Called from outside the module. +bool ext2_read_block(uint32_t block_num, void* buf) { + uint64_t flags; + spinlock_acquire_irqsave(&s_ext2_lock, &flags); + bool ok = ext2_read_block_raw(block_num, buf); + spinlock_release_irqrestore(&s_ext2_lock, flags); + return ok; +} + +bool ext2_write_block(uint32_t block_num, const void* buf) { + uint64_t flags; + spinlock_acquire_irqsave(&s_ext2_lock, &flags); + bool ok = ext2_write_block_raw(block_num, buf); + spinlock_release_irqrestore(&s_ext2_lock, flags); + return ok; +} + + +// ── superblock / GDT ───────────────────────────────────────────────────────── + +bool ext2_read_superblock_internal(void) { + uint8_t* tmp = kmalloc(1024); + if (!tmp) return false; + + if (!ata_read_sectors(2, 2, tmp)) { + printf("EXT2: failed to read superblock\n"); + kfree(tmp); + return false; + } + memcpy(&sb, tmp, sizeof(ext2_superblock_t)); + kfree(tmp); + + if (sb.s_magic != EXT2_MAGIC) { + printf("EXT2: bad magic 0x%04x\n", sb.s_magic); + return false; + } + + block_size = 1024u << sb.s_log_block_size; + num_groups = (sb.s_blocks_count + sb.s_blocks_per_group - 1) + / sb.s_blocks_per_group; + + printf("EXT2: OK block_size=%u groups=%u\n", block_size, num_groups); + return true; +} + +bool ext2_read_superblock(void) { + uint64_t flags; + spinlock_acquire_irqsave(&s_ext2_lock, &flags); + bool resp = ext2_read_superblock_internal(); + spinlock_release_irqrestore(&s_ext2_lock, flags); + return resp; +} + +static bool ext2_write_superblock_internal(void) { + uint8_t* tmp = kmalloc(1024); + printf("test4"); + if (!tmp) return false; + memset(tmp, 0, 1024); + memcpy(tmp, &sb, sizeof(ext2_superblock_t)); + bool ok = ata_write_sectors(2, 2, tmp); + kfree(tmp); + return ok; +} + +static bool ext2_write_superblock(void) { + uint64_t flags; + spinlock_acquire_irqsave(&s_ext2_lock, &flags); + bool resp = ext2_write_superblock_internal(); + spinlock_release_irqrestore(&s_ext2_lock, flags); + return resp; +} + +bool ext2_read_group_desc_table_internal(void) { + // GDT immediately follows the superblock block + uint32_t gdt_block = (block_size == 1024) ? 2 : 1; + uint32_t bytes = num_groups * sizeof(ext2_group_desc_t); + uint32_t nblocks = (bytes + block_size - 1) / block_size; + + uint8_t* buf = kmalloc(nblocks * block_size); + if (!buf) { + printf("nah"); + return false; + } + + for (uint32_t i = 0; i < nblocks; i++) { + if (!ext2_read_block_raw(gdt_block + i, buf + i * block_size)) { + kfree(buf); + return false; + } + } + + gdt = kmalloc(bytes); + if (!gdt) { kfree(buf); return false; } + memcpy(gdt, buf, bytes); + kfree(buf); + + return true; +} + +bool ext2_read_group_desc_table(void) { + uint64_t flags; + spinlock_acquire_irqsave(&s_ext2_lock, &flags); + bool resp = ext2_read_group_desc_table_internal(); + spinlock_release_irqrestore(&s_ext2_lock, flags); + return resp; +} + +static bool ext2_write_gdt_internal(void) { + uint32_t gdt_block = (block_size == 1024) ? 2 : 1; + uint32_t bytes = num_groups * sizeof(ext2_group_desc_t); + uint32_t nblocks = (bytes + block_size - 1) / block_size; + + uint8_t* buf = kmalloc(nblocks * block_size); + if (!buf) return false; + memset(buf, 0, nblocks * block_size); + memcpy(buf, gdt, bytes); + + bool ok = true; + for (uint32_t i = 0; i < nblocks && ok; i++) + ok = ext2_write_block_raw(gdt_block + i, buf + i * block_size); + + kfree(buf); + return ok; +} + +static bool ext2_write_gdt(void) { + uint64_t flags; + spinlock_acquire_irqsave(&s_ext2_lock, &flags); + bool resp = ext2_write_gdt_internal(); + spinlock_release_irqrestore(&s_ext2_lock, flags); + return resp; +} + +static void ext2_sync(void) { + printf("test1"); + ext2_write_superblock_internal(); + printf("test2"); + ext2_write_gdt_internal(); + printf("test3"); +} + +// ── bitmap allocators ───────────────────────────────────────────────────────── + +// Returns physical block number, or 0 on failure. +// KEY FIX: block number = group * blocks_per_group + bit_index +// NOTE: calls ext2_read_block_raw / ext2_write_block_raw — NOT the locking versions + +static uint32_t ext2_alloc_block_internal(void) { + uint8_t* bm = kmalloc(block_size); + if (!bm) return 0; + + for (uint32_t g = 0; g < num_groups; g++) { + if (gdt[g].bg_free_blocks_count == 0) continue; + + ext2_read_block_raw(gdt[g].bg_block_bitmap, bm); // _raw, not locking + + uint32_t limit = sb.s_blocks_per_group; + if (g == num_groups - 1 && sb.s_blocks_count % sb.s_blocks_per_group) + limit = sb.s_blocks_count % sb.s_blocks_per_group; + + for (uint32_t i = 0; i < limit; i++) { + if (bm[i / 8] & (1u << (i % 8))) continue; + + bm[i / 8] |= (1u << (i % 8)); + ext2_write_block_raw(gdt[g].bg_block_bitmap, bm); // _raw, not locking + gdt[g].bg_free_blocks_count--; + sb.s_free_blocks_count--; + kfree(bm); + return g * sb.s_blocks_per_group + i; + } + } + kfree(bm); + return 0; +} + +static uint32_t ext2_alloc_block(void) { + uint64_t flags; + spinlock_acquire_irqsave(&s_ext2_lock, &flags); + uint32_t resp = ext2_alloc_block_internal(); + spinlock_release_irqrestore(&s_ext2_lock, flags); + return resp; +} + +static void ext2_free_block_internal(uint32_t blk) { + if (!blk) return; + uint32_t g = blk / sb.s_blocks_per_group; + uint32_t i = blk % sb.s_blocks_per_group; + + uint8_t* bm = kmalloc(block_size); + if (!bm) return; + + ext2_read_block_raw(gdt[g].bg_block_bitmap, bm); + bm[i / 8] &= ~(1u << (i % 8)); + ext2_write_block_raw(gdt[g].bg_block_bitmap, bm); + gdt[g].bg_free_blocks_count++; + sb.s_free_blocks_count++; + kfree(bm); +} + +static void ext2_free_block(uint32_t blk) { + uint64_t flags; + spinlock_acquire_irqsave(&s_ext2_lock, &flags); + ext2_free_block_internal(blk); + spinlock_release_irqrestore(&s_ext2_lock, flags); +} + +static uint32_t alloc_zero_block_internal(void) { + uint32_t b = ext2_alloc_block_internal(); // _internal, not locking + if (!b) return 0; + uint8_t* z = kmalloc(block_size); + if (!z) { ext2_free_block_internal(b); return 0; } + memset(z, 0, block_size); + ext2_write_block_raw(b, z); // _raw + kfree(z); + return b; +} + +static uint32_t alloc_zero_block(void) { + uint64_t flags; + spinlock_acquire_irqsave(&s_ext2_lock, &flags); + uint32_t resp = alloc_zero_block_internal(); + spinlock_release_irqrestore(&s_ext2_lock, flags); + return resp; +} + +// Returns 1-based inode number, or 0 on failure. +static uint32_t ext2_alloc_inode_internal(bool is_dir) { + uint8_t* bm = kmalloc(block_size); + if (!bm) return 0; + + for (uint32_t g = 0; g < num_groups; g++) { + if (gdt[g].bg_free_inodes_count == 0) continue; + + ext2_read_block_raw(gdt[g].bg_inode_bitmap, bm); + + for (uint32_t i = 0; i < sb.s_inodes_per_group; i++) { + if (bm[i / 8] & (1u << (i % 8))) continue; + + bm[i / 8] |= (1u << (i % 8)); + ext2_write_block_raw(gdt[g].bg_inode_bitmap, bm); + gdt[g].bg_free_inodes_count--; + sb.s_free_inodes_count--; + if (is_dir) gdt[g].bg_used_dirs_count++; + kfree(bm); + return g * sb.s_inodes_per_group + i + 1; // 1-based + } + } + kfree(bm); + return 0; +} + +static uint32_t ext2_alloc_inode(bool is_dir) { + uint64_t flags; + spinlock_acquire_irqsave(&s_ext2_lock, &flags); + uint32_t resp = ext2_alloc_inode_internal(is_dir); + spinlock_release_irqrestore(&s_ext2_lock, flags); + return resp; +} + +static void ext2_free_inode_internal(uint32_t inum, bool is_dir) { + if (!inum) return; + inum--; + uint32_t g = inum / sb.s_inodes_per_group; + uint32_t i = inum % sb.s_inodes_per_group; + + uint8_t* bm = kmalloc(block_size); + if (!bm) return; + + ext2_read_block_raw(gdt[g].bg_inode_bitmap, bm); + bm[i / 8] &= ~(1u << (i % 8)); + ext2_write_block_raw(gdt[g].bg_inode_bitmap, bm); + gdt[g].bg_free_inodes_count++; + sb.s_free_inodes_count++; + if (is_dir && gdt[g].bg_used_dirs_count) gdt[g].bg_used_dirs_count--; + kfree(bm); +} + +static void ext2_free_inode(uint32_t inum, bool is_dir) { + uint64_t flags; + spinlock_acquire_irqsave(&s_ext2_lock, &flags); + ext2_free_inode_internal(inum, is_dir); + spinlock_release_irqrestore(&s_ext2_lock, flags); +} + +// ── inode I/O ──────────────────────────────────────────────────────────────── + +bool ext2_read_inode_internal(uint32_t inum, ext2_inode_t* out) { + inum--; + uint32_t g = inum / sb.s_inodes_per_group; + uint32_t idx = inum % sb.s_inodes_per_group; + uint32_t ipb = block_size / sb.s_inode_size; + uint32_t block_off = idx / ipb; + uint32_t inode_off = idx % ipb; + + uint8_t* buf = kmalloc(block_size); + if (!buf) return false; + if (!ext2_read_block_raw(gdt[g].bg_inode_table + block_off, buf)) { + kfree(buf); return false; + } + memcpy(out, buf + inode_off * sb.s_inode_size, sizeof(ext2_inode_t)); + kfree(buf); + return true; +} + +bool ext2_read_inode(uint32_t inum, ext2_inode_t* out) { + uint64_t flags; + spinlock_acquire_irqsave(&s_ext2_lock, &flags); + bool resp = ext2_read_inode_internal(inum, out); + spinlock_release_irqrestore(&s_ext2_lock, flags); + return resp; +} + +bool ext2_write_inode_internal(uint32_t inum, ext2_inode_t* inode) { + inum--; + uint32_t g = inum / sb.s_inodes_per_group; + uint32_t idx = inum % sb.s_inodes_per_group; + uint32_t ipb = block_size / sb.s_inode_size; + uint32_t block_off = idx / ipb; + uint32_t inode_off = idx % ipb; + + uint8_t* buf = kmalloc(block_size); + if (!buf) return false; + if (!ext2_read_block_raw(gdt[g].bg_inode_table + block_off, buf)) { + kfree(buf); return false; + } + memcpy(buf + inode_off * sb.s_inode_size, inode, sizeof(ext2_inode_t)); + bool ok = ext2_write_block_raw(gdt[g].bg_inode_table + block_off, buf); + kfree(buf); + return ok; +} + +bool ext2_write_inode(uint32_t inum, ext2_inode_t* inode) { + uint64_t flags; + spinlock_acquire_irqsave(&s_ext2_lock, &flags); + bool resp = ext2_write_inode_internal(inum, inode); + spinlock_release_irqrestore(&s_ext2_lock, flags); + return resp; +} + +// ── block map (handles all indirect levels, read or allocate) ──────────────── + +static uint32_t ext2_block_map_internal(ext2_inode_t* inode, uint32_t fb, bool create) { + uint32_t ptrs = block_size / 4; + + // direct + if (fb < 12) { + if (create && !inode->i_block[fb]) + inode->i_block[fb] = alloc_zero_block_internal(); + return inode->i_block[fb]; + } + fb -= 12; + + // single indirect + if (fb < ptrs) { + if (create && !inode->i_block[12]) + inode->i_block[12] = alloc_zero_block_internal(); + if (!inode->i_block[12]) return 0; + + uint32_t* tbl = kmalloc(block_size); + ext2_read_block_raw(inode->i_block[12], tbl); + if (create && !tbl[fb]) tbl[fb] = alloc_zero_block_internal(); + uint32_t r = tbl[fb]; + if (create) ext2_write_block_raw(inode->i_block[12], tbl); + kfree(tbl); + return r; + } + fb -= ptrs; + + // double indirect + if (fb < ptrs * ptrs) { + if (create && !inode->i_block[13]) + inode->i_block[13] = alloc_zero_block_internal(); + if (!inode->i_block[13]) return 0; + + uint32_t* l1 = kmalloc(block_size); + ext2_read_block_raw(inode->i_block[13], l1); + uint32_t i1 = fb / ptrs, i2 = fb % ptrs; + if (create && !l1[i1]) { + l1[i1] = alloc_zero_block_internal(); + ext2_write_block_raw(inode->i_block[13], l1); + } + if (!l1[i1]) { kfree(l1); return 0; } + + uint32_t* l2 = kmalloc(block_size); + ext2_read_block_raw(l1[i1], l2); + if (create && !l2[i2]) l2[i2] = alloc_zero_block_internal(); + uint32_t r = l2[i2]; + if (create) ext2_write_block_raw(l1[i1], l2); + kfree(l1); kfree(l2); + return r; + } + fb -= ptrs * ptrs; + + // triple indirect + if (create && !inode->i_block[14]) + inode->i_block[14] = alloc_zero_block_internal(); + if (!inode->i_block[14]) return 0; + + uint32_t* l1 = kmalloc(block_size); + ext2_read_block_raw(inode->i_block[14], l1); + uint32_t i1 = fb / (ptrs * ptrs); + uint32_t rem = fb % (ptrs * ptrs); + uint32_t i2 = rem / ptrs, i3 = rem % ptrs; + + if (create && !l1[i1]) { l1[i1] = alloc_zero_block_internal(); ext2_write_block_raw(inode->i_block[14], l1); } + if (!l1[i1]) { kfree(l1); return 0; } + + uint32_t* l2 = kmalloc(block_size); + ext2_read_block_raw(l1[i1], l2); + if (create && !l2[i2]) { l2[i2] = alloc_zero_block_internal(); ext2_write_block_raw(l1[i1], l2); } + if (!l2[i2]) { kfree(l1); kfree(l2); return 0; } + + uint32_t* l3 = kmalloc(block_size); + ext2_read_block_raw(l2[i2], l3); + if (create && !l3[i3]) l3[i3] = alloc_zero_block_internal(); + uint32_t r = l3[i3]; + if (create) { + ext2_write_block_raw(l2[i2], l3); + ext2_write_block_raw(l1[i1], l2); + ext2_write_block_raw(inode->i_block[14], l1); + } + kfree(l1); kfree(l2); kfree(l3); + return r; +} + +static uint32_t ext2_block_map(ext2_inode_t* inode, uint32_t fb, bool create) { + uint64_t flags; + spinlock_acquire_irqsave(&s_ext2_lock, &flags); + uint32_t resp = ext2_block_map_internal(inode, fb, create); + spinlock_release_irqrestore(&s_ext2_lock, flags); + return resp; +} + +// ── free all data blocks belonging to an inode ──────────────────────────────── + +static void ext2_free_inode_blocks_internal(ext2_inode_t* inode) { + uint32_t ptrs = block_size / 4; + uint32_t total_data = (inode->i_size + block_size - 1) / block_size; + + for (uint32_t i = 0; i < total_data; i++) { + uint32_t b = ext2_block_map_internal(inode, i, false); + if (b) ext2_free_block_internal(b); + } + + uint32_t* tbl = kmalloc(block_size); + if (!tbl) return; + + // free single-indirect table block + if (inode->i_block[12]) { + ext2_free_block_internal(inode->i_block[12]); + inode->i_block[12] = 0; + } + + // free double-indirect and its L1 table blocks + if (inode->i_block[13]) { + ext2_read_block_raw(inode->i_block[13], tbl); + for (uint32_t i = 0; i < ptrs; i++) + if (tbl[i]) ext2_free_block_internal(tbl[i]); + ext2_free_block_internal(inode->i_block[13]); + inode->i_block[13] = 0; + } + + // free triple-indirect and its L1+L2 table blocks + if (inode->i_block[14]) { + uint32_t* l2 = kmalloc(block_size); + ext2_read_block_raw(inode->i_block[14], tbl); + for (uint32_t i = 0; i < ptrs; i++) { + if (!tbl[i]) continue; + ext2_read_block_raw(tbl[i], l2); + for (uint32_t j = 0; j < ptrs; j++) + if (l2[j]) ext2_free_block_internal(l2[j]); + ext2_free_block_internal(tbl[i]); + } + ext2_free_block_internal(inode->i_block[14]); + inode->i_block[14] = 0; + kfree(l2); + } + kfree(tbl); +} + +static void ext2_free_inode_blocks(ext2_inode_t* inode) { + uint64_t flags; + spinlock_acquire_irqsave(&s_ext2_lock, &flags); + ext2_free_inode_blocks_internal(inode); + spinlock_release_irqrestore(&s_ext2_lock, flags); +} + +// ── file I/O ───────────────────────────────────────────────────────────────── + +bool ext2_read_file_internal(ext2_inode_t* inode, uint8_t* buf) { + if ((inode->i_mode & 0xF000) != EXT2_S_IFREG) { + printf("EXT2: not a regular file\n"); + return false; + } + uint32_t size = inode->i_size; + uint32_t done = 0; + uint8_t* tmp = kmalloc(block_size); + if (!tmp) return false; + + for (uint32_t fb = 0; done < size; fb++) { + uint32_t phys = ext2_block_map_internal(inode, fb, false); + if (!phys) break; + + ext2_read_block_raw(phys, tmp); + uint32_t n = block_size; + if (done + n > size) n = size - done; + memcpy(buf + done, tmp, n); + done += n; + } + kfree(tmp); + return true; +} + +bool ext2_read_file(ext2_inode_t* inode, uint8_t* buf) { + uint64_t flags; + spinlock_acquire_irqsave(&s_ext2_lock, &flags); + bool resp = ext2_read_file_internal(inode, buf); + spinlock_release_irqrestore(&s_ext2_lock, flags); + return resp; +} + +bool ext2_write_file_internal(ext2_inode_t* inode, uint32_t inum, + const uint8_t* data, uint32_t size, ext2_write_mode_t mode) +{ + uint32_t write_at = 0; + + if (mode == EXT2_WRITE_APPEND) { + write_at = inode->i_size; + } else { + // overwrite: tear down old blocks first + ext2_free_inode_blocks_internal(inode); + memset(inode->i_block, 0, sizeof(inode->i_block)); + inode->i_size = 0; + inode->i_blocks = 0; + } + + uint32_t new_size = write_at + size; + inode->i_size = new_size; + + uint8_t* tmp = kmalloc(block_size); + if (!tmp) return false; + + for (uint32_t written = 0; written < size; ) { + uint32_t abs = write_at + written; + uint32_t fb = abs / block_size; + uint32_t boff = abs % block_size; + uint32_t phys = ext2_block_map_internal(inode, fb, true); + if (!phys) { kfree(tmp); return false; } + + // read-modify-write for partial blocks + if (boff || (size - written) < block_size) + ext2_read_block_raw(phys, tmp); + else + memset(tmp, 0, block_size); + + uint32_t n = block_size - boff; + if (n > size - written) n = size - written; + memcpy(tmp + boff, data + written, n); + ext2_write_block_raw(phys, tmp); + written += n; + } + + inode->i_blocks = ((new_size + block_size - 1) / block_size) * (block_size / 512); + //inode->i_mtime = (uint32_t)g_Unixseconds; + //inode->i_ctime = (uint32_t)g_Unixseconds; + kfree(tmp); + ext2_write_inode_internal(inum, inode); + return true; +} + +bool ext2_write_file(ext2_inode_t* inode, uint32_t inum, + const uint8_t* data, uint32_t size, ext2_write_mode_t mode) +{ + uint64_t flags; + spinlock_acquire_irqsave(&s_ext2_lock, &flags); + bool resp = ext2_write_file_internal(inode, inum, data, size, mode); + spinlock_release_irqrestore(&s_ext2_lock, flags); + return resp; +} + +bool ext2_truncate_internal(ext2_inode_t* inode, uint32_t inum, uint32_t new_size) { + uint32_t old_size = inode->i_size; + if (new_size == old_size) return true; + + if (new_size < old_size) { + // free blocks past new_size + uint32_t old_blks = (old_size + block_size - 1) / block_size; + uint32_t new_blks = (new_size + block_size - 1) / block_size; + for (uint32_t i = new_blks; i < old_blks; i++) { + uint32_t b = ext2_block_map_internal(inode, i, false); + if (b) ext2_free_block_internal(b); + } + // zero the tail of the last surviving block + if (new_size % block_size && new_blks) { + uint32_t b = ext2_block_map_internal(inode, new_blks - 1, false); + if (b) { + uint8_t* tmp = kmalloc(block_size); + ext2_read_block_raw(b, tmp); + uint32_t from = new_size % block_size; + memset(tmp + from, 0, block_size - from); + ext2_write_block_raw(b, tmp); + kfree(tmp); + } + } + inode->i_blocks = new_blks * (block_size / 512); + } + // extending: sparse — just update the size field + + inode->i_size = new_size; + //inode->i_mtime = (uint32_t)g_Unixseconds; + //inode->i_ctime = (uint32_t)g_Unixseconds; + return ext2_write_inode_internal(inum, inode); +} + +bool ext2_truncate(ext2_inode_t* inode, uint32_t inum, uint32_t new_size) { + uint64_t flags; + spinlock_acquire_irqsave(&s_ext2_lock, &flags); + bool resp = ext2_truncate_internal(inode, inum, new_size); + spinlock_release_irqrestore(&s_ext2_lock, flags); + return resp; +} + +// ── directory helpers ───────────────────────────────────────────────────────── + +// Scan one directory inode for a named entry, return its inode number or 0. +static uint32_t dir_lookup_internal(ext2_inode_t* dir, const char* name) { + uint32_t nlen = strlen(name); + uint8_t* buf = kmalloc(block_size); + if (!buf) return 0; + uint32_t nblocks = (dir->i_size + block_size - 1) / block_size; + + for (uint32_t fb = 0; fb < nblocks; fb++) { + uint32_t phys = ext2_block_map_internal(dir, fb, false); + if (!phys) continue; + ext2_read_block_raw(phys, buf); + + uint32_t off = 0; + while (off + 8 <= block_size) { + ext2_dir_entry_t* e = (ext2_dir_entry_t*)(buf + off); + if (e->rec_len < 8 || off + e->rec_len > block_size) break; + if (e->inode && e->name_len == nlen) { + char tmp[256] = {0}; + memcpy(tmp, e->name, nlen); + if (strcmp(tmp, name) == 0) { + uint32_t r = e->inode; + kfree(buf); + return r; + } + } + off += e->rec_len; + } + } + kfree(buf); + return 0; +} + +// Insert a new directory entry into dir, allocating a new block if needed. +static bool dir_add_entry_internal(ext2_inode_t* dir, uint32_t dir_inum, + uint32_t new_inum, const char* name, uint8_t ftype) +{ + uint8_t nlen = (uint8_t)strlen(name); + uint16_t needed = (uint16_t)align4(8 + nlen); + uint8_t* buf = kmalloc(block_size); + if (!buf) return false; + + uint32_t nblocks = (dir->i_size + block_size - 1) / block_size; + + for (uint32_t fb = 0; fb < nblocks; fb++) { + uint32_t phys = ext2_block_map_internal(dir, fb, false); + if (!phys) continue; + ext2_read_block_raw(phys, buf); + + uint32_t off = 0; + while (off + 8 <= block_size) { + ext2_dir_entry_t* e = (ext2_dir_entry_t*)(buf + off); + if (e->rec_len < 8 || off + e->rec_len > block_size) break; + + uint16_t real = (uint16_t)align4(8 + (e->inode ? e->name_len : 0)); + uint16_t avail = e->rec_len - (e->inode ? real : 0); + + if (e->inode == 0 && e->rec_len >= needed) { + // reuse deleted slot + e->inode = new_inum; + e->name_len = nlen; + e->file_type = ftype; + memcpy(e->name, name, nlen); + ext2_write_block_raw(phys, buf); + kfree(buf); + return true; + } else if (e->inode && avail >= needed) { + // split: shrink existing, carve off the tail + ext2_dir_entry_t* ne = (ext2_dir_entry_t*)(buf + off + real); + ne->inode = new_inum; + ne->name_len = nlen; + ne->file_type = ftype; + ne->rec_len = avail; + memcpy(ne->name, name, nlen); + e->rec_len = real; + ext2_write_block_raw(phys, buf); + kfree(buf); + return true; + } + off += e->rec_len; + } + } + + // No room in existing blocks — grow the directory by one block + uint32_t phys = ext2_block_map_internal(dir, nblocks, true); + if (!phys) { kfree(buf); return false; } + memset(buf, 0, block_size); + + ext2_dir_entry_t* e = (ext2_dir_entry_t*)buf; + e->inode = new_inum; + e->name_len = nlen; + e->file_type = ftype; + e->rec_len = (uint16_t)block_size; + memcpy(e->name, name, nlen); + ext2_write_block_raw(phys, buf); + + dir->i_size += block_size; + dir->i_blocks = (dir->i_size / block_size) * (block_size / 512); + //dir->i_mtime = (uint32_t)g_Unixseconds; + ext2_write_inode_internal(dir_inum, dir); + kfree(buf); + return true; +} + +// Remove an entry by name, merging its space back into the previous entry. +static bool dir_remove_entry_internal(ext2_inode_t* dir, uint32_t dir_inum, const char* name) { + uint32_t nlen = strlen(name); + uint8_t* buf = kmalloc(block_size); + if (!buf) return false; + uint32_t nblocks = (dir->i_size + block_size - 1) / block_size; + + for (uint32_t fb = 0; fb < nblocks; fb++) { + uint32_t phys = ext2_block_map_internal(dir, fb, false); + if (!phys) continue; + ext2_read_block_raw(phys, buf); + + uint32_t off = 0; + ext2_dir_entry_t* prev = NULL; + + while (off + 8 <= block_size) { + ext2_dir_entry_t* e = (ext2_dir_entry_t*)(buf + off); + if (e->rec_len < 8 || off + e->rec_len > block_size) break; + + if (e->inode && e->name_len == nlen) { + char tmp[256] = {0}; + memcpy(tmp, e->name, nlen); + if (strcmp(tmp, name) == 0) { + if (prev) + prev->rec_len += e->rec_len; // absorb into previous + else + e->inode = 0; // first entry: zero inode + ext2_write_block_raw(phys, buf); + //dir->i_mtime = (uint32_t)g_Unixseconds; + ext2_write_inode_internal(dir_inum, dir); + kfree(buf); + return true; + } + } + prev = e; + off += e->rec_len; + } + } + kfree(buf); + return false; +} + +static bool dir_is_empty_internal(ext2_inode_t* dir) { + uint8_t* buf = kmalloc(block_size); + if (!buf) return true; + uint32_t nblocks = (dir->i_size + block_size - 1) / block_size; + + for (uint32_t fb = 0; fb < nblocks; fb++) { + uint32_t phys = ext2_block_map_internal(dir, fb, false); + if (!phys) continue; + ext2_read_block_raw(phys, buf); + + uint32_t off = 0; + while (off + 8 <= block_size) { + ext2_dir_entry_t* e = (ext2_dir_entry_t*)(buf + off); + if (e->rec_len < 8) break; + if (e->inode) { + char n[256] = {0}; + memcpy(n, e->name, e->name_len); + if (strcmp(n, ".") && strcmp(n, "..")) { + kfree(buf); + return false; + } + } + off += e->rec_len; + } + } + kfree(buf); + return true; +} + +// ── path resolution ─────────────────────────────────────────────────────────── + +uint32_t ext2_resolve_path_internal(const char* path) { + uint32_t cur_inum = 2; // root + ext2_inode_t cur; + if (!ext2_read_inode_internal(cur_inum, &cur)) return 0; + + if (*path == '/') path++; + if (!*path) return cur_inum; + + char comp[256]; + while (*path) { + uint32_t len = 0; + while (path[len] && path[len] != '/') len++; + if (!len || len >= 256) return 0; + + memcpy(comp, path, len); + comp[len] = '\0'; + path += len; + if (*path == '/') path++; + + cur_inum = dir_lookup_internal(&cur, comp); + if (!cur_inum) return 0; + if (!ext2_read_inode_internal(cur_inum, &cur)) return 0; + } + return cur_inum; +} + +uint32_t ext2_resolve_path(const char* path) { + uint64_t flags; + spinlock_acquire_irqsave(&s_ext2_lock, &flags); + uint32_t resp = ext2_resolve_path_internal(path); + spinlock_release_irqrestore(&s_ext2_lock, flags); + return resp; +} + +// ── public directory API ────────────────────────────────────────────────────── + +bool ext2_find_in_dir_internal(ext2_inode_t* dir, const char* name, uint32_t* out) { + *out = dir_lookup_internal(dir, name); + return *out != 0; +} + +bool ext2_find_in_dir(ext2_inode_t* dir, const char* name, uint32_t* out) { + uint64_t flags; + spinlock_acquire_irqsave(&s_ext2_lock, &flags); + bool resp = ext2_find_in_dir_internal(dir, name, out); + spinlock_release_irqrestore(&s_ext2_lock, flags); + return resp; +} + +bool ext2_read_dir_internal(ext2_inode_t* dir) { + uint8_t* buf = kmalloc(block_size); + if (!buf) return false; + uint32_t nblocks = (dir->i_size + block_size - 1) / block_size; + + for (uint32_t fb = 0; fb < nblocks; fb++) { + uint32_t phys = ext2_block_map_internal(dir, fb, false); + if (!phys) continue; + ext2_read_block_raw(phys, buf); + + uint32_t off = 0; + while (off + 8 <= block_size) { + ext2_dir_entry_t* e = (ext2_dir_entry_t*)(buf + off); + if (e->rec_len < 8 || off + e->rec_len > block_size) break; + if (e->inode) { + char name[256]; + uint8_t nl = e->name_len > EXT2_NAME_LEN ? EXT2_NAME_LEN : e->name_len; + memcpy(name, e->name, nl); + name[nl] = '\0'; + printf(" %-32s inode=%-6u %s\n", + name, e->inode, ext2_file_type_string(e->file_type)); + } + off += e->rec_len; + } + } + kfree(buf); + return true; +} + +bool ext2_read_dir(ext2_inode_t* dir) { + uint64_t flags; + spinlock_acquire_irqsave(&s_ext2_lock, &flags); + bool resp = ext2_read_dir_internal(dir); + spinlock_release_irqrestore(&s_ext2_lock, flags); + return resp; +} + +bool ext2_read_root_dir_internal(void) { + ext2_inode_t root; + if (!ext2_read_inode_internal(2, &root)) return false; + printf("Root directory:\n"); + return ext2_read_dir_internal(&root); +} + +bool ext2_read_root_dir(void) { + uint64_t flags; + spinlock_acquire_irqsave(&s_ext2_lock, &flags); + bool resp = ext2_read_root_dir_internal(); + spinlock_release_irqrestore(&s_ext2_lock, flags); + return resp; +} + +// ── high-level file ops ─────────────────────────────────────────────────────── + +bool ext2_read_file_from_root_internal(const char* name, uint8_t* buf, uint32_t* size) { + ext2_inode_t root; + if (!ext2_read_inode_internal(2, &root)) return false; + + uint32_t inum; + if (!ext2_find_in_dir_internal(&root, name, &inum)) { + printf("EXT2: not found: %s\n", name); + return false; + } + ext2_inode_t fi; + if (!ext2_read_inode_internal(inum, &fi)) return false; + *size = fi.i_size; + return ext2_read_file_internal(&fi, buf); +} + +bool ext2_read_file_from_root(const char* name, uint8_t* buf, uint32_t* size) { + uint64_t flags; + spinlock_acquire_irqsave(&s_ext2_lock, &flags); + bool resp = ext2_read_file_from_root_internal(name, buf, size); + spinlock_release_irqrestore(&s_ext2_lock, flags); + return resp; +} + + +bool ext2_write_file_from_root_internal(const char* name, const uint8_t* data, + uint32_t size, ext2_write_mode_t mode) +{ + ext2_inode_t root; + if (!ext2_read_inode_internal(2, &root)) { + return false; + } + + uint32_t inum; + if (!ext2_find_in_dir_internal(&root, name, &inum)) { + printf("EXT2: not found: %s\n", name); + return false; + } + ext2_inode_t fi; + if (!ext2_read_inode_internal(inum, &fi)) return false; + bool ok = ext2_write_file_internal(&fi, inum, data, size, mode); + if (ok) ext2_sync(); + return ok; +} + +bool ext2_write_file_from_root(const char* name, const uint8_t* data, + uint32_t size, ext2_write_mode_t mode) +{ + uint64_t flags; + spinlock_acquire_irqsave(&s_ext2_lock, &flags); + bool resp = ext2_write_file_from_root_internal(name, data, size, mode); + spinlock_release_irqrestore(&s_ext2_lock, flags); + return resp; +} + +// ── create / delete ─────────────────────────────────────────────────────────── + +bool ext2_create_file_internal(ext2_inode_t* dir, uint32_t dir_inum, + const char* name, uint32_t* out_inum) +{ + if (dir_lookup_internal(dir, name)) { + printf("EXT2: already exists: %s\n", name); + return false; + } + + uint32_t inum = ext2_alloc_inode_internal(false); + if (!inum) return false; + + ext2_inode_t inode = {0}; + inode.i_mode = EXT2_S_IFREG | 0644; + inode.i_links_count = 1; + //inode.i_atime = inode.i_ctime = inode.i_mtime = (uint32_t)g_Unixseconds; + ext2_write_inode_internal(inum, &inode); + + if (!dir_add_entry_internal(dir, dir_inum, inum, name, EXT2_FT_REG_FILE)) { + ext2_free_inode_internal(inum, false); + return false; + } + if (out_inum) *out_inum = inum; + ext2_sync(); + return true; +} + +bool ext2_create_file(ext2_inode_t* dir, uint32_t dir_inum, + const char* name, uint32_t* out_inum) +{ + uint64_t flags; + spinlock_acquire_irqsave(&s_ext2_lock, &flags); + bool resp = ext2_create_file_internal(dir, dir_inum, name, out_inum); + spinlock_release_irqrestore(&s_ext2_lock, flags); + return resp; +} + +bool ext2_mkdir_internal(ext2_inode_t* parent, uint32_t parent_inum, + const char* name, uint32_t* out_inum) +{ + if (dir_lookup_internal(parent, name)) { + printf("EXT2: already exists: %s\n", name); + return false; + } + + uint32_t inum = ext2_alloc_inode_internal(true); + if (!inum) return false; + + // Allocate the first block and write . and .. + uint32_t phys = alloc_zero_block_internal(); + if (!phys) { ext2_free_inode_internal(inum, true); return false; } + + ext2_inode_t dir = {0}; + dir.i_mode = EXT2_S_IFDIR | 0755; + dir.i_links_count = 2; // . + parent entry + dir.i_size = block_size; + dir.i_blocks = block_size / 512; + dir.i_block[0] = phys; + //dir.i_atime = dir.i_ctime = dir.i_mtime = (uint32_t)g_Unixseconds; + ext2_write_inode_internal(inum, &dir); + + uint8_t* buf = kmalloc(block_size); + memset(buf, 0, block_size); + + ext2_dir_entry_t* dot = (ext2_dir_entry_t*)buf; + dot->inode = inum; + dot->rec_len = 12; // align4(8+1) + dot->name_len = 1; + dot->file_type = EXT2_FT_DIR; + dot->name[0] = '.'; + + ext2_dir_entry_t* dotdot = (ext2_dir_entry_t*)(buf + 12); + dotdot->inode = parent_inum; + dotdot->rec_len = (uint16_t)(block_size - 12); + dotdot->name_len = 2; + dotdot->file_type = EXT2_FT_DIR; + dotdot->name[0] = '.'; + dotdot->name[1] = '.'; + + ext2_write_block_raw(phys, buf); + kfree(buf); + + if (!dir_add_entry_internal(parent, parent_inum, inum, name, EXT2_FT_DIR)) { + ext2_free_block_internal(phys); + ext2_free_inode_internal(inum, true); + return false; + } + + // each subdirectory increments the parent's hard link count (the .. link) + parent->i_links_count++; + ext2_write_inode_internal(parent_inum, parent); + + if (out_inum) *out_inum = inum; + ext2_sync(); + return true; +} + +bool ext2_mkdir(ext2_inode_t* parent, uint32_t parent_inum, + const char* name, uint32_t* out_inum) +{ + uint64_t flags; + spinlock_acquire_irqsave(&s_ext2_lock, &flags); + bool resp = ext2_mkdir_internal(parent, parent_inum, name, out_inum); + spinlock_release_irqrestore(&s_ext2_lock, flags); + return resp; +} + +bool ext2_unlink_internal(ext2_inode_t* dir, uint32_t dir_inum, const char* name) { + uint32_t inum = dir_lookup_internal(dir, name); + if (!inum) { printf("EXT2: not found: %s\n", name); return false; } + + ext2_inode_t fi; + if (!ext2_read_inode_internal(inum, &fi)) return false; + + if ((fi.i_mode & 0xF000) == EXT2_S_IFDIR) { + printf("EXT2: is a directory, use rmdir\n"); + return false; + } + if (!dir_remove_entry_internal(dir, dir_inum, name)) return false; + + fi.i_links_count--; + if (fi.i_links_count == 0) { + ext2_free_inode_blocks_internal(&fi); + //fi.i_dtime = (uint32_t)g_Unixseconds; + ext2_write_inode_internal(inum, &fi); + ext2_free_inode_internal(inum, false); + } else { + //fi.i_ctime = (uint32_t)g_Unixseconds; + ext2_write_inode_internal(inum, &fi); + } + ext2_sync(); + return true; +} + +bool ext2_unlink(ext2_inode_t* dir, uint32_t dir_inum, const char* name) { + uint64_t flags; + spinlock_acquire_irqsave(&s_ext2_lock, &flags); + bool resp = ext2_unlink_internal(dir, dir_inum, name); + spinlock_release_irqrestore(&s_ext2_lock, flags); + return resp; +} + +bool ext2_rmdir_internal(ext2_inode_t* parent, uint32_t parent_inum, const char* name) { + uint32_t inum = dir_lookup_internal(parent, name); + if (!inum) { printf("EXT2: not found: %s\n", name); return false; } + + ext2_inode_t dir; + if (!ext2_read_inode_internal(inum, &dir)) return false; + + if ((dir.i_mode & 0xF000) != EXT2_S_IFDIR) { + printf("EXT2: not a directory: %s\n", name); + return false; + } + if (!dir_is_empty_internal(&dir)) { + printf("EXT2: directory not empty: %s\n", name); + return false; + } + + if (!dir_remove_entry_internal(parent, parent_inum, name)) return false; + parent->i_links_count--; + ext2_write_inode_internal(parent_inum, parent); + + ext2_free_inode_blocks_internal(&dir); + dir.i_links_count = 0; + //dir.i_dtime = (uint32_t)g_Unixseconds; + ext2_write_inode_internal(inum, &dir); + ext2_free_inode_internal(inum, true); + + ext2_sync(); + return true; +} + +bool ext2_rmdir(ext2_inode_t* parent, uint32_t parent_inum, const char* name) { + uint64_t flags; + spinlock_acquire_irqsave(&s_ext2_lock, &flags); + bool resp = ext2_rmdir_internal(parent, parent_inum, name); + spinlock_release_irqrestore(&s_ext2_lock, flags); + return resp; +} + +bool ext2_rename_internal(ext2_inode_t* src_dir, uint32_t src_inum, + ext2_inode_t* dst_dir, uint32_t dst_inum, + const char* old_name, const char* new_name) +{ + uint32_t inum = dir_lookup_internal(src_dir, old_name); + if (!inum) { printf("EXT2: not found: %s\n", old_name); return false; } + + ext2_inode_t fi; + if (!ext2_read_inode_internal(inum, &fi)) return false; + bool is_dir = (fi.i_mode & 0xF000) == EXT2_S_IFDIR; + uint8_t ftype = is_dir ? EXT2_FT_DIR : EXT2_FT_REG_FILE; + + // If destination exists, remove it (POSIX rename semantics) + uint32_t existing = dir_lookup_internal(dst_dir, new_name); + if (existing) { + ext2_inode_t ex; + ext2_read_inode_internal(existing, &ex); + if ((ex.i_mode & 0xF000) == EXT2_S_IFDIR) { + if (!dir_is_empty_internal(&ex)) { + printf("EXT2: rename: target dir not empty\n"); + return false; + } + ext2_rmdir_internal(dst_dir, dst_inum, new_name); + } else { + ext2_unlink_internal(dst_dir, dst_inum, new_name); + } + } + + if (!dir_add_entry_internal(dst_dir, dst_inum, inum, new_name, ftype)) return false; + if (!dir_remove_entry_internal(src_dir, src_inum, old_name)) return false; + + // If moving a directory, update its .. entry and adjust link counts + if (is_dir && src_inum != dst_inum) { + uint32_t phys = ext2_block_map_internal(&fi, 0, false); + if (phys) { + uint8_t* buf = kmalloc(block_size); + ext2_read_block_raw(phys, buf); + uint32_t off = 0; + while (off + 8 <= block_size) { + ext2_dir_entry_t* e = (ext2_dir_entry_t*)(buf + off); + if (e->rec_len < 8) break; + if (e->name_len == 2 && e->name[0] == '.' && e->name[1] == '.') { + e->inode = dst_inum; + break; + } + off += e->rec_len; + } + ext2_write_block_raw(phys, buf); + kfree(buf); + } + src_dir->i_links_count--; + ext2_write_inode_internal(src_inum, src_dir); + dst_dir->i_links_count++; + ext2_write_inode_internal(dst_inum, dst_dir); + } + + ext2_sync(); + return true; +} + +bool ext2_rename(ext2_inode_t* src_dir, uint32_t src_inum, + ext2_inode_t* dst_dir, uint32_t dst_inum, + const char* old_name, const char* new_name) +{ + uint64_t flags; + spinlock_acquire_irqsave(&s_ext2_lock, &flags); + bool resp = ext2_rename_internal(src_dir, src_inum, dst_dir, dst_inum, old_name, new_name); + spinlock_release_irqrestore(&s_ext2_lock, flags); + return resp; +} + +// ── symlinks ────────────────────────────────────────────────────────────────── + +bool ext2_symlink_internal(ext2_inode_t* dir, uint32_t dir_inum, + const char* name, const char* target) +{ + if (dir_lookup_internal(dir, name)) { + printf("EXT2: already exists: %s\n", name); + return false; + } + + uint32_t inum = ext2_alloc_inode_internal(false); + if (!inum) return false; + + uint32_t tlen = strlen(target); + + ext2_inode_t inode = {0}; + inode.i_mode = EXT2_S_IFLNK | 0777; + inode.i_links_count = 1; + inode.i_size = tlen; + //inode.i_atime = inode.i_ctime = inode.i_mtime = (uint32_t)g_Unixseconds; + + if (tlen < 60) { + // fast symlink: target stored directly in i_block[] + memcpy(inode.i_block, target, tlen); + inode.i_blocks = 0; + } else { + uint32_t phys = alloc_zero_block_internal(); + if (!phys) { ext2_free_inode_internal(inum, false); return false; } + uint8_t* buf = kmalloc(block_size); + memset(buf, 0, block_size); + memcpy(buf, target, tlen); + ext2_write_block_raw(phys, buf); + kfree(buf); + inode.i_block[0] = phys; + inode.i_blocks = block_size / 512; + } + ext2_write_inode_internal(inum, &inode); + + if (!dir_add_entry_internal(dir, dir_inum, inum, name, EXT2_FT_SYMLINK)) { + ext2_free_inode_internal(inum, false); + return false; + } + ext2_sync(); + return true; +} + +bool ext2_symlink(ext2_inode_t* dir, uint32_t dir_inum, + const char* name, const char* target) +{ + uint64_t flags; + spinlock_acquire_irqsave(&s_ext2_lock, &flags); + bool resp = ext2_symlink_internal(dir, dir_inum, name, target); + spinlock_release_irqrestore(&s_ext2_lock, flags); + return resp; +} + +bool ext2_readlink_internal(uint32_t inum, char* buf, uint32_t buf_size) { + ext2_inode_t inode; + if (!ext2_read_inode_internal(inum, &inode)) return false; + if ((inode.i_mode & 0xF000) != EXT2_S_IFLNK) return false; + + uint32_t tlen = inode.i_size; + if (tlen >= buf_size) tlen = buf_size - 1; + + if (inode.i_size < 60) { + memcpy(buf, inode.i_block, tlen); + } else { + uint8_t* tmp = kmalloc(block_size); + ext2_read_block_raw(inode.i_block[0], tmp); + memcpy(buf, tmp, tlen); + kfree(tmp); + } + buf[tlen] = '\0'; + return true; +} + +bool ext2_readlink(uint32_t inum, char* buf, uint32_t buf_size) { + uint64_t flags; + spinlock_acquire_irqsave(&s_ext2_lock, &flags); + bool resp = ext2_readlink_internal(inum, buf, buf_size); + spinlock_release_irqrestore(&s_ext2_lock, flags); + return resp; +} + +// ── metadata ───────────────────────────────────────────────────────────────── + +bool ext2_stat_internal(uint32_t inum, ext2_stat_t* st) { + ext2_inode_t inode; + if (!ext2_read_inode_internal(inum, &inode)) return false; + st->ino = inum; + st->mode = inode.i_mode; + st->uid = inode.i_uid; + st->gid = inode.i_gid; + st->size = inode.i_size; + st->atime = inode.i_atime; + st->mtime = inode.i_mtime; + st->ctime = inode.i_ctime; + st->nlink = inode.i_links_count; + st->blocks = inode.i_blocks; + return true; +} + +bool ext2_stat(uint32_t inum, ext2_stat_t* st) { + uint64_t flags; + spinlock_acquire_irqsave(&s_ext2_lock, &flags); + bool resp = ext2_stat_internal(inum, st); + spinlock_release_irqrestore(&s_ext2_lock, flags); + return resp; +} + + +bool ext2_chmod_internal(uint32_t inum, uint16_t mode) { + ext2_inode_t inode; + if (!ext2_read_inode_internal(inum, &inode)) return false; + inode.i_mode = (inode.i_mode & 0xF000) | (mode & 0x0FFF); + //inode.i_ctime = (uint32_t)g_Unixseconds; + return ext2_write_inode_internal(inum, &inode); +} + +bool ext2_chown_internal(uint32_t inum, uint16_t uid, uint16_t gid) { + ext2_inode_t inode; + if (!ext2_read_inode_internal(inum, &inode)) return false; + inode.i_uid = uid; + inode.i_gid = gid; + //inode.i_ctime = (uint32_t)g_Unixseconds; + return ext2_write_inode_internal(inum, &inode); +} + +bool ext2_chmod(uint32_t inum, uint16_t mode) { + uint64_t flags; + spinlock_acquire_irqsave(&s_ext2_lock, &flags); + bool resp = ext2_chmod_internal(inum, mode); + spinlock_release_irqrestore(&s_ext2_lock, flags); + return resp; +} + +bool ext2_chown(uint32_t inum, uint16_t uid, uint16_t gid) { + uint64_t flags; + spinlock_acquire_irqsave(&s_ext2_lock, &flags); + bool resp = ext2_chown_internal(inum, uid, gid); + spinlock_release_irqrestore(&s_ext2_lock, flags); + return resp; +} \ No newline at end of file diff --git a/src/fs/ext2.h b/src/fs/ext2.h new file mode 100644 index 0000000..36a120d --- /dev/null +++ b/src/fs/ext2.h @@ -0,0 +1,220 @@ +#pragma once +#include +#include + +#define EXT2_SUPERBLOCK_OFFSET 1024 +#define EXT2_SUPERBLOCK_SIZE 1024 +#define EXT2_MAGIC 0xEF53 +#define EXT2_NAME_LEN 255 + +typedef struct ext2_superblock { + unsigned int s_inodes_count; /* Inodes count */ + unsigned int s_blocks_count; /* Blocks count */ + unsigned int s_r_blocks_count; /* Reserved blocks count */ + unsigned int s_free_blocks_count; /* Free blocks count */ + unsigned int s_free_inodes_count; /* Free inodes count */ + unsigned int s_first_data_block; /* First Data Block */ + unsigned int s_log_block_size; /* Block size */ + unsigned int s_log_frag_size; /* Fragment size */ + unsigned int s_blocks_per_group; /* # Blocks per group */ + unsigned int s_frags_per_group; /* # Fragments per group */ + unsigned int s_inodes_per_group; /* # Inodes per group */ + unsigned int s_mtime; /* Mount time */ + unsigned int s_wtime; /* Write time */ + unsigned short s_mnt_count; /* Mount count */ + unsigned short s_max_mnt_count; /* Maximal mount count */ + unsigned short s_magic; /* Magic signature */ + unsigned short s_state; /* File system state */ + unsigned short s_errors; /* Behaviour when detecting errors */ + unsigned short s_minor_rev_level; /* minor revision level */ + unsigned int s_lastcheck; /* time of last check */ + unsigned int s_checkinterval; /* max. time between checks */ + unsigned int s_creator_os; /* OS */ + unsigned int s_rev_level; /* Revision level */ + unsigned short s_def_resuid; /* Default uid for reserved blocks */ + unsigned short s_def_resgid; /* Default gid for reserved blocks */ + /* + * These fields are for EXT2_DYNAMIC_REV superblocks only. + * + * Note: the difference between the compatible feature set and + * the incompatible feature set is that if there is a bit set + * in the incompatible feature set that the kernel doesn't + * know about, it should refuse to mount the filesystem. + * + * e2fsck's requirements are more strict; if it doesn't know + * about a feature in either the compatible or incompatible + * feature set, it must abort and not try to meddle with + * things it doesn't understand... + */ + unsigned int s_first_ino; /* First non-reserved inode */ + unsigned short s_inode_size; /* size of inode structure */ + unsigned short s_block_group_nr; /* block group # of this superblock */ + unsigned int s_feature_compat; /* compatible feature set */ + unsigned int s_feature_incompat; /* incompatible feature set */ + unsigned int s_feature_ro_compat; /* readonly-compatible feature set */ + unsigned char s_uuid[16]; /* 128-bit uuid for volume */ + char s_volume_name[16]; /* volume name */ + char s_last_mounted[64]; /* directory where last mounted */ + unsigned int s_algorithm_usage_bitmap; /* For compression */ + /* + * Performance hints. Directory preallocation should only + * happen if the EXT2_COMPAT_PREALLOC flag is on. + */ + unsigned char s_prealloc_blocks; /* Nr of blocks to try to preallocate*/ + unsigned char s_prealloc_dir_blocks; /* Nr to preallocate for dirs */ + unsigned short s_padding1; + /* + * Journaling support valid if EXT3_FEATURE_COMPAT_HAS_JOURNAL set. + */ + unsigned char s_journal_uuid[16]; /* uuid of journal superblock */ + unsigned int s_journal_inum; /* inode number of journal file */ + unsigned int s_journal_dev; /* device number of journal file */ + unsigned int s_last_orphan; /* start of list of inodes to delete */ + unsigned int s_hash_seed[4]; /* HTREE hash seed */ + unsigned char s_def_hash_version; /* Default hash version to use */ + unsigned char s_reserved_char_pad; + unsigned short s_reserved_word_pad; + unsigned int s_default_mount_opts; + unsigned int s_first_meta_bg; /* First metablock block group */ + unsigned int s_reserved[190]; /* Padding to the end of the block */ +} __attribute__((packed)) ext2_superblock_t; + +typedef struct ext2_group_desc { + unsigned int bg_block_bitmap; /* Blocks bitmap block */ + unsigned int bg_inode_bitmap; /* Inodes bitmap block */ + unsigned int bg_inode_table; /* Inodes table block */ + unsigned short bg_free_blocks_count; /* Free blocks count */ + unsigned short bg_free_inodes_count; /* Free inodes count */ + unsigned short bg_used_dirs_count; /* Directories count */ + unsigned short bg_pad; + unsigned int bg_reserved[3]; +} __attribute__((packed)) ext2_group_desc_t; + +typedef struct ext2_inode { + unsigned short i_mode; /* File mode */ + unsigned short i_uid; /* Low 16 bits of Owner Uid */ + unsigned int i_size; /* Size in bytes */ + unsigned int i_atime; /* Access time */ + unsigned int i_ctime; /* Creation time */ + unsigned int i_mtime; /* Modification time */ + unsigned int i_dtime; /* Deletion Time */ + unsigned short i_gid; /* Low 16 bits of Group Id */ + unsigned short i_links_count; /* Links count */ + unsigned int i_blocks; /* Blocks count IN DISK SECTORS*/ + unsigned int i_flags; /* File flags */ + unsigned int osd1; /* OS dependent 1 */ + unsigned int i_block[15]; /* Pointers to blocks */ + unsigned int i_generation; /* File version (for NFS) */ + unsigned int i_file_acl; /* File ACL */ + unsigned int i_dir_acl; /* Directory ACL */ + unsigned int i_faddr; /* Fragment address */ + unsigned int extra[3]; +} __attribute__((packed)) ext2_inode_t; + +typedef struct ext2_dir_entry { + unsigned int inode; /* Inode number */ + unsigned short rec_len; /* Directory entry length */ + unsigned char name_len; /* Name length */ + unsigned char file_type; + char name[]; /* File name, up to EXT2_NAME_LEN */ +} __attribute__((packed)) ext2_dir_entry_t; + +typedef struct { + uint32_t ino; + uint16_t mode; + uint16_t uid; + uint16_t gid; + uint32_t size; + uint32_t atime; + uint32_t mtime; + uint32_t ctime; + uint32_t nlink; + uint32_t blocks; +} ext2_stat_t; + +typedef enum { + EXT2_WRITE_OVERWRITE, + EXT2_WRITE_APPEND, +} ext2_write_mode_t; + +// Inode type and permissions +#define EXT2_S_IFIFO 0x1000 +#define EXT2_S_IFCHR 0x2000 +#define EXT2_S_IFDIR 0x4000 +#define EXT2_S_IFBLK 0x6000 +#define EXT2_S_IFREG 0x8000 +#define EXT2_S_IFLNK 0xA000 +#define EXT2_S_IFSOCK 0xC000 + +#define EXT2_S_IRUSR 0x0100 +#define EXT2_S_IWUSR 0x0080 +#define EXT2_S_IXUSR 0x0040 +#define EXT2_S_IRGRP 0x0020 +#define EXT2_S_IWGRP 0x0010 +#define EXT2_S_IXGRP 0x0008 +#define EXT2_S_IROTH 0x0004 +#define EXT2_S_IWOTH 0x0002 +#define EXT2_S_IXOTH 0x0001 + +// File types for directory entries +#define EXT2_FT_UNKNOWN 0 +#define EXT2_FT_REG_FILE 1 +#define EXT2_FT_DIR 2 +#define EXT2_FT_CHRDEV 3 +#define EXT2_FT_BLKDEV 4 +#define EXT2_FT_FIFO 5 +#define EXT2_FT_SOCK 6 +#define EXT2_FT_SYMLINK 7 + + + + +// ── init ────────────────────────────────────────────────────────────────────── +bool ext2_read_superblock(void); +bool ext2_read_group_desc_table(void); + +// ── low-level ──────────────────────────────────────────────────────────────── +bool ext2_read_block(uint32_t block_num, void* buf); +bool ext2_write_block(uint32_t block_num, const void* buf); +bool ext2_read_inode(uint32_t inode_num, ext2_inode_t* out); +bool ext2_write_inode(uint32_t inode_num, ext2_inode_t* inode); + +// ── path / directory ───────────────────────────────────────────────────────── +uint32_t ext2_resolve_path(const char* path); // returns inode num, 0 = not found +bool ext2_find_in_dir(ext2_inode_t* dir, const char* name, uint32_t* out_inum); +bool ext2_read_dir(ext2_inode_t* dir); +bool ext2_read_root_dir(void); + +// ── file I/O ───────────────────────────────────────────────────────────────── +bool ext2_read_file(ext2_inode_t* inode, uint8_t* buf); +bool ext2_write_file(ext2_inode_t* inode, uint32_t inode_num, + const uint8_t* data, uint32_t size, ext2_write_mode_t mode); +bool ext2_truncate(ext2_inode_t* inode, uint32_t inode_num, uint32_t new_size); + +// ── high-level (operate from a path string) ─────────────────────────────────── +bool ext2_read_file_from_root(const char* name, uint8_t* buf, uint32_t* size); +bool ext2_write_file_from_root(const char* name, const uint8_t* data, + uint32_t size, ext2_write_mode_t mode); + +// ── create / delete ─────────────────────────────────────────────────────────── +bool ext2_create_file(ext2_inode_t* dir, uint32_t dir_inum, + const char* name, uint32_t* out_inum); +bool ext2_mkdir(ext2_inode_t* parent, uint32_t parent_inum, + const char* name, uint32_t* out_inum); +bool ext2_unlink(ext2_inode_t* dir, uint32_t dir_inum, const char* name); +bool ext2_rmdir(ext2_inode_t* parent, uint32_t parent_inum, const char* name); +bool ext2_rename(ext2_inode_t* src_dir, uint32_t src_inum, + ext2_inode_t* dst_dir, uint32_t dst_inum, + const char* old_name, const char* new_name); + +// ── symlinks ────────────────────────────────────────────────────────────────── +bool ext2_symlink(ext2_inode_t* dir, uint32_t dir_inum, + const char* name, const char* target); +bool ext2_readlink(uint32_t inode_num, char* buf, uint32_t buf_size); + +// ── metadata ───────────────────────────────────────────────────────────────── +bool ext2_stat(uint32_t inode_num, ext2_stat_t* st); +bool ext2_chmod(uint32_t inode_num, uint16_t mode); +bool ext2_chown(uint32_t inode_num, uint16_t uid, uint16_t gid); + +const char* ext2_file_type_string(uint8_t type); \ No newline at end of file diff --git a/src/fs/vfs.c b/src/fs/vfs.c new file mode 100644 index 0000000..09b80f4 --- /dev/null +++ b/src/fs/vfs.c @@ -0,0 +1,147 @@ +#include "vfs.h" +#include