Compare commits

...

108 Commits

Author SHA1 Message Date
iProgramInCpp e63d804f6f limine: Fix two other small typos in PROTOCOL.md 2023-10-29 04:37:09 +01:00
mintsuki cad3c72fce config: Fix bug where macro definitions were not skipped over properly when parsing 2023-10-29 04:27:04 +01:00
ミンツキ 7cd46f3d26
Merge pull request #314 from iProgramMC/fix-typo-in-protocol-1
limine: Fix a small typo error in PROTOCOL.md
2023-10-28 20:03:13 +02:00
iProgramInCpp f4051f49db
limine: Fix a small typo error in PROTOCOL.md
This corrects an error which mistakenly says "the an Entry Point request (...)", in the section where the machine state at entry into the kernel is described.
2023-10-28 17:48:30 +03:00
mintsuki a5051f92bf build: Changes to comply more with the GNU build system - adds ChangeLog 2023-10-28 05:16:45 +02:00
mintsuki ec564407da docs: Update example Limine version in README to 5.20231024.0 2023-10-24 18:50:28 +02:00
mintsuki a0127f9f40 pmm: Add MEMMAP_MAX macro and use it instead of hardcoding 256 2023-10-24 18:38:18 +02:00
mintsuki e49865a467 lib/time: EFI: Return time of 0 if GetTime() unsupported 2023-10-24 18:38:18 +02:00
48cf 2bba72634f lib/gterm: Try to initialize all 32-bpp framebuffers 2023-10-24 18:38:18 +02:00
48cf 45b39285f1 pmm: Ignore allow_high_allocs on non x86-64 architectures 2023-10-24 18:38:18 +02:00
mintsuki a795dc1972 build: Backport misc autoconf/pkgconf improvements 2023-10-24 01:21:24 +02:00
mintsuki c1860c8d80 limine/ioapic: Change spec to avoid masking IOAPIC RTEs unless Fixed or Lowest Priority 2023-10-24 01:21:24 +02:00
mintsuki 49cfba851c build: Misc minor QOL configure.ac/GNUmakefile.in improvements 2023-10-24 01:21:24 +02:00
mintsuki b348bb75e7 docs: Update example Limine version in README to 5.20231006.0 2023-10-06 12:25:44 -05:00
mintsuki c1f5b21177 misc: Remove unnecessary ifdefs added in previous commits 2023-10-06 12:25:44 -05:00
mintsuki b474b6bad0 misc: Only allocate memory and modules above 4GiB on 64-bit platforms 2023-10-06 12:25:44 -05:00
mintsuki 5323bce117 pmm: Allow allocations above 4GiB and use them in freadall() 2023-10-06 12:25:44 -05:00
mintsuki 1bcbf817ed docs: Update example Limine version in README to 5.20230928.2 2023-09-28 17:49:31 -05:00
mintsuki f81b9d2dc3 build: Fix makefile target dependencies bug introduced in a0c2f95 2023-09-28 17:49:31 -05:00
mintsuki d0a1285feb docs: Update example Limine version in README to 5.20230928.1 2023-09-28 16:26:32 -05:00
mintsuki a0c2f95a1d build: Fix bug introduced in 7885f260 due to a misunderstanding of an objcopy flag 2023-09-28 16:03:13 -05:00
mintsuki d421ebcb58 docs: Update example Limine version in README to 5.20230928.0 2023-09-28 06:56:28 -05:00
mintsuki 7117b85c86 build: Fix indentation issue in common/GNUmakefile 2023-09-28 06:56:28 -05:00
mintsuki 3a81c3e13d build: ldscripts: .reloc -> .dummy_reloc 2023-09-28 06:56:28 -05:00
mintsuki a0997a598b build: Fix race conditions introduced in 22d45a5428 2023-09-28 06:56:28 -05:00
mintsuki 212dbd32c1 misc: Add .note.GNU-stack where it was still missing 2023-09-28 06:56:28 -05:00
mintsuki a55f68b3bd smp: riscv64: Replace .insn directive with .4byte 2023-09-28 06:56:28 -05:00
mintsuki a83dafe6f4 misc: Add section .note.GNU-stack to assembly files 2023-09-28 06:56:28 -05:00
mintsuki afdc556301 time: Change signature of get_jdn() to use int types 2023-09-28 06:56:28 -05:00
mintsuki bfc518cc07 docs: Update example Limine version in README to 5.20230924.0 2023-09-24 02:03:59 -05:00
mintsuki 81c39fc080 elf: Panic if there are PHDRs with different perms sharing same page 2023-09-24 01:56:50 -05:00
mintsuki 87a88bf565 smp: Remove dead 32-bit trampoline code 2023-09-23 17:37:38 -05:00
mintsuki 3fde8f0158 docs: PROTOCOL.md: Fix up layout of mappings table 2023-09-22 16:54:15 -05:00
mintsuki 50f4383f93 limine: Make explicit some implied padding in some structures 2023-09-22 16:40:07 -05:00
mintsuki c7df84e237 test: riscv64: Fix issue with OVMF not working on latest QEMU 2023-09-22 16:39:59 -05:00
mintsuki f1236373fe menu: Fix padding issue introduced in e1d25f8 2023-09-22 16:39:51 -05:00
mintsuki a36de776a7 docs: Update example Limine version in README to 5.20230917.0 2023-09-16 17:14:13 -05:00
mintsuki a0fb5a04d3 docs: PROTOCOL.md: Backport caching section from trunk 2023-09-16 16:31:16 -05:00
mintsuki 042a6e9554 misc: Backports from trunk 2023-09-16 15:12:14 -05:00
mintsuki c5c43cb0fd misc: aarch64: Remove unused enter_in_current_el() function 2023-09-16 14:28:33 -05:00
mintsuki 5f7bcc0b1d riscv: Fix cherry-picking issue introduced in e3d65aa628 2023-09-16 11:35:43 -05:00
mintsuki 45958f7162 misc: Consistently call x86-64 such, instead of x86_64 2023-09-16 11:31:35 -05:00
mintsuki e9b5511084 docs: PROTOCOL.md: Minor fixes 2023-09-16 11:31:19 -05:00
xvanc f4bfe1289a riscv: skip `rv{32,64}` prefix when parsing extensions from isa strings 2023-09-16 11:28:15 -05:00
xvanc cdac49ebfb acpi: remove duplicate definition in sys/lapic.c 2023-09-16 11:28:15 -05:00
xvanc 90b82dc43f riscv/vmm: use Svpbmt extension when available 2023-09-16 11:28:15 -05:00
xvanc e3d65aa628 riscv: refactor smp init 2023-09-16 11:28:15 -05:00
xvanc f33732a2e5 riscv: implement feature dectection 2023-09-16 11:21:17 -05:00
xvanc 09c430f286 lib/libc: add misc utilities 2023-09-16 11:21:17 -05:00
xvanc 2200161e7d acpi: move acpi structure defs to lib/acpi.h 2023-09-16 11:21:17 -05:00
mintsuki f8bfe41e71 test: Use -dumpmachine to find architecture instead of expecting -target 2023-09-11 17:16:19 -05:00
mintsuki 0f7ee05635 misc/bios: Update and improve linker script and related files 2023-09-11 17:16:19 -05:00
mintsuki b54c3fc9cc protos/chainload: Fix bug that could result in bogus oom errors. Fixes #302 2023-09-11 17:16:19 -05:00
mintsuki 756dd235ea decompressor: Mark .entry section with proper flags in entry.asm 2023-09-11 17:16:19 -05:00
mintsuki 09c87feaee decompressor: Add rodata PHDR and section to ld script 2023-09-11 17:16:19 -05:00
Kacper Słomiński 916aa370b2 protos: chainload: Allocate memory for the null terminator in cmdline 2023-09-11 17:16:19 -05:00
mintsuki 0ebf0245df misc: Misc EFI linker script improvements and drop .sbat 2023-09-11 17:16:19 -05:00
mintsuki 8f789fc0ae docs: Update example Limine version in README to 5.20230909.0 2023-09-09 16:08:08 -05:00
mintsuki b5cffbb6e8 misc: Improve UEFI linker scripts 2023-09-09 15:57:38 -05:00
mintsuki 9ff62c2a62 docs: README.md: Fix minor grammar mistake 2023-09-09 10:08:44 -05:00
mintsuki 68f82c3d30 stage1/gdt: Mark accessed flag in descriptors 2023-09-09 10:08:44 -05:00
mintsuki 2642249edd docs: Remove references to shim as we don't directly support it 2023-09-09 10:08:44 -05:00
mintsuki e6a67c80a6 x86/gdt: Mark accessed flag in descriptors 2023-09-09 10:08:44 -05:00
mintsuki 541dbd265c docs: Update example Limine version in README to 5.20230830.0 2023-08-29 22:34:47 -05:00
mintsuki e207c03f69 build: Drop -mabi=sysv for x86 for clang 16 2023-08-29 22:34:27 -05:00
mintsuki 57e4ae6e25 config: Disable editor by default if config b2sum present. Fixes #296 2023-08-29 22:34:20 -05:00
mintsuki a30cad3556 menu: Change menu arrow to use unicode big arrow 2023-08-29 22:34:15 -05:00
mintsuki ac0d9465f5 gterm: Update font's big left and right arrows 2023-08-29 22:34:11 -05:00
mintsuki f0b899b5bc docs: Update example Limine version in README to 5.20230819.0 2023-08-19 08:43:54 -05:00
mintsuki 4abedffb43 disk: BIOS: Skip drive if sector size is 0. Fixes #294 2023-08-19 08:20:45 -05:00
Kacper Słomiński 50dab6c2f1 smp: aarch64: Don't needlessly invalidate the data cache
Also get rid of the function to do clean + invalidate as not to be
tempted by it.
2023-08-18 13:38:14 -05:00
Kacper Słomiński ba5d63b82a elf: aarch64: Don't needlessly invalidate the data cache
Cleaning the data cache to PoC without invalidating it is enough when
invalidating the instruction cache to PoU.
2023-08-18 13:37:55 -05:00
mintsuki 573d0095bf elf: elf64_load_section(): Return false early if sh_num == 0 2023-08-18 13:37:39 -05:00
mintsuki 27a32e416c disk: Add additional volume_index_i overflow guards 2023-08-18 13:37:16 -05:00
mintsuki 9a074530a9 exceptions: Change naming of exceptions in panic message 2023-08-18 13:36:58 -05:00
mintsuki a248b557bb docs: Update example Limine version in README to 5.20230811.0 2023-08-11 10:31:14 -05:00
mintsuki d66df6b38a limine: Do not return SMBIOS response if not present 2023-08-10 19:26:54 -05:00
mintsuki 1e9a42e7ce test: General makefile updates 2023-08-08 14:09:31 -05:00
mintsuki b8fff872de test: Use Flanterm 2023-08-08 14:09:19 -05:00
mekb 820d4751d3 menu: Add option to hide help text 2023-08-08 14:09:11 -05:00
xvanc 82ea6d6a57 test/riscv: disable linker relaxation, specify ISA string and ABI
Although linker relaxation is disabled, the compiler still emits small
data sections which must be explicitly included in the linker script.
2023-08-04 07:22:12 -05:00
xvanc 030242d69a vmm/riscv: fix bug in `vmm_max_paging_mode()` 2023-08-03 20:12:51 -05:00
mintsuki b64335f62a docs: Update example Limine version in README to 5.20230801.0 2023-08-01 05:32:12 -05:00
mintsuki 50b8ab2c26 rv64: Misc relaxation related fixes 2023-08-01 05:32:05 -05:00
mintsuki 2d0752f60c docs: Update example Limine version in README to 5.20230729.0 2023-07-29 12:00:19 -05:00
mintsuki ff86be6be6 misc: Update test wallpaper and screenshot 2023-07-29 11:55:37 -05:00
mintsuki 2f1dac0600 gterm: Change resolutions at which autoscaling is triggered 2023-07-29 11:55:37 -05:00
mintsuki 0ecb2ab895 menu: Center menu vertically 2023-07-29 11:55:37 -05:00
mintsuki 474fc105a5 gop: Readd preset mode storage 2023-07-29 11:55:37 -05:00
mintsuki 418f8d7280 menu: Do not draw box around boot menu 2023-07-29 02:17:12 -05:00
mintsuki 722bde2cbc menu: Adjust centering by 2 characters to the left 2023-07-28 04:26:48 -05:00
mintsuki 5bdb1bbf55 menu: Fix a couple of boot menu alignment issues 2023-07-28 04:26:48 -05:00
mintsuki 8f167bc2e5 menu: Initialise max_len if null regardless of shift 2023-07-28 04:26:48 -05:00
mintsuki d73cd37834 menu: Fix maybe uninitialised issue with cur_len var 2023-07-28 04:26:48 -05:00
mintsuki 478b6f3806 menu: Fix NULL deref bug with shift variable 2023-07-28 04:26:48 -05:00
mintsuki 4b452e69a4 console: Add slide command 2023-07-28 04:26:48 -05:00
mintsuki 98f30bfdd6 menu: Center boot menu 2023-07-28 04:26:48 -05:00
mintsuki ba2597605b Revert "build: Make limine-uefi-cd.bin 16MiB in size (use FAT16)"
This reverts commit 2da0a08072.
2023-07-28 04:26:48 -05:00
mintsuki 9921af54d0 gterm: Autoscale font on higher resolutions 2023-07-28 04:26:48 -05:00
Kacper Słomiński a2e502328d limine: Adjust higher half offsets for AArch64 2023-07-26 17:05:43 -05:00
Kacper Słomiński dc68fcaff7 limine: Use a higher-half pointer for the stack on AArch64 2023-07-26 17:05:33 -05:00
mintsuki f365a46617 misc: Minor updates to linker scripts 2023-07-26 17:05:20 -05:00
mintsuki 871a8053c2 build: Get rid of OBJCOPY2ELF_FLAGS since only IA-32/BIOS used it 2023-07-26 17:05:06 -05:00
mintsuki 49ecb6b577 build: Get rid of RISCV_CFLAGS variable as it is now unnecessary 2023-07-26 17:04:54 -05:00
mintsuki 997e2c756a ci: Remove openssh dependency no longer required for release 2023-07-26 17:04:46 -05:00
mintsuki bc1896c5bb riscv64: Do not use global pointer register 2023-07-26 17:04:30 -05:00
mintsuki e261a96fa4 docs/protocol: Fix typo and mandate ra and gp registers to be 0 for rv64 2023-07-26 17:04:21 -05:00
mintsuki 1f82dd89c7 host/limine: Fix typo 2023-07-26 17:03:52 -05:00
97 changed files with 1598 additions and 1118 deletions

View File

@ -22,7 +22,7 @@ jobs:
run: ./bootstrap && ./configure TOOLCHAIN_FOR_TARGET=llvm --enable-werror --enable-all && make all && make maintainer-clean
- name: Build the bootloader (GNU, x86)
run: ./bootstrap && ./configure TOOLCHAIN_FOR_TARGET=gnu --enable-werror --enable-bios --enable-uefi-ia32 --enable-uefi-x86_64 && make all && make maintainer-clean
run: ./bootstrap && ./configure TOOLCHAIN_FOR_TARGET=gnu --enable-werror --enable-bios --enable-uefi-ia32 --enable-uefi-x86-64 && make all && make maintainer-clean
- name: Build the bootloader (GNU, aarch64)
run: ./bootstrap && ./configure TOOLCHAIN_FOR_TARGET=aarch64-linux-gnu --enable-werror --enable-uefi-aarch64 && make all && make maintainer-clean

View File

@ -13,7 +13,7 @@ jobs:
steps:
- name: Install dependencies
run: pacman --noconfirm -Syu && pacman --needed --noconfirm -S base-devel git autoconf automake nasm curl mtools llvm clang lld mingw-w64-gcc openssh
run: pacman --noconfirm -Syu && pacman --needed --noconfirm -S base-devel git autoconf automake nasm curl mtools llvm clang lld mingw-w64-gcc
- name: Checkout code
uses: actions/checkout@v3
@ -51,7 +51,7 @@ jobs:
run: i686-w64-mingw32-strip build/bin/limine.exe
- name: Copy LICENSE to bin
run: cp LICENSE build/bin/
run: cp COPYING build/bin/LICENSE
- name: Copy install-sh to bin
run: cp build-aux/install-sh build/bin/

2
.gitignore vendored
View File

@ -29,7 +29,9 @@
/freestanding-toolchain
/configure
/configure.ac.save
/INSTALL
/build-aux
/aclocal.m4
/*~
/config.status
/config.log

View File

@ -69,6 +69,7 @@ Limine interface control options.
* `INTERFACE_BRANDING` - A string that will be displayed on top of the Limine interface.
* `INTERFACE_BRANDING_COLOUR` - A value between 0 and 7 specifying the colour of the branding string. Default is cyan (6).
* `INTERFACE_BRANDING_COLOR` - Alias of `INTERFACE_BRANDING_COLOUR`.
* `INTERFACE_HELP_HIDDEN` - Hides the help text located at the top of the screen showing the key bindings.
Limine graphical terminal control options. They are ignored if using text mode.

View File

View File

@ -11,7 +11,7 @@ override datarootdir := @datarootdir@
override mandir := @mandir@
override docdir := @docdir@
override NATIVE_STRIP := @NATIVE_STRIP@
override STRIP := @STRIP@
DESTDIR ?=
@ -72,15 +72,18 @@ export AWK
override DEFAULT_CPPFLAGS := @CPPFLAGS@
$(eval $(call DEFAULT_VAR,CPPFLAGS,$(DEFAULT_CPPFLAGS)))
override CPPFLAGS := @PKGCONF_CPPFLAGS@ $(CPPFLAGS)
export CPPFLAGS
override DEFAULT_CFLAGS := @CFLAGS@
$(eval $(call DEFAULT_VAR,CFLAGS,$(DEFAULT_CFLAGS)))
override CFLAGS += @PKGCONF_CFLAGS@
export CFLAGS
override DEFAULT_LDFLAGS := @LDFLAGS@
$(eval $(call DEFAULT_VAR,LDFLAGS,$(DEFAULT_LDFLAGS)))
export LDFLAGS
override DEFAULT_LIBS := @LIBS@
$(eval $(call DEFAULT_VAR,LIBS,$(DEFAULT_LIBS)))
override LIBS += @PKGCONF_LIBS@
export LIBS
override WERROR_FLAG := @WERROR_FLAG@
@ -138,7 +141,7 @@ clean: limine-bios-clean limine-uefi-ia32-clean limine-uefi-x86-64-clean limine-
.PHONY: install
install: all
$(INSTALL) -d '$(call SHESCAPE,$(DESTDIR)$(docdir))'
$(INSTALL_DATA) '$(call SHESCAPE,$(SRCDIR))/LICENSE' '$(call SHESCAPE,$(DESTDIR)$(docdir))/'
$(INSTALL_DATA) '$(call SHESCAPE,$(SRCDIR))/COPYING' '$(call SHESCAPE,$(DESTDIR)$(docdir))/'
$(INSTALL_DATA) '$(call SHESCAPE,$(SRCDIR))/CONFIG.md' '$(call SHESCAPE,$(DESTDIR)$(docdir))/'
$(INSTALL_DATA) '$(call SHESCAPE,$(SRCDIR))/PROTOCOL.md' '$(call SHESCAPE,$(DESTDIR)$(docdir))/'
$(INSTALL_DATA) '$(call SHESCAPE,$(SRCDIR))/PHILOSOPHY.md' '$(call SHESCAPE,$(DESTDIR)$(docdir))/'
@ -178,11 +181,11 @@ endif
.PHONY: install-strip
install-strip: install
$(NATIVE_STRIP) '$(call SHESCAPE,$(DESTDIR)$(bindir))/limine'
$(STRIP) '$(call SHESCAPE,$(DESTDIR)$(bindir))/limine'
.PHONY: uninstall
uninstall:
rm -f '$(call SHESCAPE,$(DESTDIR)$(docdir))/LICENSE'
rm -f '$(call SHESCAPE,$(DESTDIR)$(docdir))/COPYING'
rm -f '$(call SHESCAPE,$(DESTDIR)$(docdir))/CONFIG.md'
rm -f '$(call SHESCAPE,$(DESTDIR)$(docdir))/PROTOCOL.md'
rm -f '$(call SHESCAPE,$(DESTDIR)$(docdir))/PHILOSOPHY.md'
@ -212,8 +215,8 @@ $(call MKESCAPE,$(BINDIR))/limine-uefi-cd.bin: $(if $(BUILD_UEFI_IA32),$(call MK
ifneq ($(BUILD_UEFI_CD),no)
$(MKDIR_P) '$(call SHESCAPE,$(BINDIR))'
rm -f '$(call SHESCAPE,$(BINDIR))/limine-uefi-cd.bin'
dd if=/dev/zero of='$(call SHESCAPE,$(BINDIR))/limine-uefi-cd.bin' bs=1M count=0 seek=16 2>/dev/null
( mformat -i '$(call SHESCAPE,$(BINDIR))/limine-uefi-cd.bin' :: && \
dd if=/dev/zero of='$(call SHESCAPE,$(BINDIR))/limine-uefi-cd.bin' bs=512 count=2880 2>/dev/null
( mformat -i '$(call SHESCAPE,$(BINDIR))/limine-uefi-cd.bin' -f 1440 :: && \
mmd -D s -i '$(call SHESCAPE,$(BINDIR))/limine-uefi-cd.bin' ::/EFI && \
mmd -D s -i '$(call SHESCAPE,$(BINDIR))/limine-uefi-cd.bin' ::/EFI/BOOT && \
( ( [ -f '$(call SHESCAPE,$(BUILDDIR))/common-uefi-aarch64/BOOTAA64.EFI' ] && \
@ -288,6 +291,7 @@ dist:
$(MKDIR_P) '$(call SHESCAPE,$(BUILDDIR))'/"limine-$(LIMINE_VERSION)"
cp -r '$(call SHESCAPE,$(SRCDIR))'/.git '$(call SHESCAPE,$(BUILDDIR))'/"limine-$(LIMINE_VERSION)"/
cd '$(call SHESCAPE,$(BUILDDIR))'/"limine-$(LIMINE_VERSION)" && git checkout .
cd '$(call SHESCAPE,$(BUILDDIR))'/"limine-$(LIMINE_VERSION)" && git log --oneline --decorate > ChangeLog
cd '$(call SHESCAPE,$(BUILDDIR))'/"limine-$(LIMINE_VERSION)" && ./bootstrap
rm -rf '$(call SHESCAPE,$(BUILDDIR))'/"limine-$(LIMINE_VERSION)/common/flanterm/.git"
rm -rf '$(call SHESCAPE,$(BUILDDIR))'/"limine-$(LIMINE_VERSION)/freestanding-headers/.git"
@ -322,7 +326,7 @@ distclean: clean
.PHONY: maintainer-clean
maintainer-clean: distclean
cd '$(call SHESCAPE,$(SRCDIR))' && rm -rf common/flanterm common/stb/stb_image.h decompressor/tinf freestanding-headers libgcc-binaries limine-efi freestanding-toolchain configure build-aux *'~' autom4te.cache *.tar.xz *.tar.gz
cd '$(call SHESCAPE,$(SRCDIR))' && rm -rf common/flanterm common/stb/stb_image.h decompressor/tinf freestanding-headers libgcc-binaries limine-efi freestanding-toolchain configure INSTALL build-aux *'~' autom4te.cache aclocal.m4 *.tar.xz *.tar.gz
.PHONY: common-uefi-x86-64
common-uefi-x86-64:

View File

@ -17,9 +17,9 @@ in the config file provides as much security as encrypting the kernel does.
### What? But what if someone modifies the config file! Ha! You clearly have not thought about that!
We have. While this is a pointless effort on legacy x86 BIOS, it is a reasonable expectation on UEFI systems with Secure Boot. Limine provides a
way to modify its own EFI executable to bake in the BLAKE2B checksum of the config file itself. The EFI executable gets then enrolled or otherwise
verified by the Secure Boot loader through, eg., the shim project. This prevents modifications being done to the config file (and in turn the
checksums contained there) from going unnoticed.
way to modify its own EFI executable to bake in the BLAKE2B checksum of the config file itself. The EFI executable can then get signed with
a key added to the firmware's keychain. This prevents modifications to the config file (and in turn the checksums contained there)
from going unnoticed.
### What about ext2/3/4? Why is that supported then?

View File

@ -87,7 +87,7 @@ The protocol mandates kernels to load themselves at or above
`0xffffffff80000000`. Lower half kernels are *not supported*.
At handoff, the kernel will be properly loaded and mapped with appropriate
MMU permissions at the requested virtual memory address (provided it is at
MMU permissions, as supervisor, at the requested virtual memory address (provided it is at
or above `0xffffffff80000000`).
No specific physical memory placement is guaranteed, except that the kernel
@ -97,11 +97,11 @@ below.
Alongside the loaded kernel, the bootloader will set up memory mappings as such:
```
Base Physical Address - Size -> Virtual address
0x0000000000001000 - 4 GiB plus any additional memory map entry -> 0x0000000000001000
0x0000000000000000 - 4 GiB plus any additional memory map entry -> HHDM start
Base Physical Address | | Base Virtual Address
0x0000000000001000 | (4 GiB - 0x1000) and any additional memory map region | 0x0000000000001000
0x0000000000000000 | 4 GiB and any additional memory map region | HHDM start
```
Where HHDM start is returned by the Higher Half Direct Map feature (see below).
Where "HHDM start" is returned by the Higher Half Direct Map feature (see below).
These mappings are supervisor, read, write, execute (-rwx).
The bootloader page tables are in bootloader-reclaimable memory (see Memory Map
@ -112,13 +112,64 @@ If the kernel is a position independent executable, the bootloader is free to
relocate it as it sees fit, potentially performing KASLR (as specified by the
config).
## Entry machine state
## Caching
### x86_64
### x86-64
The kernel executable, loaded at or above `0xffffffff80000000`, sees all of its
segments mapped using write-back (WB) caching at the page tables level.
All HHDM and identity map memory regions are mapped using write-back (WB) caching at the page
tables level, except framebuffer regions which are mapped using write-combining
(WC) caching at the page tables level.
The PAT's (Page Attribute Table) layout is specified to be as follows:
```
PAT0 -> WB
PAT1 -> WT
PAT2 -> UC-
PAT3 -> UC
PAT4 -> WP
PAT5 -> WC
PAT6 -> unspecified
PAT7 -> unspecified
```
The MTRRs are left as the firmware set them up.
### aarch64
The kernel executable, loaded at or above `0xffffffff80000000`, sees all of its
segments mapped using Normal Write-Back RW-Allocate non-transient caching mode.
All HHDM and identity map memory regions are mapped using the Normal Write-Back RW-Allocate
non-transient caching mode, except for the framebuffer regions, which are
mapped in using an unspecified caching mode, correct for use with the
framebuffer on the platform.
The `MAIR_EL1` register will at least contain entries for the above-mentioned
caching modes, in an unspecified order.
In order to access MMIO regions, the kernel must ensure the correct caching mode
is used on its own.
### riscv64
If the `Svpbmt` extension is available, all framebuffer memory regions are mapped
with `PBMT=NC` to enable write-combining optimizations. The kernel executable,
loaded at or above `0xffffffff80000000`, and all HHDM and identity map memory regions are mapped
with the default `PBMT=PMA`.
If the `Svpbmt` extension is not available, no PMAs can be overridden (effectively,
everything is mapped with `PBMT=PMA`).
## Machine state at entry
### x86-64
`rip` will be the entry point as defined as part of the executable file format,
unless the an Entry Point feature is requested (see below), in which case,
the value of `rip` is going to be taken from there.
unless the Entry Point feature is requested (see below), in which case, the value
of `rip` is going to be taken from there.
At entry all segment registers are loaded as 64 bit code/data segments, limits
and bases are ignored since this is 64-bit mode.
@ -146,7 +197,8 @@ If 5-level paging is requested and available, then 5-level paging is enabled
The A20 gate is opened.
Legacy PIC and IO APIC IRQs are all masked.
Legacy PIC (if available) and IO APIC IRQs (only those with delivery mode fixed
(0b000) or lowest priority (0b001)) are all masked.
If booted by EFI/UEFI, boot services are exited.
@ -160,30 +212,28 @@ All other general purpose registers are set to 0.
### aarch64
`PC` will be the entry point as defined as part of the executable file format,
unless the an Entry Point feature is requested (see below), in which case,
unless the Entry Point feature is requested (see below), in which case,
the value of `PC` is going to be taken from there.
The contents of the `VBAR_EL1` register are undefined, and the kernel must load it's own.
The contents of the `VBAR_EL1` register are undefined, and the kernel must load
its own.
The `MAIR_EL1` register will contain at least these entries, in an unspecified order:
- Normal, Write-back RW-Allocate non-transient (`0b11111111`),
- Unspecified, correct for use with the framebuffer.
The kernel and the lower-half identity mapping will be mapped with Normal write-back memory,
while the framebuffer is mapped with the correct caching mode. The kernel must ensure that
MMIO it wants to access is mapped with the correct caching mode.
The `MAIR_EL1` register contents are described above, in the caching section.
All interrupts are masked (`PSTATE.{D, A, I, F}` are set to 1).
The kernel is entered in little-endian AArch64 EL1t (EL1 with `PSTATE.SP` set to 0, `PSTATE.E` set to 0, and `PSTATE.nRW` set to 0).
The kernel is entered in little-endian AArch64 EL1t (EL1 with `PSTATE.SP` set to
0, `PSTATE.E` set to 0, and `PSTATE.nRW` set to 0).
Other fields of `PSTATE` are undefined.
At entry: the MMU (`SCTLR_EL1.M`) is enabled, the I-Cache and D-Cache (`SCTLR_EL1.{I, C}`) are enabled,
data alignment checking (`SCTLR_EL1.A`) is disabled. SP alignment checking (`SCTLR_EL1.{SA, SA0}`) is enabled.
Other fields of `SCTLR_EL1` are reset to 0 or to their reserved value.
At entry: the MMU (`SCTLR_EL1.M`) is enabled, the I-Cache and D-Cache
(`SCTLR_EL1.{I, C}`) are enabled, data alignment checking (`SCTLR_EL1.A`) is
disabled. SP alignment checking (`SCTLR_EL1.{SA, SA0}`) is enabled. Other fields
of `SCTLR_EL1` are reset to 0 or to their reserved value.
Higher ELs do not interfere with accesses to vector or floating point instructions or registers.
Higher ELs do not interfere with accesses to vector or floating point
instructions or registers.
Higher ELs do not interfere with accesses to the generic timer and counter.
@ -195,23 +245,24 @@ If booted by EFI/UEFI, boot services are exited.
at least 64KiB (65536 bytes) in size, or the size specified in the Stack
Size Request (see below).
All other general purpose registers (including `X29` and `X30`) are set to 0. Vector registers are in an undefined state.
All other general purpose registers (including `X29` and `X30`) are set to 0.
Vector registers are in an undefined state.
### riscv64
At entry the machine is executing in Supervisor mode.
`pc` will be the entry point as defined as part of the executable file format,
unless the an Entry Point feature is requested (see below), in which case,
the value of `pc` is going to be taken from there.
unless the Entry Point feature is requested (see below), in which case, the
value of `pc` is going to be taken from there.
`x1`(`ra`) is undefined, the kernel must not return from the entry point.
`x1`(`ra`) is set to 0, the kernel must not return from the entry point.
`x2`(`sp`) is set to point to a stack, in bootloader-reclaimable memory, which is
at least 64KiB (65536 bytes) in size, or the size specified in the Stack
Size Request (see below).
`x3`(`gp`) is undefined, kernel must load its own global pointer if needed.
`x3`(`gp`) is set to 0, kernel must load its own global pointer if needed.
All other general purpose registers, with the exception of `x5`(`t0`), are set to 0.
@ -221,7 +272,7 @@ If booted by EFI/UEFI, boot services are exited.
`sstatus.FS` and `sstatus.XS` are both set to `Off`.
Paging is enable with the paging mode specified by the Paging Mode feature (see below).
Paging is enabled with the paging mode specified by the Paging Mode feature (see below).
The (A)PLIC, if present, is in an undefined state.
@ -518,7 +569,7 @@ The possible settings are as follows:
The effect of each of these options matches the effect of the `stty(1)`
options by the same name.
#### x86_64
#### x86-64
Additionally, the kernel must ensure, when calling `write()`, that:
@ -699,7 +750,7 @@ The response indicates which paging mode was actually enabled by the bootloader.
Kernels must be prepared to handle the case where the requested paging mode is
not supported by the hardware.
#### x86_64
#### x86-64
Values for `mode`:
```c
@ -769,7 +820,7 @@ struct limine_5_level_paging_response {
```
Notes: The presence of this request will prompt the bootloader to turn on
x86_64 5-level paging. It will not be turned on if this request is not present.
x86-64 5-level paging. It will not be turned on if this request is not present.
If the response pointer is changed to a valid pointer, 5-level paging is engaged.
### SMP (multiprocessor) Feature
@ -789,9 +840,9 @@ struct limine_smp_request {
};
```
* `flags` - Bit 0: Enable X2APIC, if possible. (x86_64-only)
* `flags` - Bit 0: Enable X2APIC, if possible. (x86-64 only)
#### x86_64:
#### x86-64:
Response:
@ -846,7 +897,7 @@ Response:
```c
struct limine_smp_response {
uint64_t revision;
uint32_t flags;
uint64_t flags;
uint64_t bsp_mpidr;
uint64_t cpu_count;
struct limine_smp_info **cpus;
@ -895,7 +946,7 @@ Response:
```c
struct limine_smp_response {
uint64_t revision;
uint32_t flags;
uint64_t flags;
uint64_t bsp_hartid;
uint64_t cpu_count;
struct limine_smp_info **cpus;
@ -917,7 +968,7 @@ struct limine_smp_info;
typedef void (*limine_goto_address)(struct limine_smp_info *);
struct limine_smp_info {
uint32_t processor_id;
uint64_t processor_id;
uint64_t hartid;
uint64_t reserved;
limine_goto_address goto_address;

View File

@ -17,11 +17,11 @@ Donations welcome, but absolutely not mandatory!
![Reference screenshot](/screenshot.png?raw=true "Reference screenshot")
[Photo by Rostislav Uzunov](https://www.pexels.com/photo/purple-and-pink-diamond-on-blue-background-5011647/)
[Photo by Pixabay](https://www.pexels.com/photo/painting-of-black-cloud-during-sunset-164175/)
### Supported architectures
* IA-32 (32-bit x86)
* x86_64
* x86-64
* aarch64 (arm64)
* riscv64
@ -49,7 +49,7 @@ opening issues or pull requests related to this.
For 32-bit x86 systems, support is only ensured starting with those with
Pentium Pro (i686) class CPUs.
All x86_64, aarch64, and riscv64 (UEFI) systems are supported.
All x86-64, aarch64, and riscv64 (UEFI) systems are supported.
## Packaging status
@ -66,9 +66,9 @@ For example, to clone the latest binary release of the `v5.x` branch one can do
```bash
git clone https://github.com/limine-bootloader/limine.git --branch=v5.x-branch-binary --depth=1
```
or, to clone a specific binary point release (for example `v5.20230709.0`)
or, to clone a specific binary point release (for example `v5.20231024.0`)
```bash
git clone https://github.com/limine-bootloader/limine.git --branch=v5.20230709.0-binary --depth=1
git clone https://github.com/limine-bootloader/limine.git --branch=v5.20231024.0-binary --depth=1
```
In order to rebuild host utilities like `limine`, simply run `make` in the binary
@ -106,7 +106,7 @@ these, run `./configure --help`.
Limine supports both in-tree and out-of-tree builds. Simply run the `configure`
script from the directory you wish to execute the build in. The following `make`
commands are supposed to be ran inside the build directory.
commands are supposed to be run inside the build directory.
### Building Limine
@ -142,7 +142,8 @@ either the root, `limine`, `boot`, or `boot/limine` directory of one of the
partitions, formatted with a supported file system (the ESP partition is recommended).
### Secure Boot
Limine can be booted with secure boot using shim. This will also allow one to enroll
Limine can be booted with secure boot if the executable is signed and the key used to
sign it is added to the firmware's keychain. This should be done in combination with enrolling
the BLAKE2B hash of the Limine config file into the Limine EFI executable image itself for
verification purposes.
For more information see the `limine enroll-config` program and [the philosophy](/PHILOSOPHY.md).

View File

@ -26,7 +26,9 @@ fi
[ -d limine-efi ] || git clone https://github.com/limine-bootloader/limine-efi.git $SHALLOW_CLONE_FLAG
[ -d libgcc-binaries ] || git clone https://github.com/mintsuki/libgcc-binaries.git $SHALLOW_CLONE_FLAG
AUTOMAKE_LIBDIR="$(automake --print-libdir)"
cp "${AUTOMAKE_LIBDIR}/INSTALL" ./
mkdir -p build-aux
cp "$(automake --print-libdir)/install-sh" build-aux
cp "${AUTOMAKE_LIBDIR}/install-sh" build-aux/
autoreconf -fvi -Wall

View File

@ -22,20 +22,6 @@ ifeq ($(call MKESCAPE,$(BUILDDIR)),)
$(error BUILDDIR not specified)
endif
ifeq ($(TARGET),bios)
override OBJCOPY2ELF_FLAGS := -B i386 -O elf32-i386
else ifeq ($(TARGET),uefi-x86-64)
override OBJCOPY2ELF_FLAGS := -B i386 -O elf64-x86-64
else ifeq ($(TARGET),uefi-ia32)
override OBJCOPY2ELF_FLAGS := -B i386 -O elf32-i386
else ifeq ($(TARGET),uefi-aarch64)
override OBJCOPY2ELF_FLAGS := -B aarch64 -O elf64-littleaarch64
else ifeq ($(TARGET),uefi-riscv64)
override OBJCOPY2ELF_FLAGS := -B riscv64 -O elf64-littleriscv
else
$(error Invalid target)
endif
COM_OUTPUT ?= false
E9_OUTPUT ?= false
@ -69,7 +55,9 @@ override CPPFLAGS_FOR_TARGET := \
-MMD \
-MP
$(call MKESCAPE,$(BUILDDIR))/./flanterm/backends/fb.o: override CPPFLAGS_FOR_TARGET += -DFLANTERM_FB_DISABLE_BUMP_ALLOC
$(call MKESCAPE,$(BUILDDIR))/./flanterm/backends/fb.o: override CPPFLAGS_FOR_TARGET += \
-DFLANTERM_FB_DISABLE_BUMP_ALLOC \
-DFLANTERM_FB_SUPPORT_BPP
ifeq ($(TARGET),bios)
override CFLAGS_FOR_TARGET += \
@ -77,7 +65,6 @@ ifeq ($(TARGET),bios)
-fno-PIC \
-m32 \
-march=i686 \
-mabi=sysv \
-mno-80387
override CPPFLAGS_FOR_TARGET := \
$(CPPFLAGS_FOR_TARGET) \
@ -90,7 +77,6 @@ ifeq ($(TARGET),uefi-x86-64)
-fshort-wchar \
-m64 \
-march=x86-64 \
-mabi=sysv \
-mno-80387 \
-mno-mmx \
-mno-sse \
@ -109,7 +95,6 @@ ifeq ($(TARGET),uefi-ia32)
-fshort-wchar \
-m32 \
-march=i686 \
-mabi=sysv \
-mno-80387
override CPPFLAGS_FOR_TARGET := \
-I'$(call SHESCAPE,$(BUILDDIR))/limine-efi/inc' \
@ -131,16 +116,19 @@ ifeq ($(TARGET),uefi-aarch64)
endif
ifeq ($(TARGET),uefi-riscv64)
override CFLAGS_FOR_TARGET += \
-fPIE \
-fshort-wchar
ifeq ($(CC_FOR_TARGET_IS_CLANG),yes)
override RISCV_CFLAGS += -march=rv64imac -mabi=lp64
override CFLAGS_FOR_TARGET += -march=rv64imac
else
override RISCV_CFLAGS += -march=rv64imac_zicsr_zifencei -mabi=lp64
override CFLAGS_FOR_TARGET += -march=rv64imac_zicsr_zifencei
endif
override CFLAGS_FOR_TARGET += \
-fPIE \
-fshort-wchar \
$(RISCV_CFLAGS)
-mabi=lp64 \
-mno-relax
override CPPFLAGS_FOR_TARGET := \
-I'$(call SHESCAPE,$(BUILDDIR))/limine-efi/inc' \
@ -195,6 +183,7 @@ endif
ifeq ($(TARGET),uefi-riscv64)
override LDFLAGS_FOR_TARGET += \
-m elf64lriscv \
--no-relax \
-static \
-pie \
--no-dynamic-linker \
@ -291,15 +280,21 @@ $(call MKESCAPE,$(BUILDDIR))/linker_nos2map.ld: linker_bios.ld.in
$(MKDIR_P) '$(call SHESCAPE,$(BUILDDIR))'
$(CC_FOR_TARGET) -x c -E -P -undef -DLINKER_NOMAP -DLINKER_NOS2MAP linker_bios.ld.in -o '$(call SHESCAPE,$(BUILDDIR))/linker_nos2map.ld'
$(call MKESCAPE,$(BUILDDIR))/empty:
touch '$(call SHESCAPE,$@)'
$(call MKESCAPE,$(BUILDDIR))/limine_nomap.elf: $(OBJ) ../libgcc-binaries/libgcc-i686.a
$(MAKE) '$(call SHESCAPE,$(BUILDDIR))/empty'
$(MAKE) '$(call SHESCAPE,$(BUILDDIR))/linker_nos2map.ld'
$(LD_FOR_TARGET) '$(call OBJESCAPE,$^)' $(LDFLAGS_FOR_TARGET) -T'$(call SHESCAPE,$(BUILDDIR))/linker_nos2map.ld' -o '$(call SHESCAPE,$@)'
$(OBJCOPY_FOR_TARGET) -O binary --only-section=.note.gnu.build-id '$(call SHESCAPE,$@)' '$(call SHESCAPE,$(BUILDDIR))/build-id.s2.bin'
cd '$(call SHESCAPE,$(BUILDDIR))' && \
$(OBJCOPY_FOR_TARGET) -I binary $(OBJCOPY2ELF_FLAGS) build-id.s2.bin build-id.s2.o
$(OBJCOPY_FOR_TARGET) -I binary -B i386 -O elf32-i386 build-id.s2.bin build-id.s2.o && \
$(OBJCOPY_FOR_TARGET) --add-section .note.GNU-stack='$(call SHESCAPE,$(BUILDDIR))/empty' --set-section-flags .note.GNU-stack=noload,readonly build-id.s2.o
$(OBJCOPY_FOR_TARGET) -O binary --only-section=.note.gnu.build-id '$(call SHESCAPE,$@)' '$(call SHESCAPE,$(BUILDDIR))/build-id.s3.bin'
cd '$(call SHESCAPE,$(BUILDDIR))' && \
$(OBJCOPY_FOR_TARGET) -I binary $(OBJCOPY2ELF_FLAGS) build-id.s3.bin build-id.s3.o
$(OBJCOPY_FOR_TARGET) -I binary -B i386 -O elf32-i386 build-id.s3.bin build-id.s3.o && \
$(OBJCOPY_FOR_TARGET) --add-section .note.GNU-stack='$(call SHESCAPE,$(BUILDDIR))/empty' --set-section-flags .note.GNU-stack=noload,readonly build-id.s3.o
$(LD_FOR_TARGET) '$(call OBJESCAPE,$^)' '$(call SHESCAPE,$(BUILDDIR))/build-id.s2.o' '$(call SHESCAPE,$(BUILDDIR))/build-id.s3.o' $(LDFLAGS_FOR_TARGET) -T'$(call SHESCAPE,$(BUILDDIR))/linker_nos2map.ld' -o '$(call SHESCAPE,$@)'
$(call MKESCAPE,$(BUILDDIR))/linker_nomap.ld: linker_bios.ld.in
@ -307,14 +302,17 @@ $(call MKESCAPE,$(BUILDDIR))/linker_nomap.ld: linker_bios.ld.in
$(CC_FOR_TARGET) -x c -E -P -undef -DLINKER_NOMAP linker_bios.ld.in -o '$(call SHESCAPE,$(BUILDDIR))/linker_nomap.ld'
$(call MKESCAPE,$(BUILDDIR))/limine_nos3map.elf: $(OBJ) ../libgcc-binaries/libgcc-i686.a $(call MKESCAPE,$(BUILDDIR))/stage2.map.o
$(MAKE) '$(call SHESCAPE,$(BUILDDIR))/empty'
$(MAKE) '$(call SHESCAPE,$(BUILDDIR))/linker_nomap.ld'
$(LD_FOR_TARGET) '$(call OBJESCAPE,$^)' $(LDFLAGS_FOR_TARGET) -T'$(call SHESCAPE,$(BUILDDIR))/linker_nomap.ld' -o '$(call SHESCAPE,$@)'
$(OBJCOPY_FOR_TARGET) -O binary --only-section=.note.gnu.build-id '$(call SHESCAPE,$@)' '$(call SHESCAPE,$(BUILDDIR))/build-id.s2.bin'
cd '$(call SHESCAPE,$(BUILDDIR))' && \
$(OBJCOPY_FOR_TARGET) -I binary $(OBJCOPY2ELF_FLAGS) build-id.s2.bin build-id.s2.o
$(OBJCOPY_FOR_TARGET) -I binary -B i386 -O elf32-i386 build-id.s2.bin build-id.s2.o && \
$(OBJCOPY_FOR_TARGET) --add-section .note.GNU-stack='$(call SHESCAPE,$(BUILDDIR))/empty' --set-section-flags .note.GNU-stack=noload,readonly build-id.s2.o
$(OBJCOPY_FOR_TARGET) -O binary --only-section=.note.gnu.build-id '$(call SHESCAPE,$@)' '$(call SHESCAPE,$(BUILDDIR))/build-id.s3.bin'
cd '$(call SHESCAPE,$(BUILDDIR))' && \
$(OBJCOPY_FOR_TARGET) -I binary $(OBJCOPY2ELF_FLAGS) build-id.s3.bin build-id.s3.o
$(OBJCOPY_FOR_TARGET) -I binary -B i386 -O elf32-i386 build-id.s3.bin build-id.s3.o && \
$(OBJCOPY_FOR_TARGET) --add-section .note.GNU-stack='$(call SHESCAPE,$(BUILDDIR))/empty' --set-section-flags .note.GNU-stack=noload,readonly build-id.s3.o
$(LD_FOR_TARGET) '$(call OBJESCAPE,$^)' '$(call SHESCAPE,$(BUILDDIR))/build-id.s2.o' '$(call SHESCAPE,$(BUILDDIR))/build-id.s3.o' $(LDFLAGS_FOR_TARGET) -T'$(call SHESCAPE,$(BUILDDIR))/linker_nomap.ld' -o '$(call SHESCAPE,$@)'
$(call MKESCAPE,$(BUILDDIR))/linker.ld: linker_bios.ld.in
@ -322,14 +320,17 @@ $(call MKESCAPE,$(BUILDDIR))/linker.ld: linker_bios.ld.in
$(CC_FOR_TARGET) -x c -E -P -undef linker_bios.ld.in -o '$(call SHESCAPE,$(BUILDDIR))/linker.ld'
$(call MKESCAPE,$(BUILDDIR))/limine.elf: $(OBJ) ../libgcc-binaries/libgcc-i686.a $(call MKESCAPE,$(BUILDDIR))/stage2.map.o $(call MKESCAPE,$(BUILDDIR))/full.map.o
$(MAKE) '$(call SHESCAPE,$(BUILDDIR))/empty'
$(MAKE) '$(call SHESCAPE,$(BUILDDIR))/linker.ld'
$(LD_FOR_TARGET) '$(call OBJESCAPE,$^)' $(LDFLAGS_FOR_TARGET) -T'$(call SHESCAPE,$(BUILDDIR))/linker.ld' -o '$(call SHESCAPE,$@)'
$(OBJCOPY_FOR_TARGET) -O binary --only-section=.note.gnu.build-id '$(call SHESCAPE,$@)' '$(call SHESCAPE,$(BUILDDIR))/build-id.s2.bin'
cd '$(call SHESCAPE,$(BUILDDIR))' && \
$(OBJCOPY_FOR_TARGET) -I binary $(OBJCOPY2ELF_FLAGS) build-id.s2.bin build-id.s2.o
$(OBJCOPY_FOR_TARGET) -I binary -B i386 -O elf32-i386 build-id.s2.bin build-id.s2.o && \
$(OBJCOPY_FOR_TARGET) --add-section .note.GNU-stack='$(call SHESCAPE,$(BUILDDIR))/empty' --set-section-flags .note.GNU-stack=noload,readonly build-id.s2.o
$(OBJCOPY_FOR_TARGET) -O binary --only-section=.note.gnu.build-id '$(call SHESCAPE,$@)' '$(call SHESCAPE,$(BUILDDIR))/build-id.s3.bin'
cd '$(call SHESCAPE,$(BUILDDIR))' && \
$(OBJCOPY_FOR_TARGET) -I binary $(OBJCOPY2ELF_FLAGS) build-id.s3.bin build-id.s3.o
$(OBJCOPY_FOR_TARGET) -I binary -B i386 -O elf32-i386 build-id.s3.bin build-id.s3.o && \
$(OBJCOPY_FOR_TARGET) --add-section .note.GNU-stack='$(call SHESCAPE,$(BUILDDIR))/empty' --set-section-flags .note.GNU-stack=noload,readonly build-id.s3.o
$(LD_FOR_TARGET) '$(call OBJESCAPE,$^)' '$(call SHESCAPE,$(BUILDDIR))/build-id.s2.o' '$(call SHESCAPE,$(BUILDDIR))/build-id.s3.o' $(LDFLAGS_FOR_TARGET) -T'$(call SHESCAPE,$(BUILDDIR))/linker.ld' -o '$(call SHESCAPE,$@)'
endif
@ -350,7 +351,12 @@ $(call MKESCAPE,$(BUILDDIR))/BOOTX64.EFI: $(call MKESCAPE,$(BUILDDIR))/limine.el
$(OBJCOPY_FOR_TARGET) -O binary '$(call SHESCAPE,$<)' '$(call SHESCAPE,$@)'
chmod -x '$(call SHESCAPE,$@)'
$(call MKESCAPE,$(BUILDDIR))/limine-efi/gnuefi/crt0-efi-x86_64.S.o $(call MKESCAPE,$(BUILDDIR))/limine-efi/gnuefi/reloc_x86_64.c.o: $(call MKESCAPE,$(BUILDDIR))/limine-efi
$(call MKESCAPE,$(BUILDDIR))/limine-efi/gnuefi/crt0-efi-x86_64.S.o: limine-efi
$(call MKESCAPE,$(BUILDDIR))/limine-efi/gnuefi/reloc_x86_64.c.o: limine-efi
.PHONY: limine-efi
limine-efi: $(call MKESCAPE,$(BUILDDIR))/limine-efi
$(MAKE) -C '$(call SHESCAPE,$(BUILDDIR))/limine-efi/gnuefi' \
CC="$(CC_FOR_TARGET)" \
CFLAGS="$(BASE_CFLAGS)" \
@ -391,7 +397,12 @@ $(call MKESCAPE,$(BUILDDIR))/BOOTAA64.EFI: $(call MKESCAPE,$(BUILDDIR))/limine.e
$(OBJCOPY_FOR_TARGET) -O binary '$(call SHESCAPE,$<)' '$(call SHESCAPE,$@)'
chmod -x '$(call SHESCAPE,$@)'
$(call MKESCAPE,$(BUILDDIR))/limine-efi/gnuefi/crt0-efi-aarch64.S.o $(call MKESCAPE,$(BUILDDIR))/limine-efi/gnuefi/reloc_aarch64.c.o: $(call MKESCAPE,$(BUILDDIR))/limine-efi
$(call MKESCAPE,$(BUILDDIR))/limine-efi/gnuefi/crt0-efi-aarch64.S.o: limine-efi
$(call MKESCAPE,$(BUILDDIR))/limine-efi/gnuefi/reloc_aarch64.c.o: limine-efi
.PHONY: limine-efi
limine-efi: $(call MKESCAPE,$(BUILDDIR))/limine-efi
$(MAKE) -C '$(call SHESCAPE,$(BUILDDIR))/limine-efi/gnuefi' \
CC="$(CC_FOR_TARGET)" \
CFLAGS="$(BASE_CFLAGS)" \
@ -431,10 +442,15 @@ $(call MKESCAPE,$(BUILDDIR))/BOOTRISCV64.EFI: $(call MKESCAPE,$(BUILDDIR))/limin
$(OBJCOPY_FOR_TARGET) -O binary '$(call SHESCAPE,$<)' '$(call SHESCAPE,$@)'
chmod -x '$(call SHESCAPE,$@)'
$(call MKESCAPE,$(BUILDDIR))/limine-efi/gnuefi/crt0-efi-riscv64.S.o $(call MKESCAPE,$(BUILDDIR))/limine-efi/gnuefi/reloc_riscv64.c.o: $(call MKESCAPE,$(BUILDDIR))/limine-efi
$(call MKESCAPE,$(BUILDDIR))/limine-efi/gnuefi/crt0-efi-riscv64.S.o: limine-efi
$(call MKESCAPE,$(BUILDDIR))/limine-efi/gnuefi/reloc_riscv64.c.o: limine-efi
.PHONY: limine-efi
limine-efi: $(call MKESCAPE,$(BUILDDIR))/limine-efi
$(MAKE) -C '$(call SHESCAPE,$(BUILDDIR))/limine-efi/gnuefi' \
CC="$(CC_FOR_TARGET)" \
CFLAGS="$(BASE_CFLAGS) $(RISCV_CFLAGS)" \
CFLAGS="$(BASE_CFLAGS)" \
CPPFLAGS='-nostdinc -I$(call SHESCAPE,$(SRCDIR))/../freestanding-headers' \
ARCH=riscv64
@ -471,7 +487,12 @@ $(call MKESCAPE,$(BUILDDIR))/BOOTIA32.EFI: $(call MKESCAPE,$(BUILDDIR))/limine.e
$(OBJCOPY_FOR_TARGET) -O binary '$(call SHESCAPE,$<)' '$(call SHESCAPE,$@)'
chmod -x '$(call SHESCAPE,$@)'
$(call MKESCAPE,$(BUILDDIR))/limine-efi/gnuefi/crt0-efi-ia32.S.o $(call MKESCAPE,$(BUILDDIR))/limine-efi/gnuefi/reloc_ia32.c.o: $(call MKESCAPE,$(BUILDDIR))/limine-efi
$(call MKESCAPE,$(BUILDDIR))/limine-efi/gnuefi/crt0-efi-ia32.S.o: limine-efi
$(call MKESCAPE,$(BUILDDIR))/limine-efi/gnuefi/reloc_ia32.c.o: limine-efi
.PHONY: limine-efi
limine-efi: $(call MKESCAPE,$(BUILDDIR))/limine-efi
$(MAKE) -C '$(call SHESCAPE,$(BUILDDIR))/limine-efi/gnuefi' \
CC="$(CC_FOR_TARGET)" \
CFLAGS="$(BASE_CFLAGS)" \

View File

@ -20,6 +20,9 @@ static void console_help(void) {
"%s"
"lsvol -- List volumes.\n"
"firmware -- Show firmware type.\n"
#if defined (UEFI)
"slide -- Print load slide offset.\n"
#endif
"version -- Print version.\n"
"copyright -- Print copyright.\n"
"help -- Print this help message.\n",
@ -27,6 +30,10 @@ static void console_help(void) {
);
}
#if defined (UEFI)
extern symbol __slide;
#endif
void console(void) {
print("Welcome to the Limine console.\nType 'help' for more information.\n\n");
@ -57,6 +64,10 @@ void console(void) {
print("UEFI\n");
#else
print("unknown\n");
#endif
#if defined (UEFI)
} else if (strcmp(prompt, "slide") == 0) {
print("%p\n", __slide);
#endif
} else if (strcmp(prompt, "version") == 0) {
print(LIMINE_VERSION "\n");

View File

@ -218,6 +218,10 @@ static bool detect_sector_size(struct volume *volume) {
volume->sector_size = sector_size_a > sector_size_b ? sector_size_a : sector_size_b;
if (volume->sector_size == 0) {
return false;
}
return true;
}
@ -227,11 +231,6 @@ void disk_create_index(void) {
int optical_indices = 1, hdd_indices = 1;
for (uint8_t drive = 0x80; drive < 0xf0; drive++) {
if (volume_index_i == MAX_VOLUMES) {
print("WARNING: TOO MANY VOLUMES!");
break;
}
struct rm_regs r = {0};
struct bios_drive_params drive_params;
@ -278,6 +277,10 @@ void disk_create_index(void) {
block->guid_valid = true;
}
if (volume_index_i == MAX_VOLUMES) {
print("WARNING: TOO MANY VOLUMES!");
return;
}
volume_index[volume_index_i++] = block;
for (int part = 0; ; part++) {
@ -289,6 +292,10 @@ void disk_create_index(void) {
if (ret == NO_PARTITION)
continue;
if (volume_index_i == MAX_VOLUMES) {
print("WARNING: TOO MANY VOLUMES!");
return;
}
volume_index[volume_index_i++] = p;
block->max_partition++;
@ -577,11 +584,6 @@ fail:
size_t handle_count = handles_size / sizeof(EFI_HANDLE);
for (size_t i = 0; i < handle_count; i++) {
if (volume_index_i == MAX_VOLUMES) {
print("WARNING: TOO MANY VOLUMES!");
break;
}
EFI_BLOCK_IO *drive = NULL;
status = gBS->HandleProtocol(handles[i], &block_io_guid, (void **)&drive);
@ -632,6 +634,10 @@ fail:
block->guid_valid = true;
}
if (volume_index_i == MAX_VOLUMES) {
print("WARNING: TOO MANY VOLUMES!");
return;
}
volume_index[volume_index_i++] = block;
for (int part = 0; ; part++) {
@ -646,6 +652,11 @@ fail:
struct volume *p = ext_mem_alloc(sizeof(struct volume));
memcpy(p, &_p, sizeof(struct volume));
if (volume_index_i == MAX_VOLUMES) {
print("WARNING: TOO MANY VOLUMES!");
return;
}
volume_index[volume_index_i++] = p;
block->max_partition++;

View File

@ -171,8 +171,19 @@ static struct fb_info *get_mode_list(size_t *count, EFI_GRAPHICS_OUTPUT_PROTOCOL
return ret;
}
#define MAX_PRESET_MODES 128
no_unwind static int preset_modes[MAX_PRESET_MODES];
no_unwind static bool preset_modes_initialised = false;
void init_gop(struct fb_info **ret, size_t *_fbs_count,
uint64_t target_width, uint64_t target_height, uint16_t target_bpp) {
if (preset_modes_initialised == false) {
for (size_t i = 0; i < MAX_PRESET_MODES; i++) {
preset_modes[i] = -1;
}
preset_modes_initialised = true;
}
EFI_STATUS status;
EFI_HANDLE tmp_handles[1];
@ -216,7 +227,7 @@ void init_gop(struct fb_info **ret, size_t *_fbs_count,
};
size_t fbs_count = 0;
for (size_t i = 0; i < handles_count; i++) {
for (size_t i = 0; i < handles_count && i < MAX_PRESET_MODES; i++) {
struct fb_info *fb = &(*ret)[fbs_count];
uint64_t _target_width = target_width;
@ -249,7 +260,9 @@ void init_gop(struct fb_info **ret, size_t *_fbs_count,
continue;
}
int preset_mode = gop->Mode->Mode;
if (preset_modes[i] == -1) {
preset_modes[i] = gop->Mode->Mode;
}
fb->edid = get_edid_info(handles[i]);
@ -293,7 +306,7 @@ fallback:
if (current_fallback == 1) {
current_fallback++;
if (try_mode(fb, gop, preset_mode, 0, 0, 0, *ret, fbs_count)) {
if (try_mode(fb, gop, preset_modes[i], 0, 0, 0, *ret, fbs_count)) {
goto success;
}
}

View File

@ -8,3 +8,5 @@ efi_main:
mov x29, xzr
b uefi_entry
.section .note.GNU-stack,"",%progbits

View File

@ -6,3 +6,5 @@ efi_main:
xor eax, eax
mov [esp], eax
jmp uefi_entry
section .note.GNU-stack noalloc noexec nowrite progbits

View File

@ -3,10 +3,9 @@
.global efi_main
.extern uefi_entry
efi_main:
.option push
.option norelax
lla gp, __global_pointer$
.option pop
mv fp, zero
mv ra, zero
j uefi_entry
.section .note.GNU-stack,"",%progbits

View File

@ -6,3 +6,5 @@ efi_main:
xor eax, eax
mov [rsp], rax
jmp uefi_entry
section .note.GNU-stack noalloc noexec nowrite progbits

View File

@ -22,11 +22,12 @@
#include <drivers/disk.h>
#include <sys/lapic.h>
#include <lib/readline.h>
#include <sys/cpu.h>
void stage3_common(void);
#if defined (UEFI)
extern symbol __image_base;
extern symbol __slide;
noreturn void uefi_entry(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) {
gST = SystemTable;
@ -52,7 +53,7 @@ noreturn void uefi_entry(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
#endif
#if defined (__x86_64__)
if ((uintptr_t)__image_base > 0x100000000) {
if ((uintptr_t)__slide >= 0x100000000) {
panic(false, "Limine does not support being loaded above 4GiB");
}
#endif
@ -130,6 +131,18 @@ noreturn void stage3_common(void) {
init_io_apics();
#endif
#if defined (__riscv)
#if defined (UEFI)
RISCV_EFI_BOOT_PROTOCOL *rv_proto = get_riscv_boot_protocol();
if (rv_proto == NULL || rv_proto->GetBootHartId(rv_proto, &bsp_hartid) != EFI_SUCCESS) {
panic(false, "failed to get BSP's hartid");
}
#else
#error riscv: only UEFI is supported
#endif
init_riscv();
#endif
term_notready();
menu(true);

View File

@ -3,7 +3,7 @@ extern bss_end
extern entry
extern gdt
section .entry
section .entry progbits alloc exec nowrite align=16
global _start
_start:
@ -27,3 +27,5 @@ _start:
mov ss, ax
jmp entry
section .note.GNU-stack noalloc noexec nowrite progbits

View File

@ -36,5 +36,6 @@ struct file_handle *fopen(struct volume *part, const char *filename);
void fread(struct file_handle *fd, void *buf, uint64_t loc, uint64_t count);
void fclose(struct file_handle *fd);
void *freadall(struct file_handle *fd, uint32_t type);
void *freadall_mode(struct file_handle *fd, uint32_t type, bool allow_high_allocs);
#endif

View File

@ -96,6 +96,10 @@ void fread(struct file_handle *fd, void *buf, uint64_t loc, uint64_t count) {
}
void *freadall(struct file_handle *fd, uint32_t type) {
return freadall_mode(fd, type, false);
}
void *freadall_mode(struct file_handle *fd, uint32_t type, bool allow_high_allocs) {
if (fd->is_memfile) {
if (fd->readall) {
return fd->fd;
@ -104,7 +108,7 @@ void *freadall(struct file_handle *fd, uint32_t type) {
fd->readall = true;
return fd->fd;
} else {
void *ret = ext_mem_alloc_type(fd->size, type);
void *ret = ext_mem_alloc_type_aligned_mode(fd->size, type, 4096, allow_high_allocs);
fd->read(fd, ret, 0, fd->size);
fd->close(fd);
fd->fd = ret;

View File

@ -46,4 +46,6 @@ elif [ "$3" = "64" ]; then
echo ".quad 0xffffffffffffffff" >> "$TMP4"
fi
echo '.section .note.GNU-stack,"",%progbits' >> "$TMP4"
mv "$TMP4" "$2.map.S"

View File

@ -103,6 +103,75 @@ struct smbios_entry_point_64 {
uint64_t table_address;
} __attribute__((packed));
struct madt {
struct sdt header;
uint32_t local_controller_addr;
uint32_t flags;
char madt_entries_begin[];
} __attribute__((packed));
struct madt_header {
uint8_t type;
uint8_t length;
} __attribute__((packed));
struct madt_lapic {
struct madt_header header;
uint8_t acpi_processor_uid;
uint8_t lapic_id;
uint32_t flags;
} __attribute__((packed));
struct madt_x2apic {
struct madt_header header;
uint8_t reserved[2];
uint32_t x2apic_id;
uint32_t flags;
uint32_t acpi_processor_uid;
} __attribute__((packed));
struct madt_io_apic {
uint8_t type;
uint8_t length;
uint8_t apic_id;
uint8_t reserved;
uint32_t address;
uint32_t gsib;
} __attribute__((packed));
struct madt_gicc {
struct madt_header header;
uint8_t reserved1[2];
uint32_t iface_no;
uint32_t acpi_uid;
uint32_t flags;
uint32_t parking_ver;
uint32_t perf_gsiv;
uint64_t parking_addr;
uint64_t gicc_base_addr;
uint64_t gicv_base_addr;
uint64_t gich_base_addr;
uint32_t vgic_maint_gsiv;
uint64_t gicr_base_addr;
uint64_t mpidr;
uint8_t power_eff_class;
uint8_t reserved2;
uint16_t spe_overflow_gsiv;
} __attribute__((packed));
// Reference: https://github.com/riscv-non-isa/riscv-acpi/issues/15
struct madt_riscv_intc {
struct madt_header header;
uint8_t version;
uint8_t reserved;
uint32_t flags;
uint64_t hartid;
uint32_t acpi_processor_uid;
} __attribute__((packed));
#define MADT_RISCV_INTC_ENABLED ((uint32_t)1 << 0)
#define MADT_RISCV_INTC_ONLINE_CAPABLE ((uint32_t)1 << 1)
uint8_t acpi_checksum(void *ptr, size_t size);
void *acpi_get_rsdp(void);

View File

@ -147,6 +147,8 @@ int init_config(size_t config_size) {
config_b2sum += sizeof(CONFIG_B2SUM_SIGNATURE) - 1;
if (memcmp((void *)config_b2sum, CONFIG_B2SUM_EMPTY, 128) != 0) {
editor_enabled = false;
uint8_t out_buf[BLAKE2B_OUT_BYTES];
blake2b(out_buf, config_addr, config_size - 2);
uint8_t hash_buf[BLAKE2B_OUT_BYTES];
@ -251,10 +253,17 @@ int init_config(size_t config_size) {
panic(true, "config: Malformed macro usage");
}
}
if (config_addr[i] != '=') {
if (config_addr[i++] != '=') {
i = orig_i;
goto next;
}
while (config_addr[i] != '\n' && config_addr[i] != 0) {
i++;
if (i >= config_size) {
bad_config = true;
panic(true, "config: Malformed macro usage");
}
}
continue;
}

View File

@ -280,7 +280,7 @@ bool elf64_load_section(uint8_t *elf, void *buffer, const char *name, size_t lim
#if defined (__x86_64__) || defined (__i386__)
if (hdr->machine != ARCH_X86_64) {
printv("elf: Not an x86_64 ELF file.\n");
printv("elf: Not an x86-64 ELF file.\n");
return false;
}
#elif defined (__aarch64__)
@ -297,6 +297,10 @@ bool elf64_load_section(uint8_t *elf, void *buffer, const char *name, size_t lim
#error Unknown architecture
#endif
if (hdr->sh_num == 0) {
return false;
}
if (hdr->shdr_size < sizeof(struct elf64_shdr)) {
panic(true, "elf: shdr_size < sizeof(struct elf64_shdr)");
}
@ -422,7 +426,7 @@ bool elf64_load(uint8_t *elf, uint64_t *entry_point, uint64_t *_slide, uint32_t
#if defined (__x86_64__) || defined (__i386__)
if (hdr->machine != ARCH_X86_64) {
panic(true, "elf: Not an x86_64 ELF file.\n");
panic(true, "elf: Not an x86-64 ELF file.\n");
}
#elif defined (__aarch64__)
if (hdr->machine != ARCH_AARCH64) {
@ -492,6 +496,23 @@ bool elf64_load(uint8_t *elf, uint64_t *entry_point, uint64_t *_slide, uint32_t
&& phdr_in->p_vaddr + phdr_in->p_memsz <= phdr->p_vaddr + phdr->p_memsz)) {
panic(true, "elf: Attempted to load ELF file with overlapping PHDRs (%u and %u overlap)", i, j);
}
if (ranges != NULL) {
uint64_t page_rounded_base = ALIGN_DOWN(phdr->p_vaddr, 4096);
uint64_t page_rounded_top = ALIGN_UP(phdr->p_vaddr + phdr->p_memsz, 4096);
uint64_t page_rounded_base_in = ALIGN_DOWN(phdr_in->p_vaddr, 4096);
uint64_t page_rounded_top_in = ALIGN_UP(phdr_in->p_vaddr + phdr_in->p_memsz, 4096);
if ((page_rounded_base >= page_rounded_base_in
&& page_rounded_base < page_rounded_top_in)
||
(page_rounded_top > page_rounded_base_in
&& page_rounded_top <= page_rounded_top_in)) {
if ((phdr->p_flags & 0b111) != (phdr_in->p_flags & 0b111)) {
panic(true, "elf: Attempted to load ELF file with PHDRs with different permissions sharing the same memory page.");
}
}
}
}
if (phdr->p_vaddr < min_vaddr) {
@ -573,7 +594,7 @@ again:
}
#if defined (__aarch64__)
clean_inval_dcache_poc(mem_base, mem_base + mem_size);
clean_dcache_poc(mem_base, mem_base + mem_size);
inval_icache_pou(mem_base, mem_base + mem_size);
#endif
}
@ -685,7 +706,7 @@ bool elf64_load_elsewhere(uint8_t *elf, uint64_t *entry_point,
}
if (hdr->machine != ARCH_X86_64) {
printv("elf: Not an x86_64 ELF file.\n");
printv("elf: Not an x86-64 ELF file.\n");
return false;
}

View File

@ -10,354 +10,269 @@
#include <lib/image.h>
#include <mm/pmm.h>
#include <flanterm/flanterm.h>
#define FLANTERM_FB_SUPPORT_BPP
#include <flanterm/backends/fb.h>
#include <lib/term.h>
// Builtin font originally taken from:
// https://github.com/viler-int10h/vga-text-mode-fonts/raw/master/FONTS/PC-OTHER/TOSH-SAT.F16
static const uint8_t builtin_font[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x81, 0x81, 0xa5, 0xa5, 0x81,
0x81, 0xa5, 0x99, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x3c, 0x7e, 0xff,
0xff, 0xdb, 0xdb, 0xff, 0xff, 0xdb, 0xe7, 0xff, 0x7e, 0x3c, 0x00, 0x00,
0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, 0x7c, 0x7c, 0x38, 0x38, 0x10,
0x10, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe,
0x7c, 0x7c, 0x38, 0x38, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
0x3c, 0x3c, 0xdb, 0xff, 0xff, 0xdb, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0xff, 0x66, 0x18, 0x18,
0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x78,
0x78, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xcc, 0x84, 0x84, 0xcc, 0x78, 0x00,
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd,
0xbd, 0x99, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x1e,
0x0e, 0x1e, 0x32, 0x78, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0xfc, 0x30, 0x30,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x18, 0x1c, 0x1e, 0x16, 0x12,
0x10, 0x10, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x30, 0x38, 0x2c,
0x26, 0x32, 0x3a, 0x2e, 0x26, 0x22, 0x62, 0xe2, 0xc6, 0x0e, 0x0c, 0x00,
0x00, 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7, 0x3c, 0xdb, 0x18, 0x18,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf8, 0xfe,
0xf8, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
0x06, 0x0e, 0x3e, 0xfe, 0x3e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x30, 0x78, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x78,
0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc,
0xcc, 0xcc, 0x00, 0xcc, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xdb,
0xdb, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, 0x0c,
0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x78,
0xfc, 0x30, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x78, 0x30, 0xfc, 0x00, 0x00,
0x00, 0x00, 0x30, 0x78, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0xfc, 0x78, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x18, 0x0c, 0xfe, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0xfe, 0x60, 0x30, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x24, 0x66, 0xff, 0xff, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c,
0x38, 0x38, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x30, 0x78, 0x78, 0x78, 0x78, 0x30, 0x30, 0x30, 0x00, 0x30,
0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x6c,
0x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00,
0x00, 0x18, 0x18, 0x7c, 0xc6, 0xc0, 0xc0, 0x7c, 0x06, 0x06, 0xc6, 0x7c,
0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0x0c, 0x0c, 0x18, 0x38,
0x30, 0x60, 0x60, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c,
0x6c, 0x38, 0x30, 0x76, 0xde, 0xcc, 0xcc, 0xde, 0x76, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x60, 0x60, 0x60,
0x60, 0x60, 0x60, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x38, 0xfe, 0x38, 0x6c, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e,
0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06,
0x0c, 0x0c, 0x18, 0x38, 0x30, 0x60, 0x60, 0xc0, 0xc0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xc6, 0xc6, 0xc6,
0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6,
0x06, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x3c, 0x06, 0x06, 0x06, 0x06, 0xc6,
0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc,
0xfe, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0,
0xc0, 0xc0, 0xfc, 0x06, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3c, 0x60, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0x06, 0x06, 0x0c, 0x18,
0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6,
0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x0c,
0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
0x18, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00,
0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x60, 0x30, 0x18, 0x0c,
0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00,
0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x60,
0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x06, 0x0c, 0x18, 0x30, 0x30, 0x00, 0x30,
0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xde, 0xde,
0xde, 0xde, 0xc0, 0xc0, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c,
0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00,
0x00, 0x00, 0xfc, 0xc6, 0xc6, 0xc6, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc0,
0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xcc,
0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xcc, 0xf8, 0x00, 0x00, 0x00,
0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xfc, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,
0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xfc, 0xc0,
0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6,
0xc0, 0xc0, 0xc0, 0xde, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6,
0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x0c,
0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc6, 0xc6, 0xcc, 0xd8, 0xf0, 0xe0, 0xf0, 0xd8, 0xcc, 0xc6,
0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,
0xc0, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6,
0xee, 0xfe, 0xd6, 0xd6, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc6, 0xc6, 0xe6, 0xe6, 0xf6, 0xde, 0xce, 0xce, 0xc6, 0xc6,
0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xc6,
0xc6, 0xc6, 0xc6, 0xfc, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xf6, 0xda,
0x6c, 0x06, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0xfc,
0xd8, 0xcc, 0xcc, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6,
0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6,
0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x10, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c,
0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x38,
0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc,
0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00,
0x00, 0x00, 0xfe, 0x06, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xc0, 0xc0,
0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x60, 0x60, 0x60, 0x60, 0x60,
0x60, 0x60, 0x60, 0x60, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0,
0x60, 0x60, 0x30, 0x38, 0x18, 0x0c, 0x0c, 0x06, 0x06, 0x00, 0x00, 0x00,
0x00, 0x00, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
0x00, 0x00, 0x18, 0x18, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x06, 0x06,
0x7e, 0xc6, 0xc6, 0xc6, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0,
0xc0, 0xdc, 0xe6, 0xc6, 0xc6, 0xc6, 0xc6, 0xe6, 0xdc, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc0, 0xc6,
0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x06, 0x76, 0xce, 0xc6,
0xc6, 0xc6, 0xc6, 0xce, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x7c, 0xc6, 0xc6, 0xfe, 0xc0, 0xc0, 0xc0, 0x7e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x1c, 0x36, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xce, 0xc6,
0xc6, 0xc6, 0xce, 0x76, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0xc0, 0xc0,
0xc0, 0xdc, 0xe6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x1e, 0x06, 0x06,
0x06, 0x06, 0x06, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0xc0, 0xc0,
0xc0, 0xc6, 0xcc, 0xd8, 0xf0, 0xf0, 0xd8, 0xcc, 0xc6, 0x00, 0x00, 0x00,
0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0xfe, 0xd6,
0xd6, 0xd6, 0xd6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xdc, 0xe6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0xe6, 0xc6,
0xc6, 0xc6, 0xe6, 0xdc, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x76, 0xce, 0xc6, 0xc6, 0xc6, 0xce, 0x76, 0x06, 0x06, 0x06, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0xe6, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,
0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0,
0x70, 0x1c, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30,
0x30, 0xfe, 0x30, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6,
0xc6, 0xc6, 0x6c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0x6c, 0x38, 0x38, 0x6c, 0xc6,
0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6,
0xc6, 0xc6, 0xce, 0x76, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xfe, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xfe, 0x00, 0x00, 0x00,
0x00, 0x00, 0x1c, 0x30, 0x30, 0x30, 0x30, 0xe0, 0x30, 0x30, 0x30, 0x30,
0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00,
0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x30,
0x30, 0x30, 0x30, 0x1c, 0x30, 0x30, 0x30, 0x30, 0xe0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x38, 0x38, 0x6c,
0x6c, 0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66,
0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x66, 0x3c, 0x18, 0xcc, 0x78, 0x00,
0x00, 0x00, 0x6c, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
0x7c, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xc6,
0xfe, 0xc0, 0xc0, 0xc0, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c,
0x00, 0x7c, 0x06, 0x06, 0x7e, 0xc6, 0xc6, 0xc6, 0x7e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x6c, 0x6c, 0x00, 0x7c, 0x06, 0x06, 0x7e, 0xc6, 0xc6, 0xc6,
0x7e, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0x06, 0x06,
0x7e, 0xc6, 0xc6, 0xc6, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38,
0x00, 0x7c, 0x06, 0x06, 0x7e, 0xc6, 0xc6, 0xc6, 0x7e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc0, 0xc6,
0x7c, 0x18, 0x0c, 0x38, 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6,
0xfe, 0xc0, 0xc0, 0xc0, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x6c,
0x00, 0x7c, 0xc6, 0xc6, 0xfe, 0xc0, 0xc0, 0xc0, 0x7e, 0x00, 0x00, 0x00,
0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xc6, 0xfe, 0xc0, 0xc0, 0xc0,
0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x6c, 0x00, 0x38, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c,
0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x3c, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xc6,
0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38, 0x00,
0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00,
0x18, 0x30, 0x60, 0x00, 0xfe, 0xc0, 0xc0, 0xfc, 0xc0, 0xc0, 0xc0, 0xc0,
0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0x36, 0x36,
0x76, 0xde, 0xd8, 0xd8, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x3c,
0x6c, 0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00,
0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x6c, 0x00, 0x7c, 0xc6, 0xc6,
0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18,
0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x10, 0x38, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
0x7c, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0xc6, 0xc6, 0xc6,
0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x6c,
0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xce, 0x76, 0x06, 0xc6, 0x7c, 0x00,
0x6c, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
0x7c, 0x00, 0x00, 0x00, 0x6c, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
0x30, 0x78, 0xcc, 0xc0, 0xc0, 0xcc, 0x78, 0x30, 0x30, 0x00, 0x00, 0x00,
0x00, 0x00, 0x38, 0x6c, 0x60, 0x60, 0x60, 0xf8, 0x60, 0x60, 0x60, 0xe6,
0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0xfc,
0x30, 0xfc, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xcc,
0xcc, 0xf8, 0xc4, 0xcc, 0xde, 0xcc, 0xcc, 0xcc, 0xc6, 0x00, 0x00, 0x00,
0x00, 0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18,
0x18, 0xd8, 0x70, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0x06, 0x06,
0x7e, 0xc6, 0xc6, 0xc6, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30,
0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
0x7c, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x00, 0xc6, 0xc6, 0xc6,
0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00,
0x00, 0xdc, 0xe6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00,
0x76, 0xdc, 0x00, 0xc6, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6,
0xc6, 0x00, 0x00, 0x00, 0x00, 0x78, 0xd8, 0xd8, 0x6c, 0x00, 0xfc, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x6c,
0x38, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x30, 0x60, 0xc0, 0xc6, 0xc6,
0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xfe, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc0, 0xc2, 0xc6, 0xcc, 0xd8, 0x30, 0x60, 0xdc, 0x86, 0x0c,
0x18, 0x3e, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc2, 0xc6, 0xcc, 0xd8, 0x30,
0x66, 0xce, 0x9e, 0x3e, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30,
0x00, 0x30, 0x30, 0x30, 0x78, 0x78, 0x78, 0x78, 0x30, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36,
0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x88, 0x22, 0x88,
0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88,
0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa,
0x55, 0xaa, 0x55, 0xaa, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77,
0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0xf8, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0xf8, 0x18,
0x18, 0xf8, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0xf6, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xf8, 0x18,
0x18, 0xf8, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36,
0x36, 0xf6, 0xf6, 0x06, 0x06, 0xf6, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x06,
0x06, 0xf6, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0xf6, 0xf6, 0x06, 0x06, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, 0xfe, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0xf8, 0x18,
0x18, 0xf8, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xf8, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x1f, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff,
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xff, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x1f, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0xff, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x1f, 0x18, 0x18, 0x1f, 0x1f, 0x18,
0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37,
0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x37, 0x37, 0x30, 0x30, 0x3f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x3f, 0x30, 0x30, 0x37, 0x37, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0xf7, 0x00,
0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xff, 0xff, 0x00, 0x00, 0xf7, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x37, 0x30, 0x30, 0x37, 0x37, 0x36,
0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00,
0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36,
0x36, 0xf7, 0xf7, 0x00, 0x00, 0xf7, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36,
0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00,
0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff,
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f,
0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18,
0x18, 0x1f, 0x1f, 0x18, 0x18, 0x1f, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x1f, 0x18, 0x18, 0x1f, 0x1f, 0x18,
0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
0x3f, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0xff, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0xff, 0x18, 0x18, 0xff, 0xff, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8,
0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x1f, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xf0, 0xf0, 0xf0,
0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
0x0f, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x76, 0xd6, 0xdc, 0xc8, 0xc8, 0xdc, 0xd6, 0x76, 0x00, 0x00, 0x00,
0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xd8, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc,
0xd8, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc0, 0xc0, 0xc0,
0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x7e, 0xfe, 0x24, 0x24, 0x24, 0x24, 0x66, 0xc6, 0x00, 0x00, 0x00,
0x00, 0x00, 0xfe, 0xfe, 0xc2, 0x60, 0x30, 0x18, 0x30, 0x60, 0xc2, 0xfe,
0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xc8, 0xcc,
0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x76, 0x6c, 0x60, 0xc0, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0xfc, 0x98, 0x18, 0x18, 0x18, 0x18,
0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x30, 0x30, 0x78, 0xcc, 0xcc,
0xcc, 0x78, 0x30, 0x30, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c,
0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00,
0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c,
0xee, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xcc, 0x60, 0x30, 0x78, 0xcc,
0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x76, 0xbb, 0x99, 0x99, 0xdd, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x02, 0x06, 0x3c, 0x6c, 0xce, 0xd6, 0xd6, 0xe6, 0x6c, 0x78,
0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x30, 0x60, 0xc0, 0xc0, 0xfe,
0xc0, 0xc0, 0x60, 0x30, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c,
0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0xfc,
0x30, 0x30, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x60, 0x30, 0x18, 0x0c, 0x18, 0x30, 0x60, 0x00, 0xfc, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0xc0, 0x60, 0x30, 0x18, 0x00,
0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x36, 0x36, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0xfc, 0x00, 0x30, 0x30, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00,
0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xcc, 0xcc,
0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0c, 0x0c,
0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0x6c, 0x3c, 0x1c, 0x0c, 0x00, 0x00,
0x00, 0xd8, 0xec, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x0c, 0x18, 0x30, 0x60, 0x7c,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 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, 0x3c, 0x42, 0x81, 0x81, 0xa5, 0xa5, 0x81, 0x81, 0xa5, 0x99, 0x81, 0x42, 0x3c, 0x00, 0x00,
0x00, 0x3c, 0x7e, 0xff, 0xff, 0xdb, 0xdb, 0xff, 0xff, 0xdb, 0xe7, 0xff, 0x7e, 0x3c, 0x00, 0x00,
0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, 0x7c, 0x7c, 0x38, 0x38, 0x10, 0x10, 0x00, 0x00, 0x00,
0x00, 0x10, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0x7c, 0x7c, 0x38, 0x38, 0x10, 0x10, 0x00, 0x00,
0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0xdb, 0xff, 0xff, 0xdb, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0xff, 0x66, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x78, 0x78, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xcc, 0x84, 0x84, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd, 0xbd, 0x99, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff,
0x00, 0x00, 0x00, 0x1e, 0x0e, 0x1e, 0x32, 0x78, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0xfc, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x10, 0x18, 0x1c, 0x1e, 0x16, 0x12, 0x10, 0x10, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x00,
0x00, 0x30, 0x38, 0x2c, 0x26, 0x32, 0x3a, 0x2e, 0x26, 0x22, 0x62, 0xe2, 0xc6, 0x0e, 0x0c, 0x00,
0x00, 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7, 0x3c, 0xdb, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00,
0x00, 0x02, 0x06, 0x0e, 0x1e, 0x3e, 0x7e, 0xfe, 0x7e, 0x3e, 0x1e, 0x0e, 0x06, 0x02, 0x00, 0x00,
0x00, 0x00, 0x30, 0x78, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x78, 0x30, 0x00, 0x00, 0x00,
0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x00, 0xcc, 0xcc, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7f, 0xdb, 0xdb, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00,
0x00, 0x00, 0x30, 0x78, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x78, 0x30, 0xfc, 0x00, 0x00,
0x00, 0x00, 0x30, 0x78, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00,
0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x78, 0x30, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0c, 0xfe, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0xfe, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x66, 0xff, 0xff, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c, 0x38, 0x38, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x30, 0x78, 0x78, 0x78, 0x78, 0x30, 0x30, 0x30, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00,
0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x6c, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00,
0x00, 0x18, 0x18, 0x7c, 0xc6, 0xc0, 0xc0, 0x7c, 0x06, 0x06, 0xc6, 0x7c, 0x18, 0x18, 0x00, 0x00,
0x00, 0x00, 0xc6, 0xc6, 0x0c, 0x0c, 0x18, 0x38, 0x30, 0x60, 0x60, 0xc6, 0xc6, 0x00, 0x00, 0x00,
0x00, 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x30, 0x76, 0xde, 0xcc, 0xcc, 0xde, 0x76, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x30, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x30, 0x18, 0x00, 0x00, 0x00,
0x00, 0x00, 0x60, 0x30, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x38, 0xfe, 0x38, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00,
0x00, 0x00, 0x06, 0x06, 0x0c, 0x0c, 0x18, 0x38, 0x30, 0x60, 0x60, 0xc0, 0xc0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x3c, 0x06, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x04, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x00,
0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xfc, 0x06, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3c, 0x60, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x00, 0xfe, 0xc6, 0x06, 0x06, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x0c, 0x78, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00,
0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x06, 0x0c, 0x18, 0x30, 0x30, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xde, 0xde, 0xde, 0xde, 0xc0, 0xc0, 0x7e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00,
0x00, 0x00, 0xfc, 0xc6, 0xc6, 0xc6, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xfc, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x00, 0xf8, 0xcc, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xcc, 0xf8, 0x00, 0x00, 0x00,
0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xfc, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00,
0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xfc, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xde, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00,
0x00, 0x00, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x00, 0x00, 0x00,
0x00, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc6, 0xc6, 0xcc, 0xd8, 0xf0, 0xe0, 0xf0, 0xd8, 0xcc, 0xc6, 0xc6, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc6, 0xc6, 0xee, 0xfe, 0xd6, 0xd6, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc6, 0xc6, 0xe6, 0xe6, 0xf6, 0xde, 0xce, 0xce, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x00, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0xfc, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xf6, 0xda, 0x6c, 0x06, 0x00, 0x00,
0x00, 0x00, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0xfc, 0xd8, 0xcc, 0xcc, 0xc6, 0xc6, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7c, 0xc6, 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x10, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x6c, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x38, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00,
0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00,
0x00, 0x00, 0xfe, 0x06, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00,
0x00, 0x00, 0x78, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x78, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc0, 0xc0, 0x60, 0x60, 0x30, 0x38, 0x18, 0x0c, 0x0c, 0x06, 0x06, 0x00, 0x00, 0x00,
0x00, 0x00, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x00, 0x00, 0x00,
0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
0x00, 0x00, 0x18, 0x18, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x06, 0x06, 0x7e, 0xc6, 0xc6, 0xc6, 0x7e, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xdc, 0xe6, 0xc6, 0xc6, 0xc6, 0xc6, 0xe6, 0xdc, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x06, 0x06, 0x06, 0x76, 0xce, 0xc6, 0xc6, 0xc6, 0xc6, 0xce, 0x76, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xfe, 0xc0, 0xc0, 0xc0, 0x7e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x1c, 0x36, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xce, 0xc6, 0xc6, 0xc6, 0xce, 0x76, 0x06, 0xc6, 0x7c, 0x00,
0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xdc, 0xe6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x06, 0x00, 0x00, 0x1e, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0xc6, 0xc6, 0x7c, 0x00,
0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc6, 0xcc, 0xd8, 0xf0, 0xf0, 0xd8, 0xcc, 0xc6, 0x00, 0x00, 0x00,
0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0xfe, 0xd6, 0xd6, 0xd6, 0xd6, 0xc6, 0xc6, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0xe6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0xe6, 0xc6, 0xc6, 0xc6, 0xe6, 0xdc, 0xc0, 0xc0, 0xc0, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xce, 0xc6, 0xc6, 0xc6, 0xce, 0x76, 0x06, 0x06, 0x06, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0xe6, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0x70, 0x1c, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x30, 0x30, 0x30, 0xfe, 0x30, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x10, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0x6c, 0x38, 0x38, 0x6c, 0xc6, 0xc6, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xce, 0x76, 0x06, 0xc6, 0x7c, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xfe, 0x00, 0x00, 0x00,
0x00, 0x00, 0x1c, 0x30, 0x30, 0x30, 0x30, 0xe0, 0x30, 0x30, 0x30, 0x30, 0x1c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00,
0x00, 0x00, 0xe0, 0x30, 0x30, 0x30, 0x30, 0x1c, 0x30, 0x30, 0x30, 0x30, 0xe0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x10, 0x10, 0x38, 0x38, 0x6c, 0x6c, 0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3c, 0x66, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x66, 0x3c, 0x18, 0xcc, 0x78, 0x00,
0x00, 0x00, 0x6c, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xc6, 0xfe, 0xc0, 0xc0, 0xc0, 0x7e, 0x00, 0x00, 0x00,
0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0x06, 0x06, 0x7e, 0xc6, 0xc6, 0xc6, 0x7e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x6c, 0x6c, 0x00, 0x7c, 0x06, 0x06, 0x7e, 0xc6, 0xc6, 0xc6, 0x7e, 0x00, 0x00, 0x00,
0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0x06, 0x06, 0x7e, 0xc6, 0xc6, 0xc6, 0x7e, 0x00, 0x00, 0x00,
0x00, 0x38, 0x6c, 0x38, 0x00, 0x7c, 0x06, 0x06, 0x7e, 0xc6, 0xc6, 0xc6, 0x7e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x18, 0x0c, 0x38,
0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xfe, 0xc0, 0xc0, 0xc0, 0x7e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x6c, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xfe, 0xc0, 0xc0, 0xc0, 0x7e, 0x00, 0x00, 0x00,
0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xc6, 0xfe, 0xc0, 0xc0, 0xc0, 0x7e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x6c, 0x6c, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
0x00, 0x10, 0x38, 0x6c, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
0xc6, 0xc6, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00,
0x38, 0x6c, 0x38, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00,
0x18, 0x30, 0x60, 0x00, 0xfe, 0xc0, 0xc0, 0xfc, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0x36, 0x36, 0x76, 0xde, 0xd8, 0xd8, 0x6e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x1e, 0x3c, 0x6c, 0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00,
0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x6c, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x10, 0x38, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x60, 0x30, 0x18, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x6c, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xce, 0x76, 0x06, 0xc6, 0x7c, 0x00,
0x6c, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x6c, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x30, 0x30, 0x78, 0xcc, 0xc0, 0xc0, 0xcc, 0x78, 0x30, 0x30, 0x00, 0x00, 0x00,
0x00, 0x00, 0x38, 0x6c, 0x60, 0x60, 0x60, 0xf8, 0x60, 0x60, 0x60, 0xe6, 0xfc, 0x00, 0x00, 0x00,
0x00, 0x00, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0xfc, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00,
0x00, 0x00, 0xf8, 0xcc, 0xcc, 0xf8, 0xc4, 0xcc, 0xde, 0xcc, 0xcc, 0xcc, 0xc6, 0x00, 0x00, 0x00,
0x00, 0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0x70, 0x00,
0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0x06, 0x06, 0x7e, 0xc6, 0xc6, 0xc6, 0x7e, 0x00, 0x00, 0x00,
0x00, 0x0c, 0x18, 0x30, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x0c, 0x18, 0x30, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x76, 0xdc, 0x00, 0x00, 0xdc, 0xe6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00,
0x76, 0xdc, 0x00, 0xc6, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00,
0x00, 0x78, 0xd8, 0xd8, 0x6c, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x30, 0x60, 0xc0, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc0, 0xc2, 0xc6, 0xcc, 0xd8, 0x30, 0x60, 0xdc, 0x86, 0x0c, 0x18, 0x3e, 0x00, 0x00,
0x00, 0x00, 0xc0, 0xc2, 0xc6, 0xcc, 0xd8, 0x30, 0x66, 0xce, 0x9e, 0x3e, 0x06, 0x06, 0x00, 0x00,
0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x30, 0x78, 0x78, 0x78, 0x78, 0x30, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36, 0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88,
0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa,
0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0xf8, 0x18, 0x18, 0xf8, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xf8, 0x18, 0x18, 0xf8, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18,
0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0xf6, 0x06, 0x06, 0xf6, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x06, 0x06, 0xf6, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0xf6, 0x06, 0x06, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0xf8, 0x18, 0x18, 0xf8, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x1f, 0x18, 0x18, 0x1f, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x37, 0x30, 0x30, 0x3f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x3f, 0x30, 0x30, 0x37, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0xf7, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xf7, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x37, 0x30, 0x30, 0x37, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36,
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0xf7, 0x00, 0x00, 0xf7, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36,
0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x1f, 0x18, 0x18, 0x1f, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x1f, 0x18, 0x18, 0x1f, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x3f, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0xff, 0x18, 0x18, 0xff, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xd6, 0xdc, 0xc8, 0xc8, 0xdc, 0xd6, 0x76, 0x00, 0x00, 0x00,
0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xd8, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xd8, 0xc0, 0xc0, 0x00,
0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xfe, 0x24, 0x24, 0x24, 0x24, 0x66, 0xc6, 0x00, 0x00, 0x00,
0x00, 0x00, 0xfe, 0xfe, 0xc2, 0x60, 0x30, 0x18, 0x30, 0x60, 0xc2, 0xfe, 0xfe, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xc8, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x76, 0x6c, 0x60, 0xc0, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0xfc, 0x98, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00,
0x00, 0x00, 0xfc, 0x30, 0x30, 0x78, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x30, 0xfc, 0x00, 0x00, 0x00,
0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00,
0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0xee, 0x00, 0x00, 0x00,
0x00, 0x00, 0x78, 0xcc, 0x60, 0x30, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xbb, 0x99, 0x99, 0xdd, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x02, 0x06, 0x3c, 0x6c, 0xce, 0xd6, 0xd6, 0xe6, 0x6c, 0x78, 0xc0, 0x80, 0x00, 0x00,
0x00, 0x00, 0x1e, 0x30, 0x60, 0xc0, 0xc0, 0xfe, 0xc0, 0xc0, 0x60, 0x30, 0x1e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x18, 0x30, 0x60, 0x00, 0xfc, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0xc0, 0x60, 0x30, 0x18, 0x00, 0xfc, 0x00, 0x00, 0x00,
0x00, 0x00, 0x1c, 0x36, 0x36, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0xfc, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x78, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0x6c, 0x3c, 0x1c, 0x0c, 0x00, 0x00,
0x00, 0xd8, 0xec, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x38, 0x6c, 0x0c, 0x18, 0x30, 0x60, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
static struct image *background;
@ -740,6 +655,7 @@ no_load_font:;
size_t font_scale_x = 1;
size_t font_scale_y = 1;
bool font_scale_is_default = true;
char *menu_font_scale = config_get_value(config, 0, "TERM_FONT_SCALE");
if (menu_font_scale != NULL) {
@ -747,6 +663,8 @@ no_load_font:;
if (font_scale_x > 8 || font_scale_y > 8) {
font_scale_x = 1;
font_scale_y = 1;
} else {
font_scale_is_default = false;
}
}
@ -756,13 +674,8 @@ no_load_font:;
for (size_t i = 0; i < fbs_count; i++) {
struct fb_info *fb = &fbs[i];
// Ensure this is xRGB8888, we only support that for the menu
if (fb->red_mask_size != 8
|| fb->red_mask_shift != 16
|| fb->green_mask_size != 8
|| fb->green_mask_shift != 8
|| fb->blue_mask_size != 8
|| fb->blue_mask_shift != 0) {
// Ensure that this framebuffer uses 32-bits per pixel.
if (fb->framebuffer_bpp != 32) {
continue;
}
@ -782,10 +695,24 @@ no_load_font:;
generate_canvas(fb);
if (font_scale_is_default) {
if (fb->framebuffer_width >= (1920 + 1920 / 3) && fb->framebuffer_height >= (1080 + 1080 / 3)) {
font_scale_x = 2;
font_scale_y = 2;
}
if (fb->framebuffer_width >= (3840 + 3840 / 3) && fb->framebuffer_height >= (2160 + 2160 / 3)) {
font_scale_x = 4;
font_scale_y = 4;
}
}
terms[terms_i] = flanterm_fb_init(ext_mem_alloc,
pmm_free,
(void *)(uintptr_t)fb->framebuffer_addr,
fb->framebuffer_width, fb->framebuffer_height, fb->framebuffer_pitch,
fb->red_mask_size, fb->red_mask_shift,
fb->green_mask_size, fb->green_mask_shift,
fb->blue_mask_size, fb->blue_mask_shift,
bg_canvas,
ansi_colours, ansi_bright_colours,
&default_bg, &default_fg,

View File

@ -6,6 +6,8 @@
bool isprint(int c);
bool isspace(int c);
bool isalpha(int c);
bool isdigit(int c);
int toupper(int c);
int tolower(int c);
@ -23,6 +25,7 @@ size_t strlen(const char *);
int strcmp(const char *, const char *);
int strcasecmp(const char *, const char *);
int strncmp(const char *, const char *, size_t);
int strncasecmp(const char *, const char *, size_t);
int inet_pton(const char *src, void *dst);
#endif

View File

@ -12,6 +12,14 @@ bool isspace(int c) {
return (c >= '\t' && c <= 0xD) || c == ' ';
}
bool isalpha(int c) {
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
}
bool isdigit(int c) {
return c >= '0' && c <= '9';
}
int toupper(int c) {
if (c >= 'a' && c <= 'z') {
return c - 0x20;
@ -84,6 +92,18 @@ int strncmp(const char *s1, const char *s2, size_t n) {
return 0;
}
int strncasecmp(const char *s1, const char *s2, size_t n) {
for (size_t i = 0; i < n; i++) {
char c1 = s1[i], c2 = s2[i];
if (tolower(c1) != tolower(c2))
return c1 < c2 ? -1 : 1;
if (!c1)
return 0;
}
return 0;
}
size_t strlen(const char *str) {
size_t len;

View File

@ -53,3 +53,5 @@ memcmp:
.done:
ret
section .note.GNU-stack noalloc noexec nowrite progbits

View File

@ -107,3 +107,5 @@ bits 32
pop esi
pop ebp
ret
section .note.GNU-stack noalloc noexec nowrite progbits

View File

@ -20,6 +20,7 @@ UINT32 efi_desc_ver = 0;
#endif
bool editor_enabled = true;
bool help_hidden = false;
bool parse_resolution(size_t *width, size_t *height, size_t *bpp, const char *buf) {
size_t res[3] = {0};

View File

@ -36,7 +36,7 @@ extern struct volume *boot_volume;
extern bool stage3_loaded;
#endif
extern bool quiet, serial, editor_enabled, hash_mismatch_panic;
extern bool quiet, serial, editor_enabled, help_hidden, hash_mismatch_panic;
bool parse_resolution(size_t *width, size_t *height, size_t *bpp, const char *buf);
@ -95,9 +95,6 @@ noreturn void stage3_common(void);
#if defined (__x86_64__) || defined (__i386__)
noreturn void common_spinup(void *fnptr, int args, ...);
#elif defined (__aarch64__)
noreturn void enter_in_current_el(uint64_t entry, uint64_t sp, uint64_t sctlr,
uint64_t target_x0);
noreturn void enter_in_el1(uint64_t entry, uint64_t sp, uint64_t sctlr,
uint64_t mair, uint64_t tcr, uint64_t ttbr0,
uint64_t ttbr1, uint64_t target_x0);

View File

@ -164,3 +164,5 @@ align 16
.idt: dq 0
.rm_idt: dw 0x3ff
dd 0
section .note.GNU-stack noalloc noexec nowrite progbits

View File

@ -153,3 +153,5 @@ _pit_sleep_and_quit_on_keypress:
.mods: dd 0
.ascii: dd 0
.scan: dd 0
section .note.GNU-stack noalloc noexec nowrite progbits

View File

@ -2,53 +2,6 @@
.section .text
// noreturn void enter_in_current_el(uint64_t entry, uint64_t sp, uint64_t sctlr,
// uint64_t target_x0)
// Configure current EL state and jump to kernel. Used for Linux hence
// no paging register configuration (which requires SCTLR.M = 0).
.global enter_in_current_el
enter_in_current_el:
msr sp_el0, x1
// Sanity check that SCTLR.M = 0
and x8, x2, #0b1
cbnz x8, 99f
99:
wfi
b 99b
PICK_EL x8, 0f, 1f
0:
msr sctlr_el1, x2
dsb sy
isb
// Enter kernel in EL1
mov x8, #0x3c4
msr spsr_el1, x8
msr elr_el1, x0
mov x0, x3
ZERO_REGS_EXCEPT_X0
eret
1:
msr sctlr_el2, x2
dsb sy
isb
// Enter kernel in EL2
mov x8, #0x3c8
msr spsr_el2, x8
msr elr_el2, x0
mov x0, x3
ZERO_REGS_EXCEPT_X0
eret
// noreturn void enter_in_el1(uint64_t entry, uint64_t sp, uint64_t sctlr,
// uint64_t mair, uint64_t tcr, uint64_t ttbr0,
// uint64_t ttbr1, uint64_t target_x0)
@ -108,3 +61,5 @@ enter_in_el1:
ZERO_REGS_EXCEPT_X0
eret
.section .note.GNU-stack,"",%progbits

View File

@ -35,3 +35,5 @@ common_spinup:
mov cr4, eax
call edi
section .note.GNU-stack noalloc noexec nowrite progbits

View File

@ -3,7 +3,7 @@
.global riscv_spinup
riscv_spinup:
.option norelax
csrci sstatus, 0x2
csrw sie, zero
csrw stvec, zero
@ -43,3 +43,5 @@ riscv_spinup:
mv ra, zero
jr t0
.section .note.GNU-stack,"",%progbits

View File

@ -60,3 +60,5 @@ common_spinup:
mov cr4, eax
call edi
section .note.GNU-stack noalloc noexec nowrite progbits

View File

@ -93,3 +93,5 @@ bits 32
mov cr4, eax
call edi
section .note.GNU-stack noalloc noexec nowrite progbits

View File

@ -9,7 +9,7 @@
#include <lib/misc.h>
// Julian date calculation from https://en.wikipedia.org/wiki/Julian_day
static uint64_t get_jdn(uint8_t days, uint8_t months, uint16_t years) {
static int get_jdn(int days, int months, int years) {
return (1461 * (years + 4800 + (months - 14)/12))/4 + (367 *
(months - 2 - 12 * ((months - 14)/12)))/12 -
(3 * ((years + 4900 + (months - 14)/12)/100))/4
@ -63,7 +63,11 @@ again:
#if defined (UEFI)
uint64_t time(void) {
EFI_TIME time;
gRT->GetTime(&time, NULL);
EFI_STATUS status = gRT->GetTime(&time, NULL);
if (status != 0) {
return 0;
}
return get_unix_epoch(time.Second, time.Minute, time.Hour,
time.Day, time.Month, time.Year);

View File

@ -11,7 +11,7 @@
#if defined (BIOS)
extern symbol stage2_map;
#elif defined (UEFI)
extern symbol __image_base;
extern symbol __slide;
#endif
extern symbol full_map;
@ -27,7 +27,7 @@ static char *trace_address(size_t *off, size_t addr) {
#elif defined (UEFI)
limine_map = full_map;
addr -= (size_t)__image_base;
addr -= (size_t)__slide;
#endif
uintptr_t prev_addr = 0;

View File

@ -5,8 +5,10 @@ ENTRY(_start)
PHDRS
{
text_s2 PT_LOAD FLAGS((1 << 0) | (1 << 2)) ;
rodata_s2 PT_LOAD FLAGS((1 << 2)) ;
data_s2 PT_LOAD FLAGS((1 << 1) | (1 << 2)) ;
text_s3 PT_LOAD FLAGS((1 << 0) | (1 << 2)) ;
rodata_s3 PT_LOAD FLAGS((1 << 2)) ;
data_s3 PT_LOAD FLAGS((1 << 1) | (1 << 2)) ;
}
@ -21,17 +23,13 @@ SECTIONS
*libgcc*.a:*(.text .text.*)
} :text_s2
.data.stage2 : {
.rodata.stage2 : {
*.s2.o(.rodata .rodata.*)
*libgcc*.a:*(.rodata .rodata.*)
build_id_s2 = .;
KEEP(*build-id.s2.o(*))
*.s2.o(.no_unwind)
s2_data_begin = .;
*.s2.o(.data .data.*)
*libgcc*.a:*(.data .data.*)
s2_data_end = .;
*.s2.o(.rodata .rodata.*)
*libgcc*.a:*(.rodata .rodata.*)
#ifdef LINKER_STAGE2ONLY
/* stage2 missing symbols overrides */
stage2_map = .;
@ -54,6 +52,15 @@ SECTIONS
*(.stage2_map)
#endif
#endif
} :rodata_s2
.data.stage2 : {
s2_data_begin = .;
*.s2.o(.data .data.*)
*libgcc*.a:*(.data .data.*)
s2_data_end = .;
*.s2.o(.no_unwind)
} :data_s2
#ifndef LINKER_STAGE2ONLY
@ -62,19 +69,25 @@ SECTIONS
*(.text .text.*)
} :text_s3
.data.stage3 : {
.rodata.stage3 : {
*(.rodata .rodata.*)
build_id_s3 = .;
KEEP(*build-id.s3.o(*))
*(.rodata .rodata.*)
#ifdef LINKER_NOMAP
full_map = .;
#else
*(.full_map)
#endif
*(.no_unwind)
} :rodata_s3
.data.stage3 : {
data_begin = .;
*(.data .data.*)
data_end = .;
*(.no_unwind)
} :data_s3
#endif
@ -85,10 +98,9 @@ SECTIONS
.bss : {
bss_begin = .;
*(COMMON)
*(.bss .bss.*)
*(COMMON)
bss_end = .;
data_end = .;
} :data_s3
/DISCARD/ : {

View File

@ -5,6 +5,7 @@ ENTRY(_start)
PHDRS
{
text PT_LOAD FLAGS((1 << 0) | (1 << 2)) ;
rodata PT_LOAD FLAGS((1 << 2)) ;
data PT_LOAD FLAGS((1 << 1) | (1 << 2)) ;
dynamic PT_DYNAMIC FLAGS((1 << 1) | (1 << 2)) ;
}
@ -12,42 +13,32 @@ PHDRS
SECTIONS
{
. = 0;
__image_base = .;
__image_size = __image_end - __image_base;
__slide = .;
__image_base = ABSOLUTE(.);
__image_size = ABSOLUTE(__image_end - __image_base);
.text : {
*(.pe_header)
. = ALIGN(0x1000);
__text_start = ABSOLUTE(.);
*(.text .text.*)
. = ALIGN(0x1000);
} :text
__text_start = __image_base + 0x1000;
__text_size = SIZEOF(.text) - 0x1000;
__text_end = __text_start + __text_size;
.data.sbat : {
*(.data.sbat)
. = ALIGN(0x1000);
} :data
__text_end = ABSOLUTE(.);
__text_size = ABSOLUTE(__text_end - __text_start);
PROVIDE(__sbat_sizev = 1);
.rodata : {
__reloc_start = ABSOLUTE(.);
*(.dummy_reloc)
__sbat_start = __text_end;
__sbat_size = SIZEOF(.data.sbat);
__sbat_end = __sbat_start + __sbat_size;
.data.reloc : {
*(.data.reloc)
. = ALIGN(0x1000);
} :data
__reloc_end = ABSOLUTE(.);
__reloc_size = ABSOLUTE(__reloc_end - __reloc_start);
__reloc_start = __sbat_end;
__reloc_size = SIZEOF(.data.reloc);
__reloc_end = __reloc_start + __reloc_size;
.data : {
__data_start = ABSOLUTE(.);
*(.rodata .rodata.*)
#ifdef LINKER_NOMAP
@ -55,18 +46,16 @@ SECTIONS
#else
*(.full_map)
#endif
} :rodata
*(.no_unwind)
.data : {
data_begin = .;
*(.data .data.*)
*(.bss .bss.*)
*(COMMON)
data_end = .;
} :data
.rela : {
*(.rela .rela.*)
*(.no_unwind)
} :data
.got : {
@ -78,11 +67,10 @@ SECTIONS
. = ALIGN(0x1000);
} :data :dynamic
__data_start = __reloc_end;
__data_size = SIZEOF(.data) + SIZEOF(.rela) + SIZEOF(.got) + SIZEOF(.dynamic);
__data_end = __data_start + __data_size;
__data_end = ABSOLUTE(.);
__data_size = ABSOLUTE(__data_end - __data_start);
__image_end = __data_end;
__image_end = ABSOLUTE(.);
/DISCARD/ : {
*(.eh_frame)

View File

@ -5,6 +5,7 @@ ENTRY(_start)
PHDRS
{
text PT_LOAD FLAGS((1 << 0) | (1 << 2)) ;
rodata PT_LOAD FLAGS((1 << 2)) ;
data PT_LOAD FLAGS((1 << 1) | (1 << 2)) ;
dynamic PT_DYNAMIC FLAGS((1 << 1) | (1 << 2)) ;
}
@ -12,42 +13,32 @@ PHDRS
SECTIONS
{
. = 0;
__image_base = .;
__image_size = __image_end - __image_base;
__slide = .;
__image_base = ABSOLUTE(.);
__image_size = ABSOLUTE(__image_end - __image_base);
.text : {
*(.pe_header)
. = ALIGN(0x1000);
__text_start = ABSOLUTE(.);
*(.text .text.*)
. = ALIGN(0x1000);
} :text
__text_start = __image_base + 0x1000;
__text_size = SIZEOF(.text) - 0x1000;
__text_end = __text_start + __text_size;
.data.sbat : {
*(.data.sbat)
. = ALIGN(0x1000);
} :data
__text_end = ABSOLUTE(.);
__text_size = ABSOLUTE(__text_end - __text_start);
PROVIDE(__sbat_sizev = 1);
.rodata : {
__reloc_start = ABSOLUTE(.);
*(.dummy_reloc)
__sbat_start = __text_end;
__sbat_size = SIZEOF(.data.sbat);
__sbat_end = __sbat_start + __sbat_size;
.data.reloc : {
*(.data.reloc)
. = ALIGN(0x1000);
} :data
__reloc_end = ABSOLUTE(.);
__reloc_size = ABSOLUTE(__reloc_end - __reloc_start);
__reloc_start = __sbat_end;
__reloc_size = SIZEOF(.data.reloc);
__reloc_end = __reloc_start + __reloc_size;
.data : {
__data_start = ABSOLUTE(.);
*(.rodata .rodata.*)
#ifdef LINKER_NOMAP
@ -55,18 +46,16 @@ SECTIONS
#else
*(.full_map)
#endif
} :rodata
*(.no_unwind)
.data : {
data_begin = .;
*(.data .data.*)
*(.bss .bss.*)
*(COMMON)
data_end = .;
} :data
.rel : {
*(.rel .rel.*)
*(.no_unwind)
} :data
.got : {
@ -78,11 +67,10 @@ SECTIONS
. = ALIGN(0x1000);
} :data :dynamic
__data_start = __reloc_end;
__data_size = SIZEOF(.data) + SIZEOF(.rel) + SIZEOF(.got) + SIZEOF(.dynamic);
__data_end = __data_start + __data_size;
__data_end = ABSOLUTE(.);
__data_size = ABSOLUTE(__data_end - __data_start);
__image_end = __data_end;
__image_end = ABSOLUTE(.);
/DISCARD/ : {
*(.eh_frame)

View File

@ -1,10 +1,11 @@
OUTPUT_FORMAT(elf64-littleriscv)
OUTPUT_ARCH(riscv)
OUTPUT_ARCH(riscv:rv64)
ENTRY(_start)
PHDRS
{
text PT_LOAD FLAGS((1 << 0) | (1 << 2)) ;
rodata PT_LOAD FLAGS((1 << 2)) ;
data PT_LOAD FLAGS((1 << 1) | (1 << 2)) ;
dynamic PT_DYNAMIC FLAGS((1 << 1) | (1 << 2)) ;
}
@ -12,42 +13,32 @@ PHDRS
SECTIONS
{
. = 0;
__image_base = .;
__image_size = __image_end - __image_base;
__slide = .;
__image_base = ABSOLUTE(.);
__image_size = ABSOLUTE(__image_end - __image_base);
.text : {
*(.pe_header)
. = ALIGN(0x1000);
__text_start = ABSOLUTE(.);
*(.text .text.*)
. = ALIGN(0x1000);
} :text
__text_start = __image_base + 0x1000;
__text_size = SIZEOF(.text) - 0x1000;
__text_end = __text_start + __text_size;
.data.sbat : {
*(.data.sbat)
. = ALIGN(0x1000);
} :data
__text_end = ABSOLUTE(.);
__text_size = ABSOLUTE(__text_end - __text_start);
PROVIDE(__sbat_sizev = 1);
.rodata : {
__reloc_start = ABSOLUTE(.);
*(.dummy_reloc)
__sbat_start = __text_end;
__sbat_size = SIZEOF(.data.sbat);
__sbat_end = __sbat_start + __sbat_size;
.data.reloc : {
*(.data.reloc)
. = ALIGN(0x1000);
} :data
__reloc_end = ABSOLUTE(.);
__reloc_size = ABSOLUTE(__reloc_end - __reloc_start);
__reloc_start = __sbat_end;
__reloc_size = SIZEOF(.data.reloc);
__reloc_end = __reloc_start + __reloc_size;
.data : {
__data_start = ABSOLUTE(.);
*(.rodata .rodata.*)
#ifdef LINKER_NOMAP
@ -55,21 +46,18 @@ SECTIONS
#else
*(.full_map)
#endif
} :rodata
*(.no_unwind)
.data : {
data_begin = .;
*(.data .data.*)
__global_pointer$ = . + 0x800;
*(.sdata .sdata.*)
*(.sbss .sbss.*)
*(.bss .bss.*)
*(COMMON)
data_end = .;
} :data
.rela : {
*(.rela .rela.*)
*(.no_unwind)
} :data
.got : {
@ -81,11 +69,10 @@ SECTIONS
. = ALIGN(0x1000);
} :data :dynamic
__data_start = __reloc_end;
__data_size = SIZEOF(.data) + SIZEOF(.rela) + SIZEOF(.got) + SIZEOF(.dynamic);
__data_end = __data_start + __data_size;
__data_end = ABSOLUTE(.);
__data_size = ABSOLUTE(__data_end - __data_start);
__image_end = __data_end;
__image_end = ABSOLUTE(.);
/DISCARD/ : {
*(.eh_frame)

View File

@ -5,6 +5,7 @@ ENTRY(_start)
PHDRS
{
text PT_LOAD FLAGS((1 << 0) | (1 << 2)) ;
rodata PT_LOAD FLAGS((1 << 2)) ;
data PT_LOAD FLAGS((1 << 1) | (1 << 2)) ;
dynamic PT_DYNAMIC FLAGS((1 << 1) | (1 << 2)) ;
}
@ -12,42 +13,32 @@ PHDRS
SECTIONS
{
. = 0;
__image_base = .;
__image_size = __image_end - __image_base;
__slide = .;
__image_base = ABSOLUTE(.);
__image_size = ABSOLUTE(__image_end - __image_base);
.text : {
*(.pe_header)
. = ALIGN(0x1000);
__text_start = ABSOLUTE(.);
*(.text .text.*)
. = ALIGN(0x1000);
} :text
__text_start = __image_base + 0x1000;
__text_size = SIZEOF(.text) - 0x1000;
__text_end = __text_start + __text_size;
.data.sbat : {
*(.data.sbat)
. = ALIGN(0x1000);
} :data
__text_end = ABSOLUTE(.);
__text_size = ABSOLUTE(__text_end - __text_start);
PROVIDE(__sbat_sizev = 1);
.rodata : {
__reloc_start = ABSOLUTE(.);
*(.dummy_reloc)
__sbat_start = __text_end;
__sbat_size = SIZEOF(.data.sbat);
__sbat_end = __sbat_start + __sbat_size;
.data.reloc : {
*(.data.reloc)
. = ALIGN(0x1000);
} :data
__reloc_end = ABSOLUTE(.);
__reloc_size = ABSOLUTE(__reloc_end - __reloc_start);
__reloc_start = __sbat_end;
__reloc_size = SIZEOF(.data.reloc);
__reloc_end = __reloc_start + __reloc_size;
.data : {
__data_start = ABSOLUTE(.);
*(.rodata .rodata.*)
#ifdef LINKER_NOMAP
@ -55,18 +46,16 @@ SECTIONS
#else
*(.full_map)
#endif
} :rodata
*(.no_unwind)
.data : {
data_begin = .;
*(.data .data.*)
*(.bss .bss.*)
*(COMMON)
data_end = .;
} :data
.rela : {
*(.rela .rela.*)
*(.no_unwind)
} :data
.got : {
@ -78,11 +67,10 @@ SECTIONS
. = ALIGN(0x1000);
} :data :dynamic
__data_start = __reloc_end;
__data_size = SIZEOF(.data) + SIZEOF(.rela) + SIZEOF(.got) + SIZEOF(.dynamic);
__data_end = __data_start + __data_size;
__data_end = ABSOLUTE(.);
__data_size = ABSOLUTE(__data_end - __data_start);
__image_end = __data_end;
__image_end = ABSOLUTE(.);
/DISCARD/ : {
*(.eh_frame)

View File

@ -495,15 +495,29 @@ refresh:
static size_t print_tree(size_t offset, size_t window, const char *shift, size_t level, size_t base_index, size_t selected_entry,
struct menu_entry *current_entry,
struct menu_entry **selected_menu_entry) {
struct menu_entry **selected_menu_entry,
size_t *max_len, size_t *max_height) {
size_t max_entries = 0;
bool no_print = false;
size_t dummy_max_len = 0;
if (max_len == NULL) {
max_len = &dummy_max_len;
}
size_t dummy_max_height = 0;
if (max_height == NULL) {
max_height = &dummy_max_height;
}
if (!level) {
*max_len = 0;
*max_height = 0;
}
if (shift == NULL) {
no_print = true;
}
for (;;) {
size_t cur_len = 0;
if (current_entry == NULL)
break;
if (!no_print && base_index + max_entries < offset) {
@ -523,34 +537,45 @@ static size_t print_tree(size_t offset, size_t window, const char *shift, size_t
} else {
if (!no_print) print(" ");
}
cur_len += 2;
}
if (current_entry->next == NULL) {
if (!no_print) print(serial ? " `" : "");
} else {
if (!no_print) print(serial ? " |" : "");
}
cur_len += 2;
}
if (current_entry->sub) {
if (!no_print) print(current_entry->expanded ? "[-]" : "[+]");
cur_len += 3;
} else if (level) {
if (!no_print) print(serial ? "-> " : "─> ");
if (!no_print) print(serial ? "-> " : "─►");
cur_len += 2;
} else {
if (!no_print) print(" ");
cur_len += 3;
}
if (base_index + max_entries == selected_entry) {
*selected_menu_entry = current_entry;
if (!no_print) print("\e[7m");
}
if (!no_print) print(" %s \e[27m\n", current_entry->name);
(*max_height)++;
cur_len += 1 + strlen(current_entry->name) + 1;
skip_line:
if (current_entry->sub && current_entry->expanded) {
max_entries += print_tree(offset, window, shift, level + 1, base_index + max_entries + 1,
selected_entry,
current_entry->sub,
selected_menu_entry);
selected_menu_entry,
max_len, max_height);
}
max_entries++;
current_entry = current_entry->next;
if (cur_len > *max_len) {
*max_len = cur_len;
}
}
return max_entries;
}
@ -560,6 +585,7 @@ static size_t rewound_memmap_entries = 0;
static no_unwind uint8_t *rewound_data;
#if defined (BIOS)
static no_unwind uint8_t *rewound_s2_data;
static no_unwind uint8_t *rewound_bss;
#endif
extern symbol data_begin;
@ -567,6 +593,8 @@ extern symbol data_end;
#if defined (BIOS)
extern symbol s2_data_begin;
extern symbol s2_data_end;
extern symbol bss_begin;
extern symbol bss_end;
#endif
static void menu_init_term(void) {
@ -604,12 +632,14 @@ noreturn void _menu(bool first_run) {
size_t data_size = (uintptr_t)data_end - (uintptr_t)data_begin;
#if defined (BIOS)
size_t s2_data_size = (uintptr_t)s2_data_end - (uintptr_t)s2_data_begin;
size_t bss_size = (uintptr_t)bss_end - (uintptr_t)bss_begin;
#endif
if (rewound_memmap != NULL) {
memcpy(data_begin, rewound_data, data_size);
#if defined (BIOS)
memcpy(s2_data_begin, rewound_s2_data, s2_data_size);
memcpy(bss_begin, rewound_bss, bss_size);
#endif
memcpy(memmap, rewound_memmap, rewound_memmap_entries * sizeof(struct memmap_entry));
memmap_entries = rewound_memmap_entries;
@ -617,13 +647,18 @@ noreturn void _menu(bool first_run) {
rewound_data = ext_mem_alloc(data_size);
#if defined (BIOS)
rewound_s2_data = ext_mem_alloc(s2_data_size);
rewound_bss = ext_mem_alloc(bss_size);
#endif
rewound_memmap = ext_mem_alloc(256 * sizeof(struct memmap_entry));
rewound_memmap = ext_mem_alloc(MEMMAP_MAX * sizeof(struct memmap_entry));
if (memmap_entries > MEMMAP_MAX) {
panic(false, "menu: Too many memmap entries");
}
memcpy(rewound_memmap, memmap, memmap_entries * sizeof(struct memmap_entry));
rewound_memmap_entries = memmap_entries;
memcpy(rewound_data, data_begin, data_size);
#if defined (BIOS)
memcpy(rewound_s2_data, s2_data_begin, s2_data_size);
memcpy(rewound_bss, bss_begin, bss_size);
#endif
}
@ -669,6 +704,11 @@ noreturn void _menu(bool first_run) {
editor_enabled = strcmp(editor_enabled_str, "yes") == 0;
}
char *help_hidden_str = config_get_value(NULL, 0, "INTERFACE_HELP_HIDDEN");
if (help_hidden_str != NULL) {
help_hidden = strcmp(help_hidden_str, "yes") == 0;
}
menu_branding = config_get_value(NULL, 0, "INTERFACE_BRANDING");
if (menu_branding == NULL)
menu_branding = "Limine " LIMINE_VERSION;
@ -706,7 +746,7 @@ noreturn void _menu(bool first_run) {
if (!skip_timeout && !timeout) {
// Use print tree to load up selected_menu_entry and determine if the
// default entry is valid.
print_tree(0, 0, NULL, 0, 0, selected_entry, menu_tree, &selected_menu_entry);
print_tree(0, 0, NULL, 0, 0, selected_entry, menu_tree, &selected_menu_entry, NULL, NULL);
if (selected_menu_entry == NULL || selected_menu_entry->sub != NULL) {
quiet = false;
print("Default entry is not valid or directory, booting to menu.\n");
@ -759,43 +799,20 @@ refresh:
console();
}
{ // Draw box around boot menu
size_t x, y;
terms[0]->get_cursor_pos(terms[0], &x, &y);
size_t max_tree_len, max_tree_height;
print_tree(tree_offset, terms[0]->rows - 10, NULL, 0, 0, selected_entry, menu_tree,
&selected_menu_entry, &max_tree_len, &max_tree_height);
print(serial ? "/" : "");
for (size_t i = 0; i < terms[0]->cols - 2; i++) {
switch (i) {
case 1: case 2: case 3:
if (tree_offset > 0) {
print(serial ? "^" : ""); break;
}
// FALLTHRU
default:
print(serial ? "-" : ""); break;
}
}
print(serial ? "\\" : "");
size_t tree_prefix_len = (terms[0]->cols / 2 - DIV_ROUNDUP(max_tree_len, 2)) - 2;
char *tree_prefix = ext_mem_alloc(tree_prefix_len + 1);
memset(tree_prefix, ' ', tree_prefix_len);
for (size_t i = y + 1; i < terms[0]->rows - 2; i++) {
set_cursor_pos_helper(0, i);
print(serial ? "|" : "");
set_cursor_pos_helper(terms[0]->cols - 1, i);
print(serial ? "|" : "");
}
set_cursor_pos_helper(0, terms[0]->rows - 2);
set_cursor_pos_helper(0, terms[0]->rows / 2 - DIV_ROUNDUP(max_tree_height, 2));
print(serial ? "\\" : "");
for (size_t i = 0; i < terms[0]->cols - 2; i++) {
print(serial ? "-" : "");
}
print(serial ? "/" : "");
size_t max_entries = print_tree(tree_offset, terms[0]->rows - 10, tree_prefix, 0, 0, selected_entry, menu_tree,
&selected_menu_entry, NULL, NULL);
set_cursor_pos_helper(x, y + 2);
}
size_t max_entries = print_tree(tree_offset, terms[0]->rows - 10, serial ? "| " : "", 0, 0, selected_entry, menu_tree,
&selected_menu_entry);
pmm_free(tree_prefix, tree_prefix_len);
{
size_t x, y;
@ -806,6 +823,7 @@ refresh:
print(serial ? "vvv" : "↓↓↓");
}
if (!help_hidden) {
set_cursor_pos_helper(0, 3);
if (editor_enabled && selected_menu_entry->sub == NULL) {
print(" \e[32mARROWS\e[0m Select \e[32mENTER\e[0m Boot \e[32mE\e[0m Edit");
@ -815,6 +833,7 @@ refresh:
}
set_cursor_pos_helper(terms[0]->cols - 13, 3);
print("\e[32mC\e[0m Console");
}
set_cursor_pos_helper(x, y);
}
@ -865,7 +884,7 @@ timeout_aborted:
if (ent < (int)max_entries) {
selected_entry = ent;
print_tree(0, 0, NULL, 0, 0, selected_entry, menu_tree,
&selected_menu_entry);
&selected_menu_entry, NULL, NULL);
goto autoboot;
}
goto refresh;

View File

@ -23,3 +23,5 @@ menu:
mov x29, xzr
b _menu
.section .note.GNU-stack,"",%progbits

View File

@ -26,3 +26,4 @@ menu:
push 0
jmp _menu
section .note.GNU-stack noalloc noexec nowrite progbits

View File

@ -10,6 +10,7 @@ stack_at_first_entry:
.extern _menu
menu:
.option norelax
lla t0, stack_at_first_entry
ld t1, (t0)
beqz t1, 1f
@ -19,3 +20,5 @@ menu:
2: mv fp, zero
mv ra, zero
j _menu
.section .note.GNU-stack,"",%progbits

View File

@ -19,3 +19,5 @@ menu:
push 0
push 0
jmp _menu
section .note.GNU-stack noalloc noexec nowrite progbits

View File

@ -22,6 +22,8 @@ struct memmap_entry {
#define MEMMAP_FRAMEBUFFER 0x1002
#define MEMMAP_EFI_RECLAIMABLE 0x2000
#define MEMMAP_MAX 512
struct meminfo {
size_t uppermem;
size_t lowermem;
@ -56,6 +58,7 @@ void pmm_randomise_memory(void);
void *ext_mem_alloc(size_t count);
void *ext_mem_alloc_type(size_t count, uint32_t type);
void *ext_mem_alloc_type_aligned(size_t count, uint32_t type, size_t alignment);
void *ext_mem_alloc_type_aligned_mode(size_t count, uint32_t type, size_t alignment, bool allow_high_allocs);
void *conv_mem_alloc(size_t count);

View File

@ -288,8 +288,8 @@ void init_memmap(void) {
#if defined (UEFI)
static struct memmap_entry *recl;
extern symbol __image_base;
extern symbol __image_end;
extern symbol __slide;
extern symbol __image_size;
void init_memmap(void) {
EFI_STATUS status;
@ -356,6 +356,7 @@ void init_memmap(void) {
uint64_t base = entry->PhysicalStart;
uint64_t length = entry->NumberOfPages * 4096;
#if !defined (__x86_64__) && !defined (__aarch64__) && !defined (__riscv64)
// We only manage memory below 4GiB. For anything above that, make it
// EFI reclaimable.
if (our_type == MEMMAP_USABLE) {
@ -374,6 +375,7 @@ void init_memmap(void) {
our_type = MEMMAP_EFI_RECLAIMABLE;
}
}
#endif
memmap[memmap_entries].base = base;
memmap[memmap_entries].length = length;
@ -422,10 +424,8 @@ void init_memmap(void) {
sanitiser_keep_first_page = old_skfp;
size_t bootloader_size = ALIGN_UP((uintptr_t)__image_end - (uintptr_t)__image_base, 4096);
// Allocate bootloader itself
memmap_alloc_range((uintptr_t)__image_base, bootloader_size,
memmap_alloc_range((uintptr_t)__slide, (uintptr_t)__image_size,
MEMMAP_BOOTLOADER_RECLAIMABLE, 0, true, false, true);
sanitise_entries(memmap, &memmap_entries, false);
@ -567,8 +567,16 @@ void *ext_mem_alloc_type(size_t count, uint32_t type) {
return ext_mem_alloc_type_aligned(count, type, 4096);
}
// Allocate memory top down, hopefully without bumping into kernel or modules
void *ext_mem_alloc_type_aligned(size_t count, uint32_t type, size_t alignment) {
return ext_mem_alloc_type_aligned_mode(count, type, alignment, false);
}
// Allocate memory top down.
void *ext_mem_alloc_type_aligned_mode(size_t count, uint32_t type, size_t alignment, bool allow_high_allocs) {
#if !defined (__x86_64__)
(void)allow_high_allocs;
#endif
count = ALIGN_UP(count, alignment);
if (allocations_disallowed)
@ -581,12 +589,18 @@ void *ext_mem_alloc_type_aligned(size_t count, uint32_t type, size_t alignment)
int64_t entry_base = (int64_t)(memmap[i].base);
int64_t entry_top = (int64_t)(memmap[i].base + memmap[i].length);
#if defined(__x86_64__) || defined(__i386__)
// Let's make sure the entry is not > 4GiB
if (entry_top >= 0x100000000) {
if (entry_top >= 0x100000000
#if defined (__x86_64__)
&& !allow_high_allocs
#endif
) {
entry_top = 0x100000000;
if (entry_base >= entry_top)
continue;
}
#endif
int64_t alloc_base = ALIGN_DOWN(entry_top - (int64_t)count, alignment);

View File

@ -119,6 +119,12 @@ level4:
pml1 = get_next_level(pagemap, pml2, virt_addr, pg_size, 1, pml2_entry);
// PML1 wants PAT bit at 7 instead of 12
if (flags & ((uint64_t)1 << 12)) {
flags &= ~((uint64_t)1 << 12);
flags |= ((uint64_t)1 << 7);
}
pml1[pml1_entry] = (pt_entry_t)(phys_addr | flags);
}
@ -246,6 +252,7 @@ level4:
#define PT_FLAG_USER ((uint64_t)1 << 4)
#define PT_FLAG_ACCESSED ((uint64_t)1 << 6)
#define PT_FLAG_DIRTY ((uint64_t)1 << 7)
#define PT_FLAG_PBMT_NC ((uint64_t)1 << 62)
#define PT_PADDR_MASK ((uint64_t)0x003ffffffffffc00)
#define PT_FLAG_RWX (PT_FLAG_READ | PT_FLAG_WRITE | PT_FLAG_EXEC)
@ -265,6 +272,8 @@ static uint64_t pt_to_vmm_flags_internal(pt_entry_t entry) {
flags |= VMM_FLAG_WRITE;
if (!(entry & PT_FLAG_EXEC))
flags |= VMM_FLAG_NOEXEC;
if (entry & PT_FLAG_PBMT_NC)
flags |= VMM_FLAG_FB;
return flags;
}
@ -312,7 +321,7 @@ int vmm_max_paging_mode(void)
pt_entry_t entry = PT_FLAG_ACCESSED | PT_FLAG_DIRTY | PT_FLAG_RWX | PT_FLAG_VALID;
for (int i = 0; i < 256; i++) {
table[i] = entry;
entry += page_sizes[lvl];
entry += page_sizes[lvl] >> 2;
}
uint64_t satp = ((uint64_t)(6 + lvl) << 60) | ((uint64_t)table >> 12);
@ -331,11 +340,19 @@ done:
return 6 + max_level;
}
static pt_entry_t pbmt_nc = 0;
pagemap_t new_pagemap(int paging_mode) {
pagemap_t pagemap;
pagemap.paging_mode = paging_mode;
pagemap.max_page_size = paging_mode - 6;
pagemap.top_level = ext_mem_alloc(PT_SIZE);
if (riscv_check_isa_extension("svpbmt", NULL, NULL)) {
printv("riscv: Svpbmt extension is supported.\n");
pbmt_nc = PT_FLAG_PBMT_NC;
}
return pagemap;
}
@ -351,6 +368,8 @@ void map_page(pagemap_t pagemap, uint64_t virt_addr, uint64_t phys_addr, uint64_
ptflags |= PT_FLAG_WRITE;
if (!(flags & VMM_FLAG_NOEXEC))
ptflags |= PT_FLAG_EXEC;
if (flags & VMM_FLAG_FB)
ptflags |= pbmt_nc;
// Start at the highest level.
// The values of `enum page_size` map to the level index at which that size is mapped.

View File

@ -8,7 +8,7 @@
#define VMM_FLAG_WRITE ((uint64_t)1 << 1)
#define VMM_FLAG_NOEXEC ((uint64_t)1 << 63)
#define VMM_FLAG_FB ((uint64_t)0)
#define VMM_FLAG_FB (((uint64_t)1 << 3) | ((uint64_t)1 << 12))
#define VMM_MAX_LEVEL 3
@ -52,13 +52,13 @@ void map_page(pagemap_t pagemap, uint64_t virt_addr, uint64_t phys_addr, uint64_
#define PAGING_MODE_AARCH64_4LVL 0
#define PAGING_MODE_AARCH64_5LVL 1
#define paging_mode_va_bits(mode) ((mode) ? 57 : 48)
#define paging_mode_va_bits(mode) ((mode) ? 52 : 48)
static inline uint64_t paging_mode_higher_half(int paging_mode) {
if (paging_mode == PAGING_MODE_AARCH64_5LVL) {
return 0xff00000000000000;
return 0xffc0000000000000;
} else {
return 0xffff800000000000;
return 0xffff000000000000;
}
}

View File

@ -217,15 +217,13 @@ noreturn void efi_chainload_file(char *config, char *cmdline, struct file_handle
EFI_HANDLE efi_part_handle = image->efi_part_handle;
void *_ptr = freadall(image, MEMMAP_RESERVED);
void *ptr = freadall(image, MEMMAP_RESERVED);
size_t image_size = image->size;
void *ptr;
status = gBS->AllocatePool(EfiLoaderData, image_size, &ptr);
if (status)
panic(true, "chainload: Allocation failure");
memcpy(ptr, _ptr, image_size);
pmm_free(_ptr, image->size);
memmap_alloc_range_in(untouched_memmap, &untouched_memmap_entries,
(uintptr_t)ptr, ALIGN_UP(image_size, 4096),
MEMMAP_RESERVED, MEMMAP_USABLE, true, false, true);
fclose(image);
term_notready();
@ -242,7 +240,7 @@ noreturn void efi_chainload_file(char *config, char *cmdline, struct file_handle
size_t cmdline_len = strlen(cmdline);
CHAR16 *new_cmdline;
status = gBS->AllocatePool(EfiLoaderData, cmdline_len * sizeof(CHAR16), (void **)&new_cmdline);
status = gBS->AllocatePool(EfiLoaderData, (cmdline_len + 1) * sizeof(CHAR16), (void **)&new_cmdline);
if (status) {
panic(true, "chainload: Allocation failure");
}

View File

@ -33,7 +33,6 @@
#include <limine.h>
#define MAX_REQUESTS 128
#define MAX_MEMMAP 256
static pagemap_t build_pagemap(int paging_mode, bool nx, struct elf_range *ranges, size_t ranges_count,
uint64_t physical_base, uint64_t virtual_base,
@ -41,11 +40,9 @@ static pagemap_t build_pagemap(int paging_mode, bool nx, struct elf_range *range
pagemap_t pagemap = new_pagemap(paging_mode);
if (ranges_count == 0) {
// Map 0 to 2GiB at 0xffffffff80000000
for (uint64_t i = 0; i < 0x80000000; i += 0x40000000) {
map_page(pagemap, 0xffffffff80000000 + i, i, VMM_FLAG_WRITE, Size1GiB);
panic(true, "limine: ranges_count == 0");
}
} else {
for (size_t i = 0; i < ranges_count; i++) {
uint64_t virt = ranges[i].base;
uint64_t phys;
@ -53,7 +50,7 @@ static pagemap_t build_pagemap(int paging_mode, bool nx, struct elf_range *range
if (virt & ((uint64_t)1 << 63)) {
phys = physical_base + (virt - virtual_base);
} else {
panic(false, "limine: Protected memory ranges are only supported for higher half kernels");
panic(false, "limine: Virtual address of a PHDR in lower half");
}
uint64_t pf =
@ -64,7 +61,6 @@ static pagemap_t build_pagemap(int paging_mode, bool nx, struct elf_range *range
map_page(pagemap, virt + j, phys + j, pf, Size4KiB);
}
}
}
// Sub 2MiB mappings
for (uint64_t i = 0; i < 0x200000; i += 0x1000) {
@ -108,11 +104,13 @@ static pagemap_t build_pagemap(int paging_mode, bool nx, struct elf_range *range
uint64_t length = _memmap[i].length;
uint64_t top = base + length;
if (base < 0x100000000)
if (base < 0x100000000) {
base = 0x100000000;
}
if (base >= top)
if (base >= top) {
continue;
}
uint64_t aligned_base = ALIGN_DOWN(base, 0x40000000);
uint64_t aligned_top = ALIGN_UP(top, 0x40000000);
@ -125,16 +123,16 @@ static pagemap_t build_pagemap(int paging_mode, bool nx, struct elf_range *range
}
}
// Map the framebuffer as uncacheable
#if defined (__aarch64__)
// Map the framebuffer with appropriate permissions
for (size_t i = 0; i < _memmap_entries; i++) {
if (_memmap[i].type != MEMMAP_FRAMEBUFFER) {
continue;
}
uint64_t base = _memmap[i].base;
uint64_t length = _memmap[i].length;
uint64_t top = base + length;
if (_memmap[i].type != MEMMAP_FRAMEBUFFER)
continue;
uint64_t aligned_base = ALIGN_DOWN(base, 0x1000);
uint64_t aligned_top = ALIGN_UP(top, 0x1000);
uint64_t aligned_length = aligned_top - aligned_base;
@ -145,7 +143,6 @@ static pagemap_t build_pagemap(int paging_mode, bool nx, struct elf_range *range
map_page(pagemap, direct_map_offset + page, page, VMM_FLAG_WRITE | VMM_FLAG_FB, Size4KiB);
}
}
#endif
return pagemap;
}
@ -252,7 +249,7 @@ static struct limine_file get_file(struct file_handle *file, char *cmdline) {
ret.path = reported_addr(path);
ret.address = reported_addr(freadall(file, MEMMAP_KERNEL_AND_MODULES));
ret.address = reported_addr(freadall_mode(file, MEMMAP_KERNEL_AND_MODULES, true));
ret.size = file->size;
ret.cmdline = reported_addr(cmdline);
@ -570,7 +567,11 @@ FEAT_START
smbios_response->entry_64 = reported_addr(smbios_entry_64);
}
if (smbios_entry_32 == NULL && smbios_entry_64 == NULL) {
pmm_free(smbios_response, sizeof(struct limine_smbios_response));
} else {
smbios_request->response = reported_addr(smbios_response);
}
FEAT_END
#if defined (UEFI)
@ -933,19 +934,6 @@ FEAT_END
pagemap = build_pagemap(paging_mode, nx_available, ranges, ranges_count,
physical_base, virtual_base, direct_map_offset);
#if defined (__riscv64)
// Fetch the BSP's Hart ID before exiting boot services.
size_t bsp_hartid;
bool have_bsp_hartid = false;
RISCV_EFI_BOOT_PROTOCOL *riscv_boot_proto = get_riscv_boot_protocol();
if (riscv_boot_proto != NULL) {
if (riscv_boot_proto->GetBootHartId(riscv_boot_proto, &bsp_hartid) == EFI_SUCCESS) {
have_bsp_hartid = true;
}
}
#endif
#if defined (UEFI)
efi_exit_boot_services();
#endif
@ -962,7 +950,7 @@ FEAT_START
#if defined (__x86_64__) || defined (__i386__)
uint32_t bsp_lapic_id;
smp_info = init_smp(&cpu_count, &bsp_lapic_id,
true, paging_mode,
paging_mode,
pagemap, smp_request->flags & LIMINE_SMP_X2APIC, nx_available,
direct_map_offset, true);
#elif defined (__aarch64__)
@ -971,12 +959,7 @@ FEAT_START
smp_info = init_smp(&cpu_count, &bsp_mpidr,
pagemap, LIMINE_MAIR(fb_attr), LIMINE_TCR(tsz, pa), LIMINE_SCTLR);
#elif defined (__riscv64)
if (!have_bsp_hartid) {
printv("smp: failed to get bsp's hart id\n");
break;
}
smp_info = init_smp(&cpu_count, bsp_hartid, pagemap);
smp_info = init_smp(&cpu_count, pagemap);
#else
#error Unknown architecture
#endif
@ -1024,8 +1007,8 @@ FEAT_START
if (memmap_request != NULL) {
memmap_response = ext_mem_alloc(sizeof(struct limine_memmap_response));
_memmap = ext_mem_alloc(sizeof(struct limine_memmap_entry) * MAX_MEMMAP);
memmap_list = ext_mem_alloc(MAX_MEMMAP * sizeof(uint64_t));
_memmap = ext_mem_alloc(sizeof(struct limine_memmap_entry) * MEMMAP_MAX);
memmap_list = ext_mem_alloc(MEMMAP_MAX * sizeof(uint64_t));
}
size_t mmap_entries;
@ -1035,7 +1018,7 @@ FEAT_START
break; // next feature
}
if (mmap_entries > MAX_MEMMAP) {
if (mmap_entries > MEMMAP_MAX) {
panic(false, "limine: Too many memmap entries");
}
@ -1093,6 +1076,16 @@ FEAT_END
rm_int(0x15, &r, &r);
#endif
// Set PAT as:
// PAT0 -> WB (06)
// PAT1 -> WT (04)
// PAT2 -> UC- (07)
// PAT3 -> UC (00)
// PAT4 -> WP (05)
// PAT5 -> WC (01)
uint64_t pat = (uint64_t)0x010500070406;
wrmsr(0x277, pat);
pic_mask_all();
io_apic_mask_all();
@ -1108,7 +1101,9 @@ FEAT_END
#elif defined (__aarch64__)
vmm_assert_4k_pages();
enter_in_el1(entry_point, (uint64_t)stack, LIMINE_SCTLR, LIMINE_MAIR(fb_attr), LIMINE_TCR(tsz, pa),
uint64_t reported_stack = reported_addr(stack);
enter_in_el1(entry_point, reported_stack, LIMINE_SCTLR, LIMINE_MAIR(fb_attr), LIMINE_TCR(tsz, pa),
(uint64_t)pagemap.top_level[0],
(uint64_t)pagemap.top_level[1], 0);
#elif defined (__riscv64)

View File

@ -98,3 +98,5 @@ bits 64
xor r15d, r15d
iretq
section .note.GNU-stack noalloc noexec nowrite progbits

View File

@ -9,14 +9,14 @@ linux_gdt:
dw 0xffff
dw 0x0000
db 0x00
db 10011010b
db 10011011b
db 11001111b
db 0x00
dw 0xffff
dw 0x0000
db 0x00
db 10010010b
db 10010011b
db 11001111b
db 0x00
@ -65,3 +65,5 @@ linux_spinup:
cld
jmp [esp+4]
section .note.GNU-stack noalloc noexec nowrite progbits

View File

@ -37,7 +37,7 @@ static size_t get_multiboot1_info_size(
ALIGN_UP(sizeof(section_entry_size * section_num), 16) + // ELF info
ALIGN_UP(sizeof(struct multiboot1_module) * modules_count, 16) + // modules count
ALIGN_UP(modules_cmdlines_size, 16) + // modules command lines
ALIGN_UP(sizeof(struct multiboot1_mmap_entry) * 256, 16); // memory map
ALIGN_UP(sizeof(struct multiboot1_mmap_entry) * MEMMAP_MAX, 16); // memory map
}
static void *mb1_info_alloc(void **mb1_info_raw, size_t size) {

View File

@ -46,9 +46,9 @@ static size_t get_multiboot2_info_size(
ALIGN_UP(sizeof(struct multiboot_tag_load_base_addr), MULTIBOOT_TAG_ALIGN) + // load base address
ALIGN_UP(smbios_tag_size, MULTIBOOT_TAG_ALIGN) + // SMBIOS
ALIGN_UP(sizeof(struct multiboot_tag_basic_meminfo), MULTIBOOT_TAG_ALIGN) + // basic memory info
ALIGN_UP(sizeof(struct multiboot_tag_mmap) + sizeof(struct multiboot_mmap_entry) * 256, MULTIBOOT_TAG_ALIGN) + // MMAP
ALIGN_UP(sizeof(struct multiboot_tag_mmap) + sizeof(struct multiboot_mmap_entry) * MEMMAP_MAX, MULTIBOOT_TAG_ALIGN) + // MMAP
#if defined (UEFI)
ALIGN_UP(sizeof(struct multiboot_tag_efi_mmap) + (efi_desc_size * 256), MULTIBOOT_TAG_ALIGN) + // EFI MMAP
ALIGN_UP(sizeof(struct multiboot_tag_efi_mmap) + (efi_desc_size * MEMMAP_MAX), MULTIBOOT_TAG_ALIGN) + // EFI MMAP
#if defined (__i386__)
ALIGN_UP(sizeof(struct multiboot_tag_efi32), MULTIBOOT_TAG_ALIGN) + // EFI system table 32
ALIGN_UP(sizeof(struct multiboot_tag_efi32_ih), MULTIBOOT_TAG_ALIGN) + // EFI image handle 32
@ -738,7 +738,7 @@ skip_modeset:;
// Create memory map tag
//////////////////////////////////////////////
{
if (mb_mmap_count > 256) {
if (mb_mmap_count > MEMMAP_MAX) {
panic(false, "multiboot2: too many memory map entries");
}
@ -785,7 +785,7 @@ skip_modeset:;
//////////////////////////////////////////////
#if defined (UEFI)
{
if ((efi_mmap_size / efi_desc_size) > 256) {
if ((efi_mmap_size / efi_desc_size) > MEMMAP_MAX) {
panic(false, "multiboot2: too many EFI memory map entries");
}

View File

@ -19,3 +19,5 @@ multiboot_spinup_32:
pop edx ; elf_ranges_count
jmp ebx
section .note.GNU-stack noalloc noexec nowrite progbits

View File

@ -62,3 +62,5 @@ multiboot_reloc_stub:
global multiboot_reloc_stub_end
multiboot_reloc_stub_end:
section .note.GNU-stack noalloc noexec nowrite progbits

View File

@ -95,3 +95,5 @@ align 16
.idt: dq 0
.rm_idt: dw 0x3ff
dd 0
section .note.GNU-stack noalloc noexec nowrite progbits

View File

@ -1,15 +0,0 @@
#if defined (UEFI)
#include <config.h>
asm (
".section .data.sbat\n\t"
"sbat:\n\t"
".ascii \"sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md\\n\"\n\t"
".ascii \"limine,1,Limine,limine," LIMINE_VERSION ",https://limine-bootloader.org\\n\"\n\t"
"__sbat_endv:\n\t"
".global __sbat_sizev\n\t"
".set __sbat_sizev, __sbat_endv - sbat\n\t"
);
#endif

View File

@ -23,6 +23,6 @@ extern void delay(uint64_t cycles);
extern size_t icache_line_size(void);
extern size_t dcache_line_size(void);
extern void clean_inval_dcache_poc(uintptr_t start, uintptr_t end);
extern void clean_dcache_poc(uintptr_t start, uintptr_t end);
extern void inval_icache_pou(uintptr_t start, uintptr_t end);
extern int current_el(void);

View File

@ -252,13 +252,13 @@ inline size_t dcache_line_size(void) {
return ((ctr >> 16) & 0b1111) << 4;
}
// Clean and invalidate D-Cache to Point of Coherency
inline void clean_inval_dcache_poc(uintptr_t start, uintptr_t end) {
// Clean D-Cache to Point of Coherency
inline void clean_dcache_poc(uintptr_t start, uintptr_t end) {
size_t dsz = dcache_line_size();
uintptr_t addr = start & ~(dsz - 1);
while (addr < end) {
asm volatile ("dc civac, %0" :: "r"(addr) : "memory");
asm volatile ("dc cvac, %0" :: "r"(addr) : "memory");
addr += dsz;
}
@ -320,6 +320,30 @@ inline uint64_t rdtsc(void) {
locked_read__ret; \
})
extern size_t bsp_hartid;
struct riscv_hart {
struct riscv_hart *next;
const char *isa_string;
size_t hartid;
uint32_t acpi_uid;
uint8_t mmu_type;
uint8_t flags;
};
#define RISCV_HART_COPROC ((uint8_t)1 << 0) // is a coprocessor
#define RISCV_HART_HAS_MMU ((uint8_t)1 << 1) // `mmu_type` field is valid
extern struct riscv_hart *hart_list;
bool riscv_check_isa_extension_for(size_t hartid, const char *ext, size_t *maj, size_t *min);
static inline bool riscv_check_isa_extension(const char *ext, size_t *maj, size_t *min) {
return riscv_check_isa_extension_for(bsp_hartid, ext, maj, min);
}
void init_riscv(void);
#else
#error Unknown architecture
#endif

261
common/sys/cpu_riscv.c Normal file
View File

@ -0,0 +1,261 @@
#if defined(__riscv)
#include <lib/acpi.h>
#include <lib/misc.h>
#include <lib/print.h>
#include <sys/cpu.h>
#include <mm/pmm.h>
#include <stddef.h>
#include <stdint.h>
// ACPI RISC-V Hart Capabilities Table
struct rhct {
struct sdt header;
uint32_t flags;
uint64_t time_base_frequency;
uint32_t nodes_len;
uint32_t nodes_offset;
uint8_t nodes[];
} __attribute__((packed));
#define RHCT_ISA_STRING 0
#define RHCT_CMO 1
#define RHCT_MMU 2
#define RHCT_HART_INFO 65535
struct rhct_header {
uint16_t type; // node type
uint16_t size; // node size (bytes)
uint16_t revision; // node revision
} __attribute__((packed));
// One `struct rhct_hart_info` structure exists per hart in the system.
// The `offsets` array points to other entries in the RHCT associated with the
// hart.
struct rhct_hart_info {
struct rhct_header header;
uint16_t offsets_len;
uint32_t acpi_processor_uid;
uint32_t offsets[];
} __attribute__((packed));
struct rhct_isa_string {
struct rhct_header header;
uint16_t isa_string_len;
const char isa_string[];
} __attribute__((packed));
#define RISCV_MMU_TYPE_SV39 0
#define RISCV_MMU_TYPE_SV48 1
#define RISCV_MMU_TYPE_SV57 2
struct rhct_mmu {
struct rhct_header header;
uint8_t reserved0;
uint8_t mmu_type;
} __attribute__((packed));
size_t bsp_hartid;
struct riscv_hart *hart_list;
static struct riscv_hart *bsp_hart;
static struct riscv_hart *riscv_get_hart(size_t hartid) {
for (struct riscv_hart *hart = hart_list; hart != NULL; hart = hart->next) {
if (hart->hartid == hartid) {
return hart;
}
}
panic(false, "no `struct riscv_hart` for hartid %u", hartid);
}
static inline struct rhct_hart_info *rhct_get_hart_info(struct rhct *rhct, uint32_t acpi_uid) {
uint32_t offset = rhct->nodes_offset;
for (uint32_t i = 0; i < rhct->nodes_len; i++) {
struct rhct_hart_info *node = (void *)((uintptr_t)rhct + offset);
if (node->header.type == RHCT_HART_INFO && node->acpi_processor_uid == acpi_uid) {
return node;
}
offset += node->header.size;
}
return NULL;
}
void init_riscv(void) {
struct madt *madt = acpi_get_table("APIC", 0);
struct rhct *rhct = acpi_get_table("RHCT", 0);
if (madt == NULL || rhct == NULL) {
panic(false, "riscv: requires acpi");
}
for (uint8_t *madt_ptr = (uint8_t *)madt->madt_entries_begin;
(uintptr_t)madt_ptr < (uintptr_t)madt + madt->header.length; madt_ptr += *(madt_ptr + 1)) {
if (*madt_ptr != 0x18) {
continue;
}
struct madt_riscv_intc *intc = (struct madt_riscv_intc *)madt_ptr;
// Ignore harts we can't do anything with.
if (!(intc->flags & MADT_RISCV_INTC_ENABLED ||
intc->flags & MADT_RISCV_INTC_ONLINE_CAPABLE)) {
continue;
}
uint32_t acpi_uid = intc->acpi_processor_uid;
size_t hartid = intc->hartid;
struct rhct_hart_info *hart_info = rhct_get_hart_info(rhct, acpi_uid);
if (hart_info == NULL) {
panic(false, "riscv: missing rhct node for hartid %u", hartid);
}
const char *isa_string = NULL;
uint8_t mmu_type = 0;
uint8_t flags = 0;
for (uint32_t i = 0; i < hart_info->offsets_len; i++) {
const struct rhct_header *node = (void *)((uintptr_t)rhct + hart_info->offsets[i]);
switch (node->type) {
case RHCT_ISA_STRING:
isa_string = ((struct rhct_isa_string *)node)->isa_string;
break;
case RHCT_MMU:
mmu_type = ((struct rhct_mmu *)node)->mmu_type;
flags |= RISCV_HART_HAS_MMU;
break;
}
}
if (isa_string == NULL) {
print("riscv: missing isa string for hartid %u, skipping.\n", hartid);
continue;
}
if (strncmp("rv64", isa_string, 4) && strncmp("rv32", isa_string, 4)) {
print("riscv: skipping hartid %u with invalid isa string: %s", hartid, isa_string);
}
struct riscv_hart *hart = ext_mem_alloc(sizeof(struct riscv_hart));
if (hart == NULL) {
panic(false, "out of memory");
}
hart->hartid = hartid;
hart->acpi_uid = acpi_uid;
hart->isa_string = isa_string;
hart->mmu_type = mmu_type;
hart->flags = flags;
hart->next = hart_list;
hart_list = hart;
if (hart->hartid == bsp_hartid) {
bsp_hart = hart;
}
}
if (bsp_hart == NULL) {
panic(false, "riscv: missing `struct riscv_hart` for BSP");
}
if (strncasecmp(bsp_hart->isa_string, "rv64i", 5)) {
panic(false, "unsupported cpu: %s", bsp_hart->isa_string);
}
for (struct riscv_hart *hart = hart_list; hart != NULL; hart = hart->next) {
if (hart != bsp_hart && strcmp(bsp_hart->isa_string, hart->isa_string)) {
hart->flags |= RISCV_HART_COPROC;
}
}
}
struct isa_extension {
const char *name;
size_t name_len;
uint32_t ver_maj;
uint32_t ver_min;
};
// Parse the next sequence of digit characters into an integer.
static bool parse_number(const char **s, size_t *_n) {
size_t n = 0;
bool parsed = false;
while (isdigit(**s)) {
n *= 10;
n += *(*s)++ - '0';
parsed = true;
}
*_n = n;
return parsed;
}
// Parse the next extension from an ISA string.
static bool parse_extension(const char **s, struct isa_extension *ext) {
if (**s == '\0') {
return false;
}
const char *name = *s;
size_t name_len = 1;
if (**s == 's' || **s == 'S' || **s == 'x' || **s == 'X' || **s == 'z' || **s == 'Z') {
while (isalpha((*s)[name_len])) {
name_len++;
}
}
*s += name_len;
size_t maj = 0, min = 0;
if (parse_number(s, &maj)) {
if (**s == 'p') {
*s += 1;
parse_number(s, &min);
}
}
while (**s == '_') {
*s += 1;
}
if (ext) {
ext->name = name;
ext->name_len = name_len;
ext->ver_maj = maj;
ext->ver_min = min;
}
return true;
}
static bool extension_matches(const struct isa_extension *ext, const char *name) {
for (size_t i = 0; i < ext->name_len; i++) {
const char c1 = tolower(ext->name[i]);
const char c2 = tolower(*name++);
if (c2 == '\0' || c1 != c2) {
return false;
}
}
// Make sure `name` is not longer.
return *name == '\0';
}
bool riscv_check_isa_extension_for(size_t hartid, const char *name, size_t *maj, size_t *min) {
// Skip the `rv{32,64}` prefix so it's not parsed as extensions.
const char *isa_string = riscv_get_hart(hartid)->isa_string + 4;
struct isa_extension ext;
while (parse_extension(&isa_string, &ext)) {
if (!extension_matches(&ext, name)) {
continue;
}
if (maj) {
*maj = ext.ver_maj;
}
if (min) {
*min = ext.ver_min;
}
return true;
}
return false;
}
#endif

View File

@ -8,3 +8,5 @@ dummy_isr:
call lapic_eoi
popa
iretd
section .note.GNU-stack noalloc noexec nowrite progbits

View File

@ -24,3 +24,5 @@ dummy_isr:
pop rcx
pop rax
iretq
section .note.GNU-stack noalloc noexec nowrite progbits

View File

@ -6,7 +6,7 @@
#if defined (BIOS)
static const char *exception_names[] = {
"Division by 0",
"Division",
"Debug",
"NMI",
"Breakpoint",
@ -22,10 +22,10 @@ static const char *exception_names[] = {
"General protection fault",
"Page fault",
"???",
"x87 exception",
"x87",
"Alignment check",
"Machine check",
"SIMD exception",
"SIMD",
"Virtualisation",
"???",
"???",
@ -41,7 +41,7 @@ static const char *exception_names[] = {
void except(uint32_t exception, uint32_t error_code, uint32_t ebp, uint32_t eip) {
(void)ebp;
panic(false, "%s at %x. Error code: %x", exception_names[exception], eip, error_code);
panic(false, "%s exception at %x. Error code: %x", exception_names[exception], eip, error_code);
}
#endif

View File

@ -12,7 +12,7 @@ static struct gdt_desc gdt_descs[] = {
.limit = 0xffff,
.base_low = 0x0000,
.base_mid = 0x00,
.access = 0b10011010,
.access = 0b10011011,
.granularity = 0b00000000,
.base_hi = 0x00
},
@ -21,7 +21,7 @@ static struct gdt_desc gdt_descs[] = {
.limit = 0xffff,
.base_low = 0x0000,
.base_mid = 0x00,
.access = 0b10010010,
.access = 0b10010011,
.granularity = 0b00000000,
.base_hi = 0x00
},
@ -30,7 +30,7 @@ static struct gdt_desc gdt_descs[] = {
.limit = 0xffff,
.base_low = 0x0000,
.base_mid = 0x00,
.access = 0b10011010,
.access = 0b10011011,
.granularity = 0b11001111,
.base_hi = 0x00
},
@ -39,7 +39,7 @@ static struct gdt_desc gdt_descs[] = {
.limit = 0xffff,
.base_low = 0x0000,
.base_mid = 0x00,
.access = 0b10010010,
.access = 0b10010011,
.granularity = 0b11001111,
.base_hi = 0x00
},
@ -48,7 +48,7 @@ static struct gdt_desc gdt_descs[] = {
.limit = 0x0000,
.base_low = 0x0000,
.base_mid = 0x00,
.access = 0b10011010,
.access = 0b10011011,
.granularity = 0b00100000,
.base_hi = 0x00
},
@ -57,7 +57,7 @@ static struct gdt_desc gdt_descs[] = {
.limit = 0x0000,
.base_low = 0x0000,
.base_mid = 0x00,
.access = 0b10010010,
.access = 0b10010011,
.granularity = 0b00000000,
.base_hi = 0x00
}

View File

@ -37,3 +37,5 @@ exceptions:
raise_exception_getaddr i
%assign i i+1
%endrep
section .note.GNU-stack noalloc noexec nowrite progbits

View File

@ -9,22 +9,6 @@
#include <lib/acpi.h>
#include <mm/pmm.h>
struct madt {
struct sdt header;
uint32_t local_controller_addr;
uint32_t flags;
char madt_entries_begin[];
} __attribute__((packed));
struct madt_io_apic {
uint8_t type;
uint8_t length;
uint8_t apic_id;
uint8_t reserved;
uint32_t address;
uint32_t gsib;
} __attribute__((packed));
struct dmar {
struct sdt header;
uint8_t host_address_width;
@ -172,6 +156,14 @@ void io_apic_mask_all(void) {
uint32_t gsi_count = io_apic_gsi_count(i);
for (uint32_t j = 0; j < gsi_count; j++) {
uintptr_t ioredtbl = j * 2 + 16;
switch ((io_apic_read(i, ioredtbl) >> 8) & 0b111) {
case 0b000: // Fixed
case 0b001: // Lowest Priority
break;
default:
continue;
}
io_apic_write(i, ioredtbl, (1 << 16)); // mask
io_apic_write(i, ioredtbl + 1, 0);
}

View File

@ -2,6 +2,7 @@
.global sbicall
sbicall:
.option norelax
mv t0, a0
mv t1, a1
mv a0, a2
@ -14,3 +15,5 @@ sbicall:
mv a6, t1
ecall
ret
.section .note.GNU-stack,"",%progbits

View File

@ -17,66 +17,9 @@
#include <sys/sbi.h>
#endif
struct madt {
struct sdt header;
uint32_t local_controller_addr;
uint32_t flags;
char madt_entries_begin[];
} __attribute__((packed));
struct madt_header {
uint8_t type;
uint8_t length;
} __attribute__((packed));
struct madt_lapic {
struct madt_header header;
uint8_t acpi_processor_uid;
uint8_t lapic_id;
uint32_t flags;
} __attribute__((packed));
struct madt_x2apic {
struct madt_header header;
uint8_t reserved[2];
uint32_t x2apic_id;
uint32_t flags;
uint32_t acpi_processor_uid;
} __attribute__((packed));
extern symbol smp_trampoline_start;
extern size_t smp_trampoline_size;
struct madt_gicc {
struct madt_header header;
uint8_t reserved1[2];
uint32_t iface_no;
uint32_t acpi_uid;
uint32_t flags;
uint32_t parking_ver;
uint32_t perf_gsiv;
uint64_t parking_addr;
uint64_t gicc_base_addr;
uint64_t gicv_base_addr;
uint64_t gich_base_addr;
uint32_t vgic_maint_gsiv;
uint64_t gicr_base_addr;
uint64_t mpidr;
uint8_t power_eff_class;
uint8_t reserved2;
uint16_t spe_overflow_gsiv;
} __attribute__((packed));
// Reference: https://github.com/riscv-non-isa/riscv-acpi/issues/15
struct madt_riscv_intc {
struct madt_header header;
uint8_t version;
uint8_t reserved;
uint32_t flags;
uint64_t hartid;
uint32_t acpi_processor_uid;
} __attribute__((packed));
#if defined (__x86_64__) || defined (__i386__)
struct trampoline_passed_info {
@ -90,7 +33,7 @@ struct trampoline_passed_info {
static bool smp_start_ap(uint32_t lapic_id, struct gdtr *gdtr,
struct limine_smp_info *info_struct,
bool longmode, int paging_mode, uint32_t pagemap,
int paging_mode, uint32_t pagemap,
bool x2apic, bool nx, uint64_t hhdm, bool wp) {
// Prepare the trampoline
static void *trampoline = NULL;
@ -110,10 +53,9 @@ static bool smp_start_ap(uint32_t lapic_id, struct gdtr *gdtr,
passed_info->smp_tpl_booted_flag = 0;
passed_info->smp_tpl_pagemap = pagemap;
passed_info->smp_tpl_target_mode = ((uint32_t)x2apic << 2)
| ((uint32_t)paging_mode << 1)
| ((uint32_t)(paging_mode == PAGING_MODE_X86_64_5LVL) << 1)
| ((uint32_t)nx << 3)
| ((uint32_t)wp << 4)
| ((uint32_t)longmode << 0);
| ((uint32_t)wp << 4);
passed_info->smp_tpl_gdt = *gdtr;
passed_info->smp_tpl_hhdm = hhdm;
@ -149,7 +91,6 @@ static bool smp_start_ap(uint32_t lapic_id, struct gdtr *gdtr,
struct limine_smp_info *init_smp(size_t *cpu_count,
uint32_t *_bsp_lapic_id,
bool longmode,
int paging_mode,
pagemap_t pagemap,
bool x2apic,
@ -257,7 +198,7 @@ struct limine_smp_info *init_smp(size_t *cpu_count,
// Try to start the AP
if (!smp_start_ap(lapic->lapic_id, &gdtr, info_struct,
longmode, paging_mode, (uintptr_t)pagemap.top_level,
paging_mode, (uintptr_t)pagemap.top_level,
x2apic, nx, hhdm, wp)) {
print("smp: FAILED to bring-up AP\n");
continue;
@ -294,7 +235,7 @@ struct limine_smp_info *init_smp(size_t *cpu_count,
// Try to start the AP
if (!smp_start_ap(x2lapic->x2apic_id, &gdtr, info_struct,
longmode, paging_mode, (uintptr_t)pagemap.top_level,
paging_mode, (uintptr_t)pagemap.top_level,
true, nx, hhdm, wp)) {
print("smp: FAILED to bring-up AP\n");
continue;
@ -366,7 +307,7 @@ static bool try_start_ap(int boot_method, uint64_t method_ptr,
// Additionally, the newly-booted AP may have caches disabled which implies
// it possibly does not see our cache contents either.
clean_inval_dcache_poc((uintptr_t)trampoline, (uintptr_t)trampoline + 0x1000);
clean_dcache_poc((uintptr_t)trampoline, (uintptr_t)trampoline + 0x1000);
inval_icache_pou((uintptr_t)trampoline, (uintptr_t)trampoline + 0x1000);
asm volatile ("" ::: "memory");
@ -374,7 +315,7 @@ static bool try_start_ap(int boot_method, uint64_t method_ptr,
switch (boot_method) {
case BOOT_WITH_SPIN_TBL:
*(volatile uint64_t *)method_ptr = (uint64_t)(uintptr_t)trampoline;
clean_inval_dcache_poc(method_ptr, method_ptr + 8);
clean_dcache_poc(method_ptr, method_ptr + 8);
asm ("sev");
break;
@ -598,68 +539,40 @@ static bool smp_start_ap(size_t hartid, size_t satp, struct limine_smp_info *inf
return false;
}
struct limine_smp_info *init_smp(size_t *cpu_count,
size_t bsp_hartid,
pagemap_t pagemap) {
// No RSDP means no ACPI.
// Parsing the Device Tree is the only other method for detecting APs.
if (acpi_get_rsdp() == NULL) {
printv("smp: ACPI is required to detect APs.\n");
return NULL;
}
struct madt *madt = acpi_get_table("APIC", 0);
if (madt == NULL)
return NULL;
size_t max_cpus = 0;
for (uint8_t *madt_ptr = (uint8_t *)madt->madt_entries_begin;
(uintptr_t)madt_ptr < (uintptr_t)madt + madt->header.length;
madt_ptr += *(madt_ptr + 1)) {
switch (*madt_ptr) {
case 0x18: {
struct madt_riscv_intc *intc = (void *)madt_ptr;
// Check if we can actually try to start the AP
if ((intc->flags & 1) ^ ((intc->flags >> 1) & 1))
max_cpus++;
continue;
struct limine_smp_info *init_smp(size_t *cpu_count, pagemap_t pagemap) {
size_t num_cpus = 0;
for (struct riscv_hart *hart = hart_list; hart != NULL; hart = hart->next) {
if (!(hart->flags & RISCV_HART_COPROC)) {
num_cpus += 1;
}
}
struct limine_smp_info *ret = ext_mem_alloc(num_cpus * sizeof(struct limine_smp_info));
if (ret == NULL) {
panic(false, "out of memory");
}
struct limine_smp_info *ret = ext_mem_alloc(max_cpus * sizeof(struct limine_smp_info));
*cpu_count = 0;
// Try to start all APs
for (uint8_t *madt_ptr = (uint8_t *)madt->madt_entries_begin;
(uintptr_t)madt_ptr < (uintptr_t)madt + madt->header.length;
madt_ptr += *(madt_ptr + 1)) {
switch (*madt_ptr) {
case 0x18: {
struct madt_riscv_intc *intc = (void *)madt_ptr;
// Check if we can actually try to start the AP
if (!((intc->flags & 1) ^ ((intc->flags >> 1) & 1)))
for (struct riscv_hart *hart = hart_list; hart != NULL; hart = hart->next) {
if (hart->flags & RISCV_HART_COPROC) {
continue;
}
struct limine_smp_info *info_struct = &ret[*cpu_count];
info_struct->processor_id = intc->acpi_processor_uid;
info_struct->hartid = intc->hartid;
info_struct->hartid = hart->hartid;
info_struct->processor_id = hart->acpi_uid;
// Do not try to restart the BSP
if (intc->hartid == bsp_hartid) {
(*cpu_count)++;
// Don't try to start the BSP.
if (hart->hartid == bsp_hartid) {
*cpu_count += 1;
continue;
}
printv("smp: Found candidate AP for bring-up. Hart ID: %u\n", intc->hartid);
printv("smp: Found candidate AP for bring-up. Hart ID: %u\n", hart->hartid);
// Try to start the AP.
size_t satp = make_satp(pagemap.paging_mode, pagemap.top_level);
if (!smp_start_ap(intc->hartid, satp, info_struct)) {
if (!smp_start_ap(hart->hartid, satp, info_struct)) {
print("smp: FAILED to bring-up AP\n");
continue;
}
@ -667,8 +580,6 @@ struct limine_smp_info *init_smp(size_t *cpu_count,
(*cpu_count)++;
continue;
}
}
}
return ret;
}

View File

@ -12,7 +12,6 @@
struct limine_smp_info *init_smp(size_t *cpu_count,
uint32_t *_bsp_lapic_id,
bool longmode,
int paging_mode,
pagemap_t pagemap,
bool x2apic,
@ -32,7 +31,6 @@ struct limine_smp_info *init_smp(size_t *cpu_count,
#elif defined (__riscv64)
struct limine_smp_info *init_smp(size_t *cpu_count,
uint64_t bsp_hartid,
pagemap_t pagemap);
#else

View File

@ -101,3 +101,5 @@ smp_trampoline_end:
.global smp_trampoline_size
smp_trampoline_size:
.quad smp_trampoline_end - smp_trampoline_start
.section .note.GNU-stack,"",%progbits

View File

@ -2,6 +2,7 @@
.global smp_trampoline_start
smp_trampoline_start:
.option norelax
// The AP begins executing here with the following state:
// satp = 0
// sstatus.SIE = 0
@ -53,7 +54,7 @@ smp_trampoline_start:
csrw stvec, zero
// Wait for kernel to tell us where to go.
0: .insn i 0x0F, 0, x0, x0, 0x010 // pause
0: .4byte 0x0100000f // pause
ld t0, 24(a0)
fence r, rw
beqz t0, 0b
@ -62,3 +63,5 @@ smp_trampoline_start:
ld sp, 16(a0)
jr t0
.section .note.GNU-stack,"",%progbits

View File

@ -39,6 +39,11 @@ smp_trampoline_start:
xor eax, eax
mov cr4, eax
mov ecx, 0x277
mov eax, 0x00070406
mov edx, 0x00000105
wrmsr
test dword [ebx + (passed_info.target_mode - smp_trampoline_start)], (1 << 2)
jz .nox2apic
@ -51,9 +56,6 @@ smp_trampoline_start:
.nox2apic:
lea esp, [ebx + (temp_stack.top - smp_trampoline_start)]
test dword [ebx + (passed_info.target_mode - smp_trampoline_start)], (1 << 0)
jz parking32
mov eax, cr4
bts eax, 5
mov cr4, eax
@ -118,34 +120,6 @@ smp_trampoline_start:
jmp rax
bits 32
parking32:
mov edi, dword [ebx + (passed_info.smp_info_struct - smp_trampoline_start)]
mov eax, 1
lock xchg dword [ebx + (passed_info.booted_flag - smp_trampoline_start)], eax
xor eax, eax
.loop:
lock xadd dword [edi + 16], eax
test eax, eax
jnz .out
pause
jmp .loop
.out:
mov esp, dword [edi + 8]
push 0
push edi
push eax
xor eax, eax
xor ebx, ebx
xor ecx, ecx
xor edx, edx
xor esi, esi
xor edi, edi
xor ebp, ebp
ret
bits 64
parking64:
mov ebx, ebx
@ -206,3 +180,5 @@ smp_trampoline_end:
global smp_trampoline_size
smp_trampoline_size dq smp_trampoline_end - smp_trampoline_start
section .note.GNU-stack noalloc noexec nowrite progbits

View File

@ -25,9 +25,6 @@ AC_LANG([C])
AC_PROG_CC
PROG_ABSPATH([CC])
AC_CHECK_HEADERS([stdint.h stddef.h stdbool.h limits.h inttypes.h stdio.h stdlib.h string.h],
[], [AC_MSG_ERROR([required header not found])])
werror_state="no"
AC_ARG_ENABLE([werror],
[AS_HELP_STRING([--enable-werror], [treat warnings as errors])],
@ -54,14 +51,68 @@ if ! test "x$FIND_FOUND" = "xyes"; then
AC_MSG_ERROR([find not found, please install find before configuring])
fi
NATIVE_STRIP="$($CC -dumpmachine)"-strip
AC_CHECK_PROG([NATIVE_STRIP_FOUND], [$NATIVE_STRIP], [yes])
if ! test "x$NATIVE_STRIP_FOUND" = "xyes"; then
NATIVE_STRIP=strip
fi
AC_SUBST([NATIVE_STRIP])
AC_ARG_VAR([STRIP], [strip command])
rm -rf "$BUILDDIR/toolchain-files"
if ! test -z "$STRIP"; then
AC_CHECK_PROG([STRIP_USER_FOUND], [$STRIP], [yes])
if ! test "x$STRIP_USER_FOUND" = "xyes"; then
AC_MSG_ERROR([$STRIP not found, please install $STRIP before configuring])
fi
else
STRIP="$($CC -dumpmachine)"-strip
AC_CHECK_PROG([STRIP_FOUND], [$STRIP], [yes])
if ! test "x$STRIP_FOUND" = "xyes"; then
STRIP=strip
AC_CHECK_PROG([STRIP_DEFAULT_FOUND], [$STRIP], [yes])
if ! test "x$STRIP_DEFAULT_FOUND" = "xyes"; then
AC_MSG_ERROR([$STRIP not found, please install $STRIP before configuring])
fi
fi
fi
AC_SUBST([STRIP])
PKGCONF_LIBS_LIST=""
PKG_PROG_PKG_CONFIG
for lib in $PKGCONF_LIBS_LIST; do
set -e
$PKG_CONFIG --exists --print-errors "$lib"
set +e
done
PKGCONF_CFLAGS="$($PKG_CONFIG --cflags-only-other $PKGCONF_LIBS_LIST 2>/dev/null)"
PKGCONF_CPPFLAGS="$($PKG_CONFIG --cflags-only-I $PKGCONF_LIBS_LIST 2>/dev/null)"
PKGCONF_LIBS="$($PKG_CONFIG --libs $PKGCONF_LIBS_LIST 2>/dev/null)"
AC_SUBST([PKGCONF_CFLAGS])
AC_SUBST([PKGCONF_CPPFLAGS])
AC_SUBST([PKGCONF_LIBS])
OLD_CFLAGS="$CFLAGS"
OLD_CPPFLAGS="$CPPFLAGS"
OLD_LIBS="$LIBS"
CFLAGS="$CFLAGS $PKGCONF_CFLAGS"
CPPFLAGS="$PKGCONF_CPPFLAGS $CPPFLAGS"
LIBS="$LIBS $PKGCONF_LIBS"
AC_CHECK_HEADERS([stdint.h stddef.h stdbool.h limits.h inttypes.h stdio.h stdlib.h string.h],
[], [AC_MSG_ERROR([required header not found])])
CFLAGS="$OLD_CFLAGS"
CPPFLAGS="$OLD_CPPFLAGS"
LIBS="$OLD_LIBS"
AC_ARG_VAR([TOOLCHAIN_FOR_TARGET], [alternative toolchain prefix for Limine (or 'llvm', or 'gnu')])
AC_ARG_VAR([CC_FOR_TARGET], [C compiler command for Limine])
AC_ARG_VAR([LD_FOR_TARGET], [linker command for Limine])
AC_ARG_VAR([OBJCOPY_FOR_TARGET], [objcopy command for Limine])
AC_ARG_VAR([OBJDUMP_FOR_TARGET], [objdump command for Limine])
AC_ARG_VAR([READELF_FOR_TARGET], [readelf command for Limine])
rm -rf toolchain-files
BUILD_ALL="no"
@ -103,7 +154,7 @@ fi
if test "x$BUILD_BIOS" = "xno"; then
BUILD_BIOS=""
else
$MKDIR_P "$BUILDDIR/toolchain-files"
$MKDIR_P toolchain-files
CC="$CC" \
ARCHITECTURE=i686 \
FREESTANDING_TOOLCHAIN_SUFFIX="_FOR_TARGET" \
@ -118,7 +169,7 @@ else
FREESTANDING_OBJDUMP="$OBJDUMP_FOR_TARGET" \
WANT_FREESTANDING_READELF=yes \
FREESTANDING_READELF="$READELF_FOR_TARGET" \
"$SRCDIR/freestanding-toolchain" >"$BUILDDIR/toolchain-files/bios-i686-toolchain.mk" || exit 1
"$SRCDIR/freestanding-toolchain" >"toolchain-files/bios-i686-toolchain.mk" || exit 1
BUILD_BIOS="limine-bios"
NEED_NASM=yes
NEED_GZIP=yes
@ -135,7 +186,7 @@ AC_ARG_ENABLE([uefi-ia32],
if test "x$BUILD_UEFI_IA32" = "xno"; then
BUILD_UEFI_IA32=""
else
$MKDIR_P "$BUILDDIR/toolchain-files"
$MKDIR_P toolchain-files
CC="$CC" \
ARCHITECTURE=i686 \
FREESTANDING_TOOLCHAIN_SUFFIX="_FOR_TARGET" \
@ -148,7 +199,7 @@ else
FREESTANDING_OBJCOPY="$OBJCOPY_FOR_TARGET" \
WANT_FREESTANDING_OBJDUMP=yes \
FREESTANDING_OBJDUMP="$OBJDUMP_FOR_TARGET" \
"$SRCDIR/freestanding-toolchain" >"$BUILDDIR/toolchain-files/uefi-i686-toolchain.mk" || exit 1
"$SRCDIR/freestanding-toolchain" >"toolchain-files/uefi-i686-toolchain.mk" || exit 1
BUILD_UEFI_IA32="limine-uefi-ia32"
NEED_NASM=yes
fi
@ -164,7 +215,7 @@ AC_ARG_ENABLE([uefi-x86-64],
if test "x$BUILD_UEFI_X86_64" = "xno"; then
BUILD_UEFI_X86_64=""
else
$MKDIR_P "$BUILDDIR/toolchain-files"
$MKDIR_P toolchain-files
CC="$CC" \
ARCHITECTURE=x86_64 \
FREESTANDING_TOOLCHAIN_SUFFIX="_FOR_TARGET" \
@ -177,7 +228,7 @@ else
FREESTANDING_OBJCOPY="$OBJCOPY_FOR_TARGET" \
WANT_FREESTANDING_OBJDUMP=yes \
FREESTANDING_OBJDUMP="$OBJDUMP_FOR_TARGET" \
"$SRCDIR/freestanding-toolchain" >"$BUILDDIR/toolchain-files/uefi-x86_64-toolchain.mk" || exit 1
"$SRCDIR/freestanding-toolchain" >"toolchain-files/uefi-x86_64-toolchain.mk" || exit 1
BUILD_UEFI_X86_64="limine-uefi-x86-64"
NEED_NASM=yes
fi
@ -193,7 +244,7 @@ AC_ARG_ENABLE([uefi-aarch64],
if test "x$BUILD_UEFI_AARCH64" = "xno"; then
BUILD_UEFI_AARCH64=""
else
mkdir -p "$BUILDDIR/toolchain-files"
mkdir -p toolchain-files
CC="$CC" \
ARCHITECTURE=aarch64 \
FREESTANDING_TOOLCHAIN_SUFFIX="_FOR_TARGET" \
@ -206,7 +257,7 @@ else
FREESTANDING_OBJCOPY="$OBJCOPY_FOR_TARGET" \
WANT_FREESTANDING_OBJDUMP=yes \
FREESTANDING_OBJDUMP="$OBJDUMP_FOR_TARGET" \
"$SRCDIR/freestanding-toolchain" >"$BUILDDIR/toolchain-files/uefi-aarch64-toolchain.mk" || exit 1
"$SRCDIR/freestanding-toolchain" >"toolchain-files/uefi-aarch64-toolchain.mk" || exit 1
BUILD_UEFI_AARCH64="limine-uefi-aarch64"
fi
@ -221,7 +272,7 @@ AC_ARG_ENABLE([uefi-riscv64],
if test "x$BUILD_UEFI_RISCV64" = "xno"; then
BUILD_UEFI_RISCV64=""
else
mkdir -p "$BUILDDIR/toolchain-files"
mkdir -p toolchain-files
CC="$CC" \
ARCHITECTURE=riscv64 \
FREESTANDING_TOOLCHAIN_SUFFIX="_FOR_TARGET" \
@ -234,7 +285,7 @@ else
FREESTANDING_OBJCOPY="$OBJCOPY_FOR_TARGET" \
WANT_FREESTANDING_OBJDUMP=yes \
FREESTANDING_OBJDUMP="$OBJDUMP_FOR_TARGET" \
"$SRCDIR/freestanding-toolchain" >"$BUILDDIR/toolchain-files/uefi-riscv64-toolchain.mk" || exit 1
"$SRCDIR/freestanding-toolchain" >"toolchain-files/uefi-riscv64-toolchain.mk" || exit 1
BUILD_UEFI_RISCV64="limine-uefi-riscv64"
fi
@ -273,13 +324,6 @@ if test "x$NEED_GZIP" = "xyes"; then
fi
fi
AC_ARG_VAR([TOOLCHAIN_FOR_TARGET], [alternative toolchain prefix for Limine (or 'llvm', or 'gnu')])
AC_ARG_VAR([CC_FOR_TARGET], [C compiler command for Limine])
AC_ARG_VAR([LD_FOR_TARGET], [linker command for Limine])
AC_ARG_VAR([OBJCOPY_FOR_TARGET], [objcopy command for Limine])
AC_ARG_VAR([OBJDUMP_FOR_TARGET], [objdump command for Limine])
AC_ARG_VAR([READELF_FOR_TARGET], [readelf command for Limine])
m4_define([DEFAULT_CFLAGS_FOR_TARGET], [-g -O2 -pipe])
AC_ARG_VAR([CFLAGS_FOR_TARGET], [C flags for Limine @<:@default: ]DEFAULT_CFLAGS_FOR_TARGET[@:>@])
test "x$CFLAGS_FOR_TARGET" = "x" && CFLAGS_FOR_TARGET="DEFAULT_CFLAGS_FOR_TARGET"
@ -289,16 +333,16 @@ AC_ARG_VAR([CPPFLAGS_FOR_TARGET], [C preprocessor flags for Limine @<:@default:
test "x$CPPFLAGS_FOR_TARGET" = "x" && CPPFLAGS_FOR_TARGET="DEFAULT_CPPFLAGS_FOR_TARGET"
m4_define([DEFAULT_LDFLAGS_FOR_TARGET], [])
AC_ARG_VAR([LDFLAGS_FOR_TARGET], [Linker flags for Limine @<:@default: ]DEFAULT_LDFLAGS_FOR_TARGET[@:>@])
AC_ARG_VAR([LDFLAGS_FOR_TARGET], [linker flags for Limine @<:@default: ]DEFAULT_LDFLAGS_FOR_TARGET[@:>@])
test "x$LDFLAGS_FOR_TARGET" = "x" && LDFLAGS_FOR_TARGET="DEFAULT_LDFLAGS_FOR_TARGET"
LIMINE_COPYRIGHT=$($GREP Copyright "$SRCDIR/LICENSE")
LIMINE_COPYRIGHT=$($GREP Copyright "$SRCDIR/COPYING")
AC_SUBST([LIMINE_COPYRIGHT])
AC_PREFIX_DEFAULT([/usr/local])
if ! test "$SRCDIR" = "$BUILDDIR"; then
cp "$SRCDIR/limine.h" "$BUILDDIR/"
if ! test -f limine.h; then
cp "$SRCDIR/limine.h" ./
fi
AC_CONFIG_FILES([man/man1/limine.1 GNUmakefile config.h])

View File

@ -38,7 +38,6 @@ override CFLAGS_FOR_TARGET += \
-fno-PIC \
-m32 \
-march=i686 \
-mabi=sysv \
-mno-80387
override CPPFLAGS_FOR_TARGET := \

View File

@ -2,7 +2,7 @@ extern bss_begin
extern bss_end
extern entry
section .entry
section .entry progbits alloc exec nowrite align=16
global _start
_start:
@ -16,3 +16,5 @@ _start:
rep stosb
jmp entry
section .note.GNU-stack noalloc noexec nowrite progbits

View File

@ -5,6 +5,7 @@ ENTRY(_start)
PHDRS
{
text PT_LOAD FLAGS((1 << 0) | (1 << 2)) ;
rodata PT_LOAD FLAGS((1 << 2)) ;
data PT_LOAD FLAGS((1 << 1) | (1 << 2)) ;
}
@ -17,15 +18,18 @@ SECTIONS
*(.text .text.*)
} :text
.data : {
.rodata : {
*(.rodata .rodata.*)
} :rodata
.data : {
*(.data .data.*)
} :data
.bss : {
bss_begin = .;
*(COMMON)
*(.bss .bss.*)
*(COMMON)
bss_end = .;
} :data

View File

@ -73,3 +73,5 @@ memcmp:
pop edi
pop esi
ret
section .note.GNU-stack noalloc noexec nowrite progbits

View File

@ -1002,7 +1002,7 @@ uninstall_mode_cleanup:
static void enroll_config_usage(const char *name) {
printf("Usage: %s enroll-config <Limine executable> <BLAKE2B of config file>\n", name);
printf("\n");
printf(" --reset Remove enrolled BLAKE2B, will not check config intergrity\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");

View File

@ -330,7 +330,7 @@ struct limine_smp_info {
struct limine_smp_response {
uint64_t revision;
uint32_t flags;
uint64_t flags;
uint64_t bsp_mpidr;
uint64_t cpu_count;
LIMINE_PTR(struct limine_smp_info **) cpus;
@ -339,7 +339,7 @@ struct limine_smp_response {
#elif defined (__riscv) && (__riscv_xlen == 64)
struct limine_smp_info {
uint32_t processor_id;
uint64_t processor_id;
uint64_t hartid;
uint64_t reserved;
LIMINE_PTR(limine_goto_address) goto_address;
@ -348,7 +348,7 @@ struct limine_smp_info {
struct limine_smp_response {
uint64_t revision;
uint32_t flags;
uint64_t flags;
uint64_t bsp_hartid;
uint64_t cpu_count;
LIMINE_PTR(struct limine_smp_info **) cpus;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 150 KiB

After

Width:  |  Height:  |  Size: 501 KiB

View File

@ -7,7 +7,7 @@ gdt:
dw 0xffff ; Limit
dw 0x0000 ; Base (low 16 bits)
db 0x00 ; Base (mid 8 bits)
db 10011010b ; Access
db 10011011b ; Access
db 11001111b ; Granularity
db 0x00 ; Base (high 8 bits)
@ -15,7 +15,7 @@ gdt:
dw 0xffff ; Limit
dw 0x0000 ; Base (low 16 bits)
db 0x00 ; Base (mid 8 bits)
db 10010010b ; Access
db 10010011b ; Access
db 11001111b ; Granularity
db 0x00 ; Base (high 8 bits)

View File

@ -13,7 +13,7 @@ ovmf-aa64:
ovmf-rv64:
$(MKDIR_P) ovmf-rv64
cd ovmf-rv64 && curl -o OVMF.fd https://retrage.github.io/edk2-nightly/bin/RELEASERISCV64_VIRT.fd && dd if=/dev/zero of=OVMF.fd bs=1 count=0 seek=33554432
cd ovmf-rv64 && curl -o OVMF.fd https://retrage.github.io/edk2-nightly/bin/RELEASERISCV64_VIRT_CODE.fd && dd if=/dev/zero of=OVMF.fd bs=1 count=0 seek=33554432
ovmf-ia32:
$(MKDIR_P) ovmf-ia32
@ -262,7 +262,7 @@ uefi-rv64-test:
sudo umount test_image/
sudo losetup -d `cat loopback_dev`
rm -rf test_image loopback_dev
qemu-system-riscv64 -m 512M -M virt -cpu rv64 -drive if=pflash,unit=1,format=raw,file=ovmf-rv64/OVMF.fd -net none -smp 4 -device ramfb -device qemu-xhci -device usb-kbd -device virtio-blk-device,drive=hd0 -drive id=hd0,format=raw,file=test.hdd -serial stdio
qemu-system-riscv64 -m 512M -M virt -cpu rv64 -drive if=pflash,unit=0,format=raw,file=ovmf-rv64/OVMF.fd -net none -smp 4 -device ramfb -device qemu-xhci -device usb-kbd -device virtio-blk-device,drive=hd0 -drive id=hd0,format=raw,file=test.hdd -serial stdio
.PHONY: uefi-ia32-test
uefi-ia32-test:

2
test/.gitignore vendored
View File

@ -1,2 +1,4 @@
test.o
test.elf
flanterm
limine.h

View File

@ -6,13 +6,26 @@ export OBJCOPY_FOR_TARGET
export READELF_FOR_TARGET
override CC := $(CC_FOR_TARGET)
CFLAGS = -O2 -g -Wall -Wextra
CFLAGS = -O2 -g -Wall -Wextra -DFLANTERM_FB_SUPPORT_BPP
LDFLAGS =
override LD := $(LD_FOR_TARGET)
override QEMU := qemu-system-x86_64
QEMUFLAGS = -m 1G -enable-kvm -cpu host
override INTERNALLDFLAGS := \
ifneq ($(findstring x86_64,$(shell $(CC_FOR_TARGET) -dumpmachine)),)
override LDFLAGS += \
-m elf_x86_64
endif
ifneq ($(findstring aarch64,$(shell $(CC_FOR_TARGET) -dumpmachine)),)
override LDFLAGS += \
-m aarch64elf
endif
ifneq ($(findstring riscv64,$(shell $(CC_FOR_TARGET) -dumpmachine)),)
override LDFLAGS += \
-m elf64lriscv
endif
override LDFLAGS += \
-Tlinker.ld \
-nostdlib \
-zmax-page-size=0x1000 \
@ -21,34 +34,57 @@ override INTERNALLDFLAGS := \
--no-dynamic-linker \
-ztext
override INTERNAL_LD_FLAGS_MULTIBOOT2 := \
override LDFLAGS_MB2 := \
-m elf_i386 \
-Tmultiboot2.ld \
-nostdlib \
-zmax-page-size=0x1000 \
-static
override INTERNAL_LD_FLAGS_MULTIBOOT1 := \
override LDFLAGS_MB1 := \
-m elf_i386 \
-Tmultiboot.ld \
-nostdlib \
-zmax-page-size=0x1000 \
-static
override INTERNALCFLAGS := \
override CFLAGS += \
-std=c11 \
-nostdinc \
-ffreestanding \
-fno-stack-protector \
-fno-stack-check \
-fno-lto \
-fPIE \
-mgeneral-regs-only \
-mno-red-zone \
-I../freestanding-headers \
-I. \
-I..
-D_LIMINE_PROTO
override INTERNALCFLAGS_MB := \
ifneq ($(findstring x86_64,$(shell $(CC_FOR_TARGET) -dumpmachine)),)
override CFLAGS += \
-m64 \
-march=x86-64 \
-mgeneral-regs-only \
-mno-red-zone
endif
ifneq ($(findstring aarch64,$(shell $(CC_FOR_TARGET) -dumpmachine)),)
override CFLAGS += \
-mgeneral-regs-only
endif
ifneq ($(findstring riscv64,$(shell $(CC_FOR_TARGET) -dumpmachine)),)
override CFLAGS += \
-march=rv64imac \
-mabi=lp64 \
-mno-relax
override LDFLAGS += \
--no-relax
endif
override CFLAGS_MB := \
-std=c11 \
-nostdinc \
-ffreestanding \
-fno-stack-protector \
-fno-stack-check \
@ -57,33 +93,41 @@ override INTERNALCFLAGS_MB := \
-fno-PIC \
-m32 \
-march=i686 \
-mabi=sysv \
-mno-80387 \
-mgeneral-regs-only \
-I../freestanding-headers \
-I. \
-I.. \
-I../common/protos
ifneq ($(findstring 86,$(CC_FOR_TARGET)),)
ifneq ($(findstring 86,$(shell $(CC_FOR_TARGET) -dumpmachine)),)
all: test.elf multiboot2.elf multiboot.elf
else
all: test.elf
endif
test.elf: limine.o e9print.o memory.o
$(LD) $^ $(LDFLAGS) $(INTERNALLDFLAGS) -o $@
flanterm:
mkdir -p flanterm
cp -rv ../common/flanterm/* ./flanterm/
limine.h:
cp -v ../limine.h ./
test.elf: limine.o e9print.o memory.o flanterm/flanterm.o flanterm/backends/fb.o
$(LD) $^ $(LDFLAGS) -o $@
multiboot2.elf: multiboot2_trampoline.o
$(CC) $(CFLAGS) $(INTERNALCFLAGS_MB) -c multiboot2.c -o multiboot2.o
$(CC) $(CFLAGS) $(INTERNALCFLAGS_MB) -c e9print.c -o e9print.o
$(LD) $^ multiboot2.o e9print.o $(LDFLAGS) $(INTERNAL_LD_FLAGS_MULTIBOOT2) -m elf_i386 -o $@
$(CC) $(CFLAGS_MB) -c memory.c -o memory.o
$(CC) $(CFLAGS_MB) -c multiboot2.c -o multiboot2.o
$(CC) $(CFLAGS_MB) -c e9print.c -o e9print.o
$(LD) $^ memory.o multiboot2.o e9print.o $(LDFLAGS_MB2) -o $@
multiboot.elf: multiboot_trampoline.o
$(CC) $(CFLAGS) $(INTERNALCFLAGS_MB) -c multiboot.c -o multiboot.o
$(CC) $(CFLAGS) $(INTERNALCFLAGS_MB) -c e9print.c -o e9print.o
$(LD) $^ multiboot.o e9print.o $(LDFLAGS) $(INTERNAL_LD_FLAGS_MULTIBOOT1) -m elf_i386 -o $@
$(CC) $(CFLAGS_MB) -c memory.c -o memory.o
$(CC) $(CFLAGS_MB) -c multiboot.c -o multiboot.o
$(CC) $(CFLAGS_MB) -c e9print.c -o e9print.o
$(LD) $^ memory.o multiboot.o e9print.o $(LDFLAGS_MB1) -o $@
%.o: %.c
$(CC) $(CFLAGS) $(INTERNALCFLAGS) -c $< -o $@
%.o: %.c flanterm limine.h
$(CC) $(CFLAGS) -c $< -o $@
%.o: %.asm
nasm -felf32 -F dwarf -g $< -o $@
@ -92,3 +136,4 @@ clean:
rm -rf test.elf limine.o e9print.o memory.o
rm -rf multiboot2.o multiboot2.elf multiboot2_trampoline.o
rm -rf multiboot.o multiboot_trampoline.o multiboot.elf
rm -rf flanterm limine.h

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 76 KiB

View File

@ -2,12 +2,22 @@
#include <stddef.h>
#include <stdint.h>
#if defined (_LIMINE_PROTO)
#include <flanterm/flanterm.h>
extern struct flanterm_context *ft_ctx;
#endif
static const char CONVERSION_TABLE[] = "0123456789abcdef";
void e9_putc(char c) {
#if defined (__x86_64__) || defined (__i386__)
__asm__ __volatile__ ("outb %0, %1" :: "a" (c), "Nd" (0xe9) : "memory");
#endif
#if defined (_LIMINE_PROTO)
if (ft_ctx != NULL) {
flanterm_write(ft_ctx, &c, 1);
}
#endif
}
void e9_print(const char *msg) {

View File

@ -2,6 +2,8 @@
#include <stddef.h>
#include <limine.h>
#include <e9print.h>
#include <flanterm/flanterm.h>
#include <flanterm/backends/fb.h>
static void limine_main(void);
@ -232,9 +234,26 @@ void ap_entry(struct limine_smp_info *info) {
extern char kernel_start[];
void limine_main(void) {
struct flanterm_context *ft_ctx = NULL;
static void limine_main(void) {
e9_printf("\nWe're alive");
struct limine_framebuffer *fb = framebuffer_request.response->framebuffers[0];
ft_ctx = flanterm_fb_simple_init(
fb->address,
fb->width,
fb->height,
fb->pitch,
fb->red_mask_size,
fb->red_mask_shift,
fb->green_mask_size,
fb->green_mask_shift,
fb->blue_mask_size,
fb->blue_mask_shift
);
uint64_t kernel_slide = (uint64_t)kernel_start - 0xffffffff80000000;
e9_printf("Kernel slide: %x", kernel_slide);

View File

@ -1,5 +1,3 @@
ENTRY(limine_main)
PHDRS
{
text PT_LOAD FLAGS((1 << 0) | (1 << 2)) ; /* Execute + Read */
@ -32,7 +30,6 @@ SECTIONS
.data : {
*(.data .data.*)
__global_pointer$ = . + 0x800;
*(.sdata .sdata.*)
} :data
@ -41,8 +38,8 @@ SECTIONS
} :data :dynamic
.bss : {
*(COMMON)
*(.sbss .sbss.*)
*(.bss .bss.*)
*(COMMON)
} :data
}