Compare commits

...

367 Commits

Author SHA1 Message Date
mintsuki 1ea5b71e49 docs: Update example Limine version in README to 4.20231024.eol 2023-10-24 18:47:43 +02:00
mintsuki aceac9c86e pmm: Add MEMMAP_MAX macro and use it instead of hardcoding 256 2023-10-24 18:34:12 +02:00
mintsuki cadeabc70b lib/time: EFI: Return time of 0 if GetTime() unsupported 2023-10-24 18:34:12 +02:00
48cf 9bcea9911c lib/gterm: Try to initialize all 32-bpp framebuffers 2023-10-24 18:33:44 +02:00
48cf 3f040cf1a9 pmm: Ignore allow_high_allocs on non x86-64 architectures 2023-10-24 18:32:37 +02:00
mintsuki 82f0edcd1f build: Backport misc autoconf/pkgconf improvements 2023-10-24 01:16:12 +02:00
mintsuki de7dff1d4f limine/ioapic: Change spec to avoid masking IOAPIC RTEs unless Fixed or Lowest Priority 2023-10-24 01:16:12 +02:00
mintsuki 3e77a04d2f build: Misc minor QOL configure.ac/GNUmakefile.in improvements 2023-10-24 01:16:12 +02:00
mintsuki 8d2b8bd51f docs: Update example Limine version in README to 4.20231006.0 2023-10-06 12:21:29 -05:00
mintsuki 6529246e84 misc: Remove unnecessary ifdefs added in previous commits 2023-10-06 12:19:45 -05:00
mintsuki b2becebbf9 misc: Only allocate memory and modules above 4GiB on 64-bit platforms 2023-10-06 12:19:45 -05:00
mintsuki b2da2d701e pmm: Allow allocations above 4GiB and use them in freadall() 2023-10-06 12:19:45 -05:00
mintsuki b1a9ce534e docs: Update example Limine version in README to 4.20230928.2 2023-09-28 17:47:31 -05:00
mintsuki d012aacfbc build: Fix makefile target dependencies bug introduced in a0c2f95 2023-09-28 17:47:14 -05:00
mintsuki f4297a30b5 docs: Update example Limine version in README to 4.20230928.1 2023-09-28 16:23:55 -05:00
mintsuki 7336d25d48 build: Fix bug introduced in 7885f260 due to a misunderstanding of an objcopy flag 2023-09-28 16:02:52 -05:00
mintsuki 0f3d857e14 docs: Update example Limine version in README to 4.20230928.0 2023-09-28 06:55:02 -05:00
mintsuki 58949b6acd build: Fix indentation issue in common/GNUmakefile 2023-09-28 06:52:03 -05:00
mintsuki 3f750a77aa build: ldscripts: .reloc -> .dummy_reloc 2023-09-28 06:52:03 -05:00
mintsuki d7f172f9cb build: Fix race conditions introduced in 22d45a5428 2023-09-28 06:51:51 -05:00
mintsuki e8d5818061 misc: Add .note.GNU-stack where it was still missing 2023-09-28 06:50:30 -05:00
mintsuki e402dec88a misc: Add section .note.GNU-stack to assembly files 2023-09-28 06:49:54 -05:00
mintsuki 20774186bf time: Change signature of get_jdn() to use int types 2023-09-28 06:48:56 -05:00
mintsuki ef3766d4a9 docs: Update example Limine version in README to 4.20230924.0 2023-09-24 02:00:08 -05:00
mintsuki 9bf2543b25 elf: Panic if there are PHDRs with different perms sharing same page 2023-09-24 01:56:16 -05:00
mintsuki c9c5a1ad7d smp: Remove dead 32-bit trampoline code 2023-09-23 17:34:15 -05:00
mintsuki 794f207bd7 misc: Backport limine.h and PROTOCOL.md from 5.x 2023-09-22 17:17:39 -05:00
mintsuki fd73ea7cd0 menu: Fix padding issue introduced in e1d25f8 2023-09-22 16:38:44 -05:00
mintsuki e94d2b7993 docs: PROTOCOL.md: Backport caching section from trunk 2023-09-16 16:55:02 -05:00
mintsuki a6e115d486 misc: Backports from trunk 2023-09-16 16:53:40 -05:00
mintsuki 1b72dd32a0 misc: aarch64: Remove unused enter_in_current_el() function 2023-09-16 16:52:46 -05:00
mintsuki 068b06e7ac misc: Consistently call x86-64 such, instead of x86_64 2023-09-16 11:41:33 -05:00
mintsuki 829712b446 docs: PROTOCOL.md: Minor fixes 2023-09-16 11:40:29 -05:00
xvanc bb3d0b81c2 acpi: remove duplicate definition in sys/lapic.c 2023-09-16 11:39:58 -05:00
xvanc f7bee447a8 lib/libc: add misc utilities 2023-09-16 11:39:40 -05:00
xvanc 9249edf772 acpi: move acpi structure defs to lib/acpi.h 2023-09-16 11:39:11 -05:00
mintsuki bd67dfeee9 test: Use -dumpmachine to find architecture instead of expecting -target 2023-09-11 17:14:09 -05:00
mintsuki 0693d86cb0 misc/bios: Update and improve linker script and related files 2023-09-11 17:13:31 -05:00
mintsuki 7d527d867c protos/chainload: Fix bug that could result in bogus oom errors. Fixes #302 2023-09-11 17:13:31 -05:00
mintsuki bddd30a667 decompressor: Mark .entry section with proper flags in entry.asm 2023-09-11 17:13:31 -05:00
mintsuki ce91f10998 decompressor: Add rodata PHDR and section to ld script 2023-09-11 17:13:31 -05:00
Kacper Słomiński e53acb997a protos: chainload: Allocate memory for the null terminator in cmdline 2023-09-11 17:13:31 -05:00
mintsuki 7305724b95 misc: Misc EFI linker script improvements and drop .sbat 2023-09-11 17:13:31 -05:00
mintsuki 093899d863 docs: Update example Limine version in README to 4.20230909.0 2023-09-09 16:03:28 -05:00
mintsuki f5e43d2e9b misc: Improve UEFI linker scripts 2023-09-09 15:54:49 -05:00
mintsuki e7311fc8a0 docs: README.md: Fix minor grammar mistake 2023-09-09 10:08:00 -05:00
mintsuki 8154512255 stage1/gdt: Mark accessed flag in descriptors 2023-09-09 10:08:00 -05:00
mintsuki 0fea596ed7 docs: Remove references to shim as we don't directly support it 2023-09-09 10:08:00 -05:00
mintsuki 559bb10fa9 x86/gdt: Mark accessed flag in descriptors 2023-09-09 10:08:00 -05:00
mintsuki 4dfea16330 docs: Update example Limine version in README to 4.20230830.0 2023-08-29 22:19:45 -05:00
mintsuki b97fd36385 build: Drop -mabi=sysv for x86 for clang 16 2023-08-29 22:18:47 -05:00
mintsuki 4a46597fcc config: Disable editor by default if config b2sum present. Fixes #296 2023-08-29 22:18:32 -05:00
mintsuki 3f0591ee8c menu: Change menu arrow to use unicode big arrow 2023-08-29 22:18:22 -05:00
mintsuki 88bdc3b074 gterm: Update font's big left and right arrows 2023-08-29 22:18:07 -05:00
mintsuki bf0adea50e docs: Update example Limine version in README to 4.20230819.0 2023-08-19 08:48:50 -05:00
mintsuki 10a7d39c66 disk: BIOS: Skip drive if sector size is 0. Fixes #294 2023-08-19 08:11:51 -05:00
Kacper Słomiński 6ab35406d3 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:34:18 -05:00
Kacper Słomiński f694d37027 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:33:58 -05:00
mintsuki f784baf397 elf: elf64_load_section(): Return false early if sh_num == 0 2023-08-18 13:33:40 -05:00
mintsuki 57c6490a32 disk: Add additional volume_index_i overflow guards 2023-08-18 13:33:23 -05:00
mintsuki 4d489c3388 exceptions: Change naming of exceptions in panic message 2023-08-18 13:33:10 -05:00
mintsuki b27c560369 docs: Update example Limine version in README to 4.20230811.0 2023-08-11 10:32:09 -05:00
mintsuki 0baf774eef limine: Do not return SMBIOS response if not present 2023-08-11 10:24:36 -05:00
mintsuki 49b27fc47b test: General makefile updates 2023-08-11 10:21:27 -05:00
mekb 2831ef370c menu: Add option to hide help text 2023-08-11 10:09:33 -05:00
mintsuki de98e55e06 docs: Update example Limine version in README to 4.20230729.0 2023-07-29 11:58:54 -05:00
mintsuki 6fd0d1b42a misc: Update test wallpaper and screenshot 2023-07-29 11:56:59 -05:00
mintsuki d9e51dc7c8 gterm: Change resolutions at which autoscaling is triggered 2023-07-29 11:56:59 -05:00
mintsuki d31db59c1d menu: Center menu vertically 2023-07-29 11:56:59 -05:00
mintsuki 098eb82dd2 gop: Readd preset mode storage 2023-07-29 11:56:59 -05:00
mintsuki d951e40de9 menu: Do not draw box around boot menu 2023-07-29 11:56:59 -05:00
mintsuki e17639fb7e menu: Adjust centering by 2 characters to the left 2023-07-28 04:20:38 -05:00
mintsuki b417c3cb8d menu: Fix a couple of boot menu alignment issues 2023-07-28 04:20:38 -05:00
mintsuki 5ebe3b0e66 menu: Initialise max_len if null regardless of shift 2023-07-28 04:20:38 -05:00
mintsuki 46720c6644 menu: Fix maybe uninitialised issue with cur_len var 2023-07-28 04:20:38 -05:00
mintsuki 63938e898b menu: Fix NULL deref bug with shift variable 2023-07-28 04:20:38 -05:00
mintsuki 57cb9561aa console: Add slide command 2023-07-28 04:20:38 -05:00
mintsuki 79b8215e36 menu: Center boot menu 2023-07-28 04:20:38 -05:00
mintsuki c13cc6c84f Revert "build: Make limine-cd-efi.bin 16MiB in size (use FAT16)"
This reverts commit 5db3175b8f.
2023-07-28 04:20:21 -05:00
mintsuki 965159978c gterm: Autoscale font on higher resolutions 2023-07-28 04:19:51 -05:00
Kacper Słomiński d7966d0bf4 limine: Adjust higher half offsets for AArch64 2023-07-26 17:02:47 -05:00
Kacper Słomiński 1a0c38949b limine: Use a higher-half pointer for the stack on AArch64 2023-07-26 17:02:31 -05:00
mintsuki 051a7a631f misc: Minor updates to linker scripts 2023-07-26 17:02:04 -05:00
mintsuki b059e8661d build: Get rid of OBJCOPY2ELF_FLAGS since only IA-32/BIOS used it 2023-07-26 17:01:50 -05:00
mintsuki b0a074ad19 ci: Remove openssh dependency no longer required for release 2023-07-26 17:00:56 -05:00
mintsuki 5c13284558 host/limine-enroll-config: Fix typo 2023-07-26 17:00:36 -05:00
mintsuki eda35f4e9b docs: Update example Limine version in README to 4.20230709.0 2023-07-09 04:12:40 +02:00
mintsuki dc8700383b elf: elf64_load(): Remove accidentally left in debug code 2023-07-09 04:11:19 +02:00
mintsuki 6b87e3fa3d part: Require keypresses between entry displays in list_volumes() 2023-07-09 04:11:19 +02:00
mintsuki 1235c53da8 misc: Use assembly for memory functions on x86 2023-07-09 04:11:19 +02:00
mintsuki 05cf8dc89c elf: Fix potential uninitialised usage of bss_size 2023-07-09 04:11:19 +02:00
mintsuki 95c6a2dd63 limine/elf: Optimise not to scan .bss for requests 2023-07-09 04:11:19 +02:00
mintsuki 507688261f asm: Add missing section directives 2023-06-20 13:26:27 +02:00
mintsuki 95372b71c9 console: Add firmware type command 2023-06-20 11:10:35 +02:00
mintsuki b15b59659c gensyms: Filter out non-function symbols 2023-06-20 08:54:55 +02:00
mintsuki c623317591 docs: Update example Limine version in README to 4.20230615.0 2023-06-15 13:20:44 +02:00
mintsuki cc387af31d pmm: Use fixed value of 1024 for recl entries count 2023-06-15 13:08:17 +02:00
mintsuki fe7910cadf pmm: Fix change-memmap-in-use bug 2023-06-15 13:08:17 +02:00
mintsuki 3b9d29385c vmm: Fix page_sizes values and move declaration to top 2023-06-15 10:46:30 +02:00
mintsuki aa926e7a6b limine: Backport paging mode request from trunk 2023-06-15 07:28:08 +02:00
mintsuki 5db3175b8f build: Make limine-cd-efi.bin 16MiB in size (use FAT16) 2023-06-15 03:17:27 +02:00
mintsuki fdc1332c34 config: Add and document ARCH built-in macro 2023-06-15 02:34:11 +02:00
mintsuki 9a80df3dd0 build: Fix permissions of output files in makefile instead of release recipe 2023-06-15 01:36:09 +02:00
mintsuki 06349a1e33 misc: Add missing EFI executables install commands to host Makefile 2023-06-15 01:24:33 +02:00
mintsuki bc429f7912 test: Misc updates to the linker script 2023-06-15 01:23:56 +02:00
mintsuki f9787f2062 docs: BOOT{IA32,X64,AA64}.EFI -> BOOT*.EFI 2023-06-14 00:14:21 +02:00
mintsuki 277f3bd722 docs: Mention creating the ESP tree in ISOHYBRID partition 2023-06-13 12:35:17 +02:00
mintsuki 6c4c275c38 docs: Add donations link 2023-06-12 17:46:40 +02:00
mintsuki d182cc4bac misc: Updates for new limine-efi 2023-06-12 06:03:09 +02:00
mintsuki 3b199d382a misc: Updates for new flanterm 2023-06-11 04:56:48 +02:00
mintsuki 5538fef5ea docs: Update example Limine version in README to 4.20230606.0 2023-06-06 02:02:25 +02:00
mintsuki f8de2a2262 misc: Remove tinf from tree, pull at bootstrap time 2023-06-06 01:53:06 +02:00
mintsuki 4af9d4a863 test: Use retrage.github.io EDK2 nightly builds for all ports 2023-06-06 01:52:50 +02:00
mintsuki 561af46ab6 protos/linux: Do not zero EFI memmap size on IA-32 EFI 2023-06-06 01:52:03 +02:00
mintsuki 471ddf3c7d docs/readme: Adjust stb_image.h link to point to dev branch 2023-06-06 01:51:54 +02:00
mintsuki c2021eefeb docs: Add Limine pronounciation link to README.md 2023-06-06 01:51:43 +02:00
mintsuki 2208f0599f test: Fix copying mistake (typo) 2023-06-06 01:51:30 +02:00
Bryce Lanham dceb954807 Fix netboot in configs where BLOCK_IO does not exist
For example, netbooting qemu-system-aarch64 with no drive specified will
result in OVMF not loading the BLOCK_IO_PROTOCOL, causing a panic in
disk.s2.c.
2023-06-06 01:51:20 +02:00
mintsuki 906c346987 docs: Update example Limine version in README to 4.20230530.0 2023-05-30 22:44:13 +02:00
mintsuki 04a57cdfdd disk/efi: Do not use DISK_IO protocol and fix buffer reuse bug 2023-05-30 22:44:13 +02:00
mintsuki f03b240287 misc: Use C instead of asm for mem*() family of functions 2023-05-30 22:44:13 +02:00
mintsuki e772b99c77 docs: Update example Limine version in README to 4.20230529.0 2023-05-29 13:15:16 +02:00
mintsuki 3054354e7e ci: Fix permissions of certain files in binary branch 2023-05-29 13:15:16 +02:00
mintsuki 092df95a44 build/uefi: Remove now-useless -DGNU_EFI_USE_MS_ABI flag 2023-05-29 13:15:16 +02:00
mintsuki 6676a3a615 build/uefi: Pass -fshort-wchar to CC 2023-05-29 13:15:16 +02:00
mintsuki 0c66863d3e docs: Update example Limine version in README 2023-05-14 09:28:25 +02:00
mintsuki 68be84f075 stb_image: Track dev branch 2023-05-14 09:28:25 +02:00
mintsuki 3806246108 host: Perform compile-time endian check if supported 2023-05-14 09:28:25 +02:00
mintsuki fe76ce8f0b elf: Improve detection of relocatable ELFs 2023-05-14 09:28:25 +02:00
mintsuki 92341a02ad docs: Update example Limine version in README 2023-05-03 22:51:14 +02:00
mintsuki f6ef193d5c stb_image: Update to commit with zlib EOF bug fixed 2023-05-03 22:51:14 +02:00
mintsuki 2bf751a48a Revert "compress/gz: Add hack to allow macOS compressed GZs to load with stbi"
This reverts commit 1dd75a18ac.
2023-05-03 22:51:14 +02:00
mintsuki a740e84d15 Revert "misc: Revert back to using tinf for all GZ decompression"
This reverts commit 3438b8d235.
2023-05-03 22:51:14 +02:00
mintsuki 5dce921e25 Revert "uri: Backport pre-tinf-removal variable assignments"
This reverts commit 514522125b.
2023-05-03 22:51:14 +02:00
mintsuki 447de6d90b build: Remove some empty lines in dist make target 2023-05-03 22:51:14 +02:00
Bryce Lanham f3f09eca49 multiboot1: also fix elf32 section loading
As with the prior mb2 fix, use the correct size elf section header for
32 bit elf
2023-05-03 22:51:14 +02:00
Bryce Lanham b7bca1b000 multiboot2: fix 32 bit elf section loading
Existing code was using 64 bit elf section header unconditionally. This
commit fixes that :)
2023-05-03 22:51:14 +02:00
mintsuki 4960086ec6 hgen: Add extra sed command for handling Solaris's od 2023-05-03 22:51:14 +02:00
mintsuki 9ff988ed74 pxe: Add and use constant PXE ACK packet size and fix BIOS PXE ACK struct 2023-04-28 05:21:06 +02:00
mintsuki 27cf36fbc8 menu: Do not initialise textmode terminal if QUIET=yes. Addresses #269 2023-04-28 05:21:06 +02:00
mintsuki b58de84b8e bootstrap: Add BOOTSTRAP_NO_SHALLOW_CLONES support 2023-04-28 05:21:06 +02:00
Bryce Lanham 988ca16212 Implement Multiboot2 network tag
Added caching of the dhcp response in the pxe code, and then adding the
tag containing it.
2023-04-28 05:21:06 +02:00
Bryce Lanham 04cc4390b4 Fix PXE BIOS boot when using a proxy DHCP server 2023-04-22 12:16:20 +02:00
mintsuki 259ab0166e build: Sanitise autoconf substitutions with gmake variables 2023-04-22 12:15:50 +02:00
mintsuki 09e38cc9c4 build: Pass proper warning flags to nasm 2023-04-22 12:14:14 +02:00
mintsuki 3bed9986b3 docs: Document TEXTMODE config for multiboot 1 and 2 2023-04-14 13:41:41 +02:00
mintsuki 72a6d921c8 multiboot1: Support TEXTMODE config as with Linux/mb2 protocols 2023-04-14 13:41:41 +02:00
mintsuki cbc7e5a860 textmode: Actually disable term hooking on non-managed initialisation 2023-04-14 13:41:41 +02:00
K. Lange 616ee9cf21 multiboot2: ignore unsupported tags if they are marked optional 2023-04-14 13:41:41 +02:00
K. Lange aae6aa1cea multiboot2: Support TEXTMODE config as with linux 2023-04-14 13:41:41 +02:00
mintsuki 77591d21b1 multiboot2: Fix lack of argument to panic format string 2023-04-14 13:41:41 +02:00
mintsuki d1cb337894 build: Reorganise warning flags 2023-04-14 13:41:41 +02:00
mintsuki 86632c703f build: Use uppercase PIE/PIC compilation flags 2023-04-14 13:41:41 +02:00
mintsuki f79c111f19 uri: Backport pre-tinf-removal variable assignments 2023-04-08 03:53:04 +02:00
mintsuki aca7e65c2f misc: Revert back to using tinf for all GZ decompression 2023-04-08 03:53:04 +02:00
mintsuki 4f56e0ac8a limine: Fix spurious deprecation warnings coming from limine.h 2023-03-30 08:26:16 +02:00
mintsuki 4e1fe0b784 limine: Add note about deprecation of terminal to PROTOCOL.md 2023-03-30 05:40:21 +02:00
mintsuki f297482dd5 limine: Clarify ambiguity with response revision and internal modules 2023-03-30 05:40:21 +02:00
mintsuki 8e97650ae9 limine: Fix issue with internal modules and kernels in root dir 2023-03-30 05:40:21 +02:00
mintsuki 425a2328f0 limine: Mark terminal as deprecated 2023-03-30 05:40:21 +02:00
mintsuki f1f56958ea term: Drop in_bootloader for new Flanterm 2023-03-30 05:40:21 +02:00
mintsuki 7a3e1f7773 misc: Updates for Flanterm rebrand 2023-03-30 05:40:21 +02:00
mintsuki 034b5cca50 limine-deploy: Check ferror() before using perror() on fread/fwrite fails 2023-03-30 05:40:21 +02:00
mintsuki e132b5dfa5 limine: Fix framebuffer pointer in terminal struct being invalid without a framebuffer request 2023-03-30 05:40:21 +02:00
mintsuki 366e8c488a limine: Fix bug where internal modules are parsed with revision < 1 2023-03-25 00:59:27 +01:00
mintsuki f5cd6e4dd6 limine: Document internal modules 2023-03-24 18:56:31 +01:00
mintsuki 48db5dd456 limine: Support relative-to-kernel paths for internal modules 2023-03-24 18:56:31 +01:00
mintsuki 795490e325 limine: Honour LIMINE_INTERNAL_MODULE_REQUIRED flag 2023-03-24 18:56:31 +01:00
mintsuki a48a90a81a limine: Load internal modules before config modules 2023-03-24 18:56:31 +01:00
mintsuki 328b817474 limine: Implement internal modules concept 2023-03-24 18:56:31 +01:00
mintsuki 6861bb803c build: Split test portion of root makefile to own file 2023-03-24 18:56:31 +01:00
mintsuki 9fa5b1759a build: Minor build system updates 2023-03-24 18:56:31 +01:00
mintsuki 6ce977f8c2 build: Minor build system updates 2023-03-24 18:56:31 +01:00
mintsuki 4aebbfb507 compress: Rename modified tinfgzip wrapper to gzip 2023-03-17 21:19:07 +01:00
mintsuki afb9e3222c build: Remove useless unset commands from common GNUmakefile 2023-03-17 21:19:07 +01:00
mintsuki 411f164b53 build: Use DEFAULT_VAR for all overridable default makefile vars 2023-03-17 21:19:07 +01:00
mintsuki 6f3deecdd2 Revert "build: bootstrap: Do not manually install install-sh"
This reverts commit 5f5c98866e.
2023-03-17 21:19:07 +01:00
mintsuki 282d2df6db build: Misc updates for new freestanding-toolchain 2023-03-17 21:19:07 +01:00
mintsuki 852750548e build: Fix up some makefile variable names 2023-03-17 21:19:07 +01:00
mintsuki b040010cec build: configure: Change some variable names to be more friendly 2023-03-17 21:19:07 +01:00
mintsuki b39c6e9e93 decompressor: Move tinf directory to decompressor directory 2023-03-17 21:19:07 +01:00
mintsuki bb8bcab3b6 build: configure: Exit on freestanding-toolchain error 2023-03-15 09:55:43 +01:00
mintsuki ed3858fe11 build: bootstrap: Do not manually install install-sh 2023-03-14 21:06:49 +01:00
mintsuki 9efe05df89 build: Add and use PROG_ABSPATH autoconf macro 2023-03-14 21:06:49 +01:00
mintsuki 91acfcc0d1 build: Updates for newer freestanding-toolchain 2023-03-14 21:06:49 +01:00
mintsuki 6a3b441be4 misc: bootstrap: Fix freestanding-toolchain presence check 2023-03-14 21:06:49 +01:00
mintsuki ebf5c62b8b misc: Do not remove freestanding-toolchain from release tarball 2023-03-13 21:40:40 +01:00
mintsuki 9c16545862 misc: Use freestanding-toolchain instead of cross-detect 2023-03-13 21:40:40 +01:00
mintsuki db099aa213 docs: LICENSE.md -> LICENSE 2023-03-13 21:40:40 +01:00
mintsuki f381c83055 chainload: LoadOptionsSize should be in bytes. Fixes #254 2023-03-08 15:40:13 +01:00
mintsuki 3f17a0f0f1 protocol: Specify that kernel must be physically contiguous 2023-03-08 07:34:08 +01:00
mintsuki 6523b0bc4e chainload: BIOS: do not rely on 0x7c00 being free 2023-03-07 14:01:59 +01:00
mintsuki 39784a2199 vga_textmode: Minor cursor-related bug fixes 2023-03-07 14:01:59 +01:00
mintsuki 97ec5124c2 misc: Load BIOS port at 0xf000 instead of 0x8000 2023-03-07 14:01:59 +01:00
mintsuki 81f4d5dfb4 misc: Change example wallpaper 2023-03-07 14:01:59 +01:00
mintsuki 9f51235ad0 stb_image: Fix free/realloc wrappers to handle being passed NULL 2023-03-05 19:01:33 +01:00
mintsuki edd4454b00 gterm: Fix NULL dereference bug when no wallpaper used 2023-03-05 09:49:29 +01:00
mintsuki 77cd8b085a gh: Remove issue templates 2023-03-05 09:25:57 +01:00
mintsuki f92e6706c4 compress/gz: Add hack to allow macOS compressed GZs to load with stbi 2023-03-05 09:25:57 +01:00
mintsuki 7b9600c893 image: Use stbi_image_free() instead of freeing buffer ourselves 2023-03-05 09:25:57 +01:00
mintsuki baf5f6c2ce stb_image: More proper implementation of malloc/free/realloc macros 2023-03-05 09:25:57 +01:00
mintsuki 4c8646300a docs: Minor README.md formatting fix 2023-03-05 09:25:57 +01:00
mintsuki 296e0a2684 image: Use stb_image for image loading 2023-03-05 09:25:57 +01:00
mintsuki af495884ba build: Honour CROSS_CPPFLAGS 2023-02-27 01:46:10 +01:00
mintsuki c3a869e185 build: Install markdown docs on install; distclean fix 2023-02-21 03:32:28 +01:00
mintsuki cc6198643e build: Only install limine-deploy.1 man page if built 2023-02-21 03:32:28 +01:00
mintsuki 7cd5abc39d docs: Add man pages for host executables 2023-02-21 03:32:28 +01:00
mintsuki 00f228f750 build: Very minor QOL fixes 2023-02-21 03:32:28 +01:00
mintsuki 4c82fa2574 docs: Update PHILOSOPHY.md to note reason for ext* driver inclusion 2023-02-20 05:10:34 +01:00
mintsuki 2a5d66e99b build: Misc quality-of-life fixes 2023-02-19 10:44:09 +01:00
mintsuki f022bcd195 misc: Let freestanding-headers handle limits.h 2023-02-19 10:44:09 +01:00
mintsuki dee6dc80ba menu: Fix issue introduced in 48053fd2 where TIMEOUT=0 would not show interface 2023-02-16 07:18:05 +01:00
mintsuki 24af4c116e uri/tinfgzip: Minor fixes and layering improvement 2023-02-16 04:19:31 +01:00
mintsuki ccb0d0f738 uri: Fix minor use-after-free bug 2023-02-16 04:19:31 +01:00
mintsuki d22b97cf66 uri: Prevent memory leak when opening compressed files 2023-02-16 04:19:31 +01:00
mintsuki 08b349e513 misc: Backport multiple framebuffer support from trunk 2023-02-16 04:13:22 +01:00
mintsuki fe9f8d17c6 docs: Document TERM_BACKGROUND_BRIGHT and TERM_FOREGROUND_BRIGHT 2023-02-15 21:20:55 +01:00
mintsuki 1d4887d59d docs: Update PHILOSOPHY.md noting that ext2/3/4 has been dropped 2023-02-15 12:48:14 +01:00
mintsuki a80eba16a8 stb/image: Comment out problematic functions 2023-02-15 12:48:14 +01:00
mintsuki c2e70b6f2e stb: Ignore some warnings coming from stb_image.h 2023-02-15 12:48:14 +01:00
mintsuki f6282c37bc compress: Replace tinf's inflate implementation with stb_image's zlib 2023-02-15 12:48:14 +01:00
mintsuki ee4c1486cd build: Use separate STRIP program in host Makefile 2023-02-12 23:27:04 +01:00
mintsuki 6164580167 build: Further fixes related to cd8188d8 2023-02-12 23:27:04 +01:00
mintsuki 66423cf2ff build: Update for latest cross-detect 2023-02-12 23:27:04 +01:00
mintsuki 958ac86183 build: Misc configure.ac improvements, install-strip fix ups 2023-02-12 23:27:04 +01:00
mintsuki 4cc03205ed build: Update for latest cross-detect 2023-02-12 07:54:49 +01:00
mintsuki 8206d237e7 host/enroll-config: Bring up to standard with deploy 2023-02-08 23:46:23 +01:00
mintsuki 1746268560 host/enroll-config: Fix buffer overflow 2023-02-08 23:46:23 +01:00
mintsuki eddc1a1230 build: Fix race condition in root GNUmakefile.in 2023-02-07 05:14:10 +01:00
mintsuki 8cb03108e0 docs: README.md: Document secure boot and config hash enrolling 2023-02-07 01:02:09 +01:00
mintsuki fa50944b6d docs: Misc README.md fixes and updates 2023-02-07 01:02:09 +01:00
mintsuki de409b9371 config: Do not allow recovering from checksum mismatch panic 2023-02-07 01:02:09 +01:00
mintsuki abc5119a01 config: No longer allow continuing boot on checksum mismatches 2023-02-07 01:02:09 +01:00
mintsuki a72d2fc59d misc: Add support for enrolling config blake2b hash in executable 2023-02-07 01:02:09 +01:00
mintsuki d7e827f51a docs: Add PHILOSOPHY.md 2023-02-07 01:02:09 +01:00
mintsuki 4d362ea0e9 protocol: Update copyright date in limine.h 2023-02-07 01:02:09 +01:00
mintsuki c132903b7f term: Expose support for out-of-band output control 2023-01-20 21:05:24 +01:00
mintsuki e6cc9c9b21 file: Fix several bugs to do with handling of path field 2023-01-20 21:05:24 +01:00
mintsuki b3146edfda Revert "Revert "Revert "ci: Build and check using Alpine instead of Arch"""
This reverts commit 8caf7b5b75.
2023-01-20 21:05:24 +01:00
Qwinci 5efd4357dc limine: Add UEFI PXE support based on @qookei's original patch with small changes. 2023-01-20 21:05:24 +01:00
mintsuki 2ef15c15e4 efi/chainload: Support passing of command lines. Addresses #244 2023-01-14 13:43:21 +01:00
mintsuki 3152b05a26 misc: Update copyright for 2023 2023-01-14 13:43:21 +01:00
mintsuki dffd45a688 Revert "Revert "ci: Build and check using Alpine instead of Arch""
This reverts commit ce4046d559.
2022-12-30 09:04:46 +01:00
mintsuki 4bb7423609 ci: Remove website upload portion of workflow 2022-12-30 08:53:38 +01:00
mintsuki 258388c890 term: Compatibility with new terminal code 2022-12-30 08:31:39 +01:00
mintsuki 78075319d4 lib/gterm: Remove now-useless full_refresh() call 2022-12-16 03:53:45 +01:00
mintsuki 72f074bfc2 term: Compatibility with latest terminal changes 2022-12-14 16:35:05 +01:00
mintsuki e1c0d71b97 host/limine-deploy: Add quiet option. Closes #243 2022-12-14 01:12:05 +01:00
mintsuki a0184f0145 docs/protocol: Fix syntax highlighting of struct limine_video_mode 2022-12-14 01:12:05 +01:00
TornaxO7 9bcaeffcc0 adding bytes description to stack_size 2022-12-14 01:12:05 +01:00
Raphael O a0933b7316 docs/protocol: Fix wording for reserved/reclaimable
Switch from bootloader-reserved to bootloader-reclaimable so that the memory regions reserved and bootloader-reclaimable are not confused.
2022-12-04 10:48:40 +01:00
mintsuki 104e0c5ef1 readline: Fix issue arising from terminal's wraparound handling fix 2022-11-19 08:20:04 +01:00
mintsuki 1c0db86965 disk: Fix issue where _p struct was not zeroed out in create_disk_index() 2022-11-19 08:20:04 +01:00
beakeyz 690c3ccee9 Fixed little memory leak in the UEFI build that would make the bootloader crash on systems with larger disks 2022-11-19 08:20:04 +01:00
mintsuki a94a0f59c6 docs: Add packaging status to README.md 2022-11-19 08:20:04 +01:00
mintsuki 066244c692 gop: Remove ConOut logic 2022-11-19 08:20:04 +01:00
mintsuki 0f70361281 gop: Use ConOut to obtain GOP whenever possible 2022-11-14 08:10:19 +01:00
mintsuki 2200f373ac limine.h: Use C90 style comments for license header 2022-11-14 08:10:19 +01:00
mintsuki e95df146df Revert "gop: Allow user to select which GOP to use in config. Addresses #233"
This reverts commit d82dc64b93.
2022-11-14 08:10:19 +01:00
mintsuki b10c5617c1 Revert "gop: Fix implicit declaration warning introduced in d82dc64b"
This reverts commit c477414c5c.
2022-11-14 08:10:19 +01:00
Ryan Cohen 937d2c379c readline: Fix command line scrolling and cursor wrap-around
Fixes `cursor_fwd` to wrap the cursor to the first column when it passes
the bottom right corner of the screen.

Fixes `readline` to update the command line's row position when the
cursor wrap-around causes the screen to scroll up.
2022-11-14 08:10:19 +01:00
mintsuki 76a5873369 gop: Fix implicit declaration warning introduced in d82dc64b 2022-11-12 00:54:30 +01:00
mintsuki f78243c375 gop: Allow user to select which GOP to use in config. Addresses #233 2022-11-12 00:54:30 +01:00
mintsuki 55a0181b11 limine.h: Add license header 2022-11-12 00:54:30 +01:00
mintsuki 9ae0bcefc9 Revert "smp/x86: Free up trampoline memory after use"
This reverts commit ae771dd8a1.
2022-11-02 15:34:53 +01:00
mintsuki f9e422b571 docs/protocol: Clarify file address alignment 2022-10-30 15:02:07 +01:00
mintsuki 88d99fa34b multiboot2: Support load_addr == -1 2022-10-30 15:02:07 +01:00
mintsuki 2fab5311d8 smp/x86: Free up trampoline memory after use 2022-10-30 15:02:07 +01:00
mintsuki 23081f06d5 pmm: Work around potential memmap data race in EFI init_memmap() 2022-10-17 06:45:45 +02:00
mintsuki f3357648ab pmm: Fix AllocatePages() call to take pages count; remove useless alignment check 2022-10-17 06:45:45 +02:00
mintsuki 7d0ef9ef24 pmm: Avoid throwing away big memory ranges that fail to AllocatePages() indiscriminately 2022-10-17 06:45:45 +02:00
mintsuki 5a1375f9d7 Revert "ci: Build and check using Alpine instead of Arch"
This reverts commit 502f77b30f.
2022-10-16 01:31:38 +02:00
mintsuki bda32f7325 linux: Revert 793d0293 2022-10-14 14:34:15 +02:00
mintsuki 8b1c1ef6e5 disk: Fix wrong parameter passed to ReadBlocks() 2022-10-14 07:45:10 +02:00
mintsuki 0f1e929178 docs: Document blake2b checksums related things 2022-10-14 07:45:10 +02:00
mintsuki 5b8f3fe0ee docs: Fix formatting issue in PROTOCOL.md 2022-10-14 07:45:10 +02:00
mintsuki 5d5f29ffeb misc: Minor cleanup after #216 2022-10-14 05:42:15 +02:00
czapek1337 2a4cbcecc0 uri: Add checksum validation 2022-10-14 05:42:15 +02:00
czapek1337 5a6cc57773 print: Specifier for printing URIs 2022-10-14 05:42:15 +02:00
mintsuki 9bf0d263ee gop: Do not zero default_res out erroneously 2022-10-14 05:42:15 +02:00
mintsuki 09941f905b limine: Add support for framebuffer modes listing 2022-10-14 05:42:15 +02:00
mintsuki 5e29b6574c file: Reimplement a1bcf3c0 without use-after-free bug 2022-10-14 05:42:15 +02:00
mintsuki a016008f16 ci: Build and check using Alpine instead of Arch 2022-10-14 05:42:15 +02:00
mintsuki bdce16444c misc: Update references to hardcoded directories 2022-10-14 05:42:15 +02:00
mintsuki 1eefb6b6a8 disk: UEFI: Add BLOCK_IO fallback for volume_from_efi_handle() 2022-10-14 05:42:15 +02:00
mintsuki ed238b7ccf disk: On UEFI, improve optical vs non-optical detection 2022-10-14 05:42:15 +02:00
mintsuki 0aa3bc05e2 elf: Add overlapping PHDR detection 2022-10-11 06:06:57 +02:00
mintsuki 9d1d910d9c disk: Only use BLOCK_IO as fallback to DISK_IO when determining optical 2022-10-09 11:09:27 +02:00
mintsuki 2e05e4ca40 disk: On BIOS, change how optical is determined 2022-10-09 11:09:27 +02:00
mintsuki 0744033703 limine: Fix bug which triggered on no-NX where wrong register was used for rd/wrmsr 2022-10-09 11:09:27 +02:00
mintsuki 3af2fb1e84 docs: Update README.md 2022-10-07 10:16:21 +02:00
mintsuki 17be311aeb menu: Add arrows to indicate overflow for many menu entries 2022-10-07 10:16:21 +02:00
mintsuki 42cc1d8e20 misc: Dynamically allocate EFI memmap copy 2022-10-07 10:16:21 +02:00
mintsuki 15737894cb menu: Properly handly high number of entries 2022-10-07 10:16:21 +02:00
mintsuki ea412cfae7 misc: Increase EFI_COPY_MAX_ENTRIES to 2048 2022-10-07 10:16:21 +02:00
mintsuki 4860f95539 limine/smp: Fix stack offset accidentally added twice 2022-10-06 19:20:06 +02:00
mintsuki 6733f194df menu: Add missing valid keys 2022-10-06 06:38:35 +02:00
mintsuki ff145eb511 term: Misc improvements for SERIAL=yes on EFI 2022-10-06 06:38:35 +02:00
mintsuki 33dac9b38a term: Unbreak textmode + serial combo 2022-10-06 06:38:35 +02:00
mintsuki 5bbda71da2 gterm: Prevent memory leak gterm_init() failure 2022-10-06 06:38:35 +02:00
mintsuki aca99ad790 limine: Fix NULL term dereference bug if gterm_init fails 2022-10-06 06:38:35 +02:00
mintsuki a76691a930 misc: Add limine subdir to stage3 and config search paths. Closes #225 2022-10-06 06:34:42 +02:00
czapek1337 6202148460 efi: Fallback to volume scan instead of panicking 2022-10-06 06:34:42 +02:00
czapek1337 6a8e4eb49a disk: Use BLOCK_IO instead of DISK_IO 2022-10-06 06:34:42 +02:00
czapek1337 e445555bab readline: Fallback to SystemTable->ConIn 2022-10-06 06:34:42 +02:00
mintsuki 9722827002 term: Better ensure term is not accessed when NULL 2022-10-05 15:05:17 +02:00
mintsuki 10df010029 limine: Do not panic if failing to set up terminal or framebuffer 2022-10-05 15:05:17 +02:00
mintsuki 194e60a3ba menu: Use fallback terminal instead of panicking on gterm_init() fail 2022-10-05 15:05:17 +02:00
mintsuki fc2fe1a3d2 limine: Fix bug where NULL term was accessed. Fixes #227 2022-10-05 15:05:17 +02:00
mintsuki d65d180c0d limine: Reimplement proper callback functionality 2022-10-04 22:22:31 +02:00
mintsuki dddcf34a8c term: Make term_notready() static 2022-10-04 22:22:31 +02:00
mintsuki 6f1e157cec term: Gate BIOS specific code behind ifdefs 2022-10-04 22:22:31 +02:00
mintsuki 7065967be3 term: Reimplement context control 2022-10-04 22:22:31 +02:00
mintsuki f5cdb5b900 term: Misc fixes and improvements 2022-10-04 22:22:31 +02:00
mintsuki 223ebc1932 term: Misc fixes and improvements 2022-10-04 22:22:31 +02:00
mintsuki 1c06055e6d term: Misc fixes and improvements 2022-10-04 22:22:31 +02:00
mintsuki 3cb47a9dd1 term: Add builtin font 2022-10-04 22:22:31 +02:00
mintsuki 68f9bdcdca term: Misc minor bug fixes 2022-10-04 22:22:31 +02:00
mintsuki c30dffd147 term: Tidy up VGA textmode wrapper code 2022-10-04 22:22:31 +02:00
mintsuki d442805bc0 term: Tidy up gterm wrapper code 2022-10-04 22:22:31 +02:00
mintsuki ad8151a6a6 term: Move to use external, portable terminal 2022-10-04 22:22:31 +02:00
mintsuki fc6e44c82c pmm: Misc bug fixes in pmm 2022-09-28 02:10:08 +02:00
mintsuki b42559b27a term: Misc bug fixes in fallback backends 2022-09-28 02:10:08 +02:00
mintsuki 225b871721 build: Use variables to determine installable files instead of ignoring errors 2022-09-28 02:10:08 +02:00
mintsuki ad09d3f423 docs: Update README.md in preparation for version naming scheme change 2022-09-27 06:57:10 +02:00
mintsuki 14ef93ab24 term: Do not reset mode on UEFI fallback init 2022-09-27 06:57:10 +02:00
mintsuki e124fe4e7a multiboot: Fix warnings when building BIOS port 2022-09-27 06:57:10 +02:00
mintsuki a0810f9e13 multiboot: Allow for headless boots 2022-09-27 06:57:10 +02:00
mintsuki 4b4f3c9d68 pmm: Obtain raw memmap from untouched_memmap rather than EFI memmap. Addresses #222 and https://forum.puppylinux.com/viewtopic.php?t=6881 2022-09-27 06:57:10 +02:00
mintsuki 165b4d8f7a pmm: Keep first page on sanitiser call in get_raw_memmap() 2022-09-27 06:57:10 +02:00
mintsuki 9203b9cea4 pmm: Backport some other stuff reverted in 4a4409e1 2022-09-27 06:57:10 +02:00
mintsuki abcbff6ec1 pmm: Backport fa6f6077 and 74a3a1c6 2022-09-27 06:57:10 +02:00
mintsuki c381963592 pmm: Undo most of what was done between 85603ec8 and 74a3a1c6 2022-09-24 04:35:52 +02:00
mintsuki 4662a4d190 panic: Fix build on non-BIOS targets 2022-09-24 04:35:52 +02:00
mintsuki 4d7f1d5d1c term: Move more of it to stage 3 2022-09-24 04:35:52 +02:00
mintsuki 6b9ba912c6 Revert "linux/efi: Perform efi_memmap_size=0 workaround for 32 on 64 as well"
This reverts commit b9f41799b4.
2022-09-24 04:35:52 +02:00
mintsuki 124b444da7 build: Update install commands to be more quiet on non-fatal fail 2022-09-24 04:35:52 +02:00
mintsuki 23a63ef476 linux/efi: Perform efi_memmap_size=0 workaround for 32 on 64 as well 2022-09-22 18:18:06 +02:00
mintsuki c1941bdfd5 build: Update build option dependencies and names 2022-09-22 18:18:06 +02:00
mintsuki c2ed0bcbd1 config: On UEFI, scan the volume containing the EFI executable first. Addresses #219 2022-09-22 18:18:06 +02:00
mintsuki 58ef3bd8a9 build: Honor LIBS variable 2022-09-20 23:57:29 +02:00
mintsuki 025792e994 build: Honor CPPFLAGS variable 2022-09-20 23:57:29 +02:00
mintsuki 93ebf613e9 menu: Fix regression when pressing a key during quiet timeout wait. Addresses in part #220 2022-09-20 23:57:29 +02:00
mintsuki 24e4e61394 build: Fix issue introduced in 87e09dba 2022-09-20 10:10:00 +02:00
mintsuki 96ceab3c72 misc: Fix bugs introduced in 3181293a 2022-09-20 10:10:00 +02:00
mintsuki a37391ce6d disk/efi: Improve firmware error handling 2022-09-20 10:10:00 +02:00
mintsuki ba1dfc1bbc build: Plug back limine_stage2only.elf into the BIOS build system 2022-09-20 10:10:00 +02:00
mintsuki f4b1996701 menu: Avoid reinitialising fallback terminal on first runs 2022-09-18 22:34:53 +02:00
mintsuki 62fa8a90af smp: Fix indentation 2022-09-18 22:34:53 +02:00
mintsuki ff33b6fbb6 efi: Limit amount of tries to get boot volume from handle 2022-09-18 22:34:53 +02:00
mintsuki b09b816ee2 misc: Fix up some no_unwind globals 2022-09-18 22:34:53 +02:00
mintsuki 710757420b misc: Misc stage 2 related improvements 2022-09-18 22:34:53 +02:00
mintsuki 3181293a04 misc: Improve printing effectively on panics and errors 2022-09-18 22:34:53 +02:00
mintsuki 8773c36ab6 multiboot2: Fix broken EFI memmap length calculation 2022-09-16 11:50:47 +02:00
mintsuki 98c9b4ea2d efi: Ensure panics are (hopefully) always visible 2022-09-16 11:50:47 +02:00
mintsuki 14181a9eba efi/disk: Use blake2b to calculate unique sector hash 2022-09-16 11:50:47 +02:00
czapek1337 f369a7e04f crypt: Implement blake2b hash function 2022-09-16 11:50:47 +02:00
mintsuki 8307d96f3c build: Do not request readelf from cross-detect when not needed 2022-09-16 11:50:47 +02:00
mintsuki 6235c15efb build: Change name of --enable-uefi-x86_64 option to --enable-uefi-x86-64 2022-09-16 11:50:47 +02:00
mintsuki a8609be921 build: Only check nasm and gzip presence as needed 2022-09-16 11:50:47 +02:00
mintsuki 1ac9fa6ae1 smp: Fix aarch64 issue introduced in 0f04f686 2022-09-15 03:17:49 +02:00
mintsuki 5b5f768360 smp: Remove hacks needed for stivale 2022-09-15 03:17:49 +02:00
mintsuki 08b004600a build: Fix stage2 map 2022-09-15 03:17:49 +02:00
Andy-Python-Programmer d56ff6f7cb DTB: ensure the `dtb_ptr` is an HHDM address
* Ensure that the `dtb_ptr` is an HHDM address
* If DTB is not found, do not generate the response

Signed-off-by: Andy-Python-Programmer <andypythonappdeveloper@gmail.com>
2022-09-12 12:09:16 +02:00
mintsuki fe647a067f elf: Fix issue where KASLR was applied to non reloc executables 2022-09-12 12:09:16 +02:00
mintsuki 831af39ed4 Revert "Revert "elf: General refactor""
This reverts commit 4c8516c6a6.
2022-09-12 12:09:16 +02:00
mintsuki 4c8516c6a6 Revert "elf: General refactor"
This reverts commit 3452e492bb.
2022-09-11 17:47:49 +02:00
157 changed files with 6380 additions and 5508 deletions

View File

@ -1,26 +0,0 @@
---
name: Bug report
about: Create a report to help us fix a bug
title: ''
labels: bug
assignees: ''
---
**Limine version used**
Put the version of Limine where the bug was encountered here. If using `trunk`, the commit hash. Also mention if BIOS or UEFI, or both.
**Expected behaviour**
A clear and concise description of what you expected to happen.
**Actual (broken) behaviour**
A clear and concise description of what happens instead.
**To Reproduce**
Steps to reproduce the behavior, if possible.
**Stacktrace**
If the bug results in a panic, show the resulting the stacktrace here.
**Additional context**
Add any other context about the problem here.

View File

@ -19,10 +19,10 @@ jobs:
run: git config --global --add safe.directory "$GITHUB_WORKSPACE"
- name: Build the bootloader (LLVM)
run: ./bootstrap && ./configure CROSS_TOOLCHAIN=llvm --enable-werror --enable-all && make all && make maintainer-clean
run: ./bootstrap && ./configure TOOLCHAIN_FOR_TARGET=llvm --enable-werror --enable-all && make all && make maintainer-clean
- name: Build the bootloader (GCC, x86)
run: ./bootstrap && ./configure CROSS_CC=gcc CROSS_LD=ld CROSS_OBJCOPY=objcopy CROSS_OBJDUMP=objdump CROSS_READELF=readelf --enable-werror --enable-bios --enable-uefi-ia32 --enable-uefi-x86_64 && 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
- name: Build the bootloader (GCC, aarch64)
run: ./bootstrap && ./configure CROSS_TOOLCHAIN=aarch64-linux-gnu --enable-werror --enable-uefi-aarch64 && 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
@ -36,7 +36,7 @@ jobs:
run: mkdir -p build
- name: Configure
run: cd build && ../configure --enable-all CROSS_TOOLCHAIN=llvm
run: cd build && ../configure --enable-all TOOLCHAIN_FOR_TARGET=llvm
- name: Build the bootloader
run: make -C build
@ -44,17 +44,26 @@ jobs:
- name: Clean limine-version
run: rm build/bin/limine-version
- name: Clean limine-enroll-config
run: rm build/bin/limine-enroll-config
- name: Build limine-enroll-config-win32
run: make -C build/bin CC="i686-w64-mingw32-gcc" CFLAGS="-O2 -pipe" CPPFLAGS="-D__USE_MINGW_ANSI_STDIO" limine-enroll-config
- name: Strip limine-enroll-config-win32
run: i686-w64-mingw32-strip build/bin/limine-enroll-config.exe
- name: Clean limine-deploy
run: rm build/bin/limine-deploy
- name: Build limine-deploy-win32
run: make -C build/bin CC="i686-w64-mingw32-gcc" CFLAGS="-O2 -pipe" limine-deploy
run: make -C build/bin CC="i686-w64-mingw32-gcc" CFLAGS="-O2 -pipe" CPPFLAGS="-D__USE_MINGW_ANSI_STDIO" limine-deploy
- name: Strip limine-deploy-win32
run: i686-w64-mingw32-strip build/bin/limine-deploy.exe
- name: Copy LICENSE to bin
run: cp LICENSE.md build/bin/
run: cp LICENSE build/bin/
- name: Copy install-sh to bin
run: cp build-aux/install-sh build/bin/
@ -98,11 +107,3 @@ jobs:
limine-*.tar.*
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Retrieve SSH key
run: 'echo "$ssh_key" > ssh_key && chmod 600 ssh_key'
env:
ssh_key: ${{ secrets.SSH_KEY }}
- name: Upload tarballs to website
run: 'scp -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i ssh_key limine-*.tar.* mint@limine-bootloader.org:/var/www/limine/html/files/limine/'

11
.gitignore vendored
View File

@ -1,9 +1,12 @@
/bin
/build
/cross-files
/toolchain-files
/limine-efi
/freestanding-headers
/libgcc-binaries
/common/flanterm
/common/stb/stb_image.h
/decompressor/tinf
/ovmf*
*.o
*.d
@ -23,14 +26,18 @@
/.vscode
/test_image
!/common/font.bin
/cross-detect
/freestanding-toolchain
/configure
/configure.ac.save
/build-aux
/aclocal.m4
/*~
/config.status
/config.log
/autom4te.cache
/man/man1/limine-version.1
/man/man1/limine-deploy.1
/man/man1/limine-enroll-config.1
/GNUmakefile
/config.h
/common-bios

View File

@ -3,8 +3,10 @@
## Location of the config file
Limine scans for a config file on *the boot drive*. Every partition on the boot drive
is scanned sequentially (first partition first, last partition last) for the presence
of either a `/limine.cfg`, `/boot/limine.cfg`, or a `/EFI/BOOT/limine.cfg` file, in that order.
is scanned sequentially - first partition first (or, on UEFI, the partition containing the
EFI executable of the booted Limine is scanned first), last partition last - for the presence
of either a `/limine.cfg`, `/limine/limine.cfg`, `/boot/limine.cfg`, `/boot/limine/limine.cfg`,
or a `/EFI/BOOT/limine.cfg` file, in that order.
Once the file is located, Limine will use it as its config file. Other possible
candidates in subsequent partitions or directories are ignored.
@ -59,6 +61,7 @@ Some keys take *URIs* as values; these are described in the next section.
* `VERBOSE` - If set to `yes`, print additional information during boot. Defaults to not verbose.
* `RANDOMISE_MEMORY` - If set to `yes`, randomise the contents of RAM at bootup in order to find bugs related to non zeroed memory or for security reasons. This option will slow down boot time significantly. For the BIOS port of Limine, this will only randomise memory below 4GiB.
* `RANDOMIZE_MEMORY` - Alias of `RANDOMISE_MEMORY`.
* `HASH_MISMATCH_PANIC` - If set to `no`, do not panic if there is a hash mismatch for a file, but print a warning instead.
Limine interface control options.
@ -66,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.
@ -77,9 +81,11 @@ Limine graphical terminal control options. They are ignored if using text mode.
* `TERM_PALETTE_BRIGHT` - Specifies the bright colour palette used by the terminal (RRGGBB). It is a `;` separated array of 8 bright colours: dark gray, bright red, bright green, yellow, bright blue, bright magenta, bright cyan, and white. Ignored if not using a graphical terminal.
* `TERM_BACKGROUND` - Terminal text background colour (TTRRGGBB). TT stands for transparency.
* `TERM_FOREGROUND` - Terminal text foreground colour (RRGGBB).
* `TERM_BACKGROUND_BRIGHT` - Terminal text background bright colour (RRGGBB).
* `TERM_FOREGROUND_BRIGHT` - Terminal text foreground bright colour (RRGGBB).
* `TERM_MARGIN` - Set the amount of margin around the terminal.
* `TERM_MARGIN_GRADIENT` - Set the thickness in pixel for the gradient around the terminal.
* `TERM_WALLPAPER` - URI where to find the .BMP file to use as wallpaper.
* `TERM_WALLPAPER` - URI where to find the file to use as wallpaper. BMP, PNG, and JPEG formats are supported.
* `TERM_WALLPAPER_STYLE` - The style which will be used to display the wallpaper image: `tiled`, `centered`, or `stretched`. Default is `stretched`.
* `TERM_BACKDROP` - When the background style is `centered`, this specifies the colour of the backdrop for parts of the screen not covered by the background image, in RRGGBB format.
@ -92,7 +98,7 @@ Editor control options.
*Locally assignable (non protocol specific)* keys are:
* `COMMENT` - An optional comment string that will be displayed by the bootloader on the menu when an entry is selected.
* `PROTOCOL` - The boot protocol that will be used to boot the kernel. Valid protocols are: `linux`, `limine`, `chainload`, `chainload_next`, `multiboot` (or `multiboot1`), and `multiboot2`.
* `CMDLINE` - The command line string to be passed to the kernel. Can be omitted.
* `CMDLINE` - The command line string to be passed to the kernel/executable. Can be omitted.
* `KERNEL_CMDLINE` - Alias of `CMDLINE`.
*Locally assignable (protocol specific)* keys are:
@ -145,6 +151,7 @@ Editor control options.
to the 1st module string entry that appear, and so on.
* `RESOLUTION` - The resolution to be used should the kernel request a graphical framebuffer. This setting takes the form of `<width>x<height>x<bpp>` and *overrides* any resolution requested by the kernel. If the resolution is not available, Limine will pick another one automatically. Omitting `<bpp>` will default to 32.
* `TEXTMODE` - If set to `yes`, prefer text mode. (BIOS only)
## URIs
@ -165,6 +172,10 @@ A resource can be one of the following:
* `fslabel` - The `root` is the name of the filesystem label of a partition.
* `tftp` - The `root` is the IP address of the tftp server to load the file from. If the root is left empty (`tftp:///...`) the file will be loaded from the server Limine booted from. This resource is only available when booting off PXE.
A URI can optionally be suffixed with a blake2b hash for the referenced file,
by appending a pound character (`#`) followed by the blake2b hash.
E.g.: `boot:///somemodule.gz#ca6914d2...446b470a`.
A URI can optionally be prefixed by a `$` character to indicate that the file
pointed to be the URI is a gzip-compressed payload to be uncompressed on the
fly. E.g.: `$boot:///somemodule.gz`.
@ -183,3 +194,9 @@ CMDLINE=something before ${MY_MACRO} something after
```
Macros must always be placed inside `${...}` where `...` is the arbitrary macro name.
### Built-in macros
Limine automatically defines these macros:
* `ARCH` - This built-in macro expands to the architecture of the machine. Possible values are: `x86-64`, `ia-32`, `aarch64`. In the case of IA-32, BIOS or UEFI, the macro will always expand to `x86-64` if the 64-bit extensions are available, else `ia-32`.

View File

@ -1,9 +1,17 @@
override MAKEFLAGS += -rR
override prefix := @prefix@
override exec_prefix := @exec_prefix@
override PACKAGE_TARNAME := @PACKAGE_TARNAME@
override ACBINDIR := @bindir@
override ACDATAROOTDIR := @datarootdir@
override ACINCLUDEDIR := @includedir@
override bindir := @bindir@
override datarootdir := @datarootdir@
override includedir := @includedir@
override datarootdir := @datarootdir@
override mandir := @mandir@
override docdir := @docdir@
override STRIP := @STRIP@
DESTDIR ?=
@ -28,15 +36,17 @@ define DEFAULT_VAR =
endif
endef
override BUILD_BIOS := @BUILD_BIOS@
override BUILD_UEFI_X86_64 := @BUILD_UEFI_X86_64@
override BUILD_UEFI_IA32 := @BUILD_UEFI_IA32@
override BUILD_UEFI_AARCH64 := @BUILD_UEFI_AARCH64@
override BUILD_CD_EFI := @BUILD_CD_EFI@
override BUILD_PXE := @BUILD_PXE@
override BUILD_CD := @BUILD_CD@
override BUILD_LIMINE_DEPLOY := @BUILD_LIMINE_DEPLOY@
override WERROR := @WERROR@
export WERROR
$(eval $(call DEFAULT_VAR,CC,@CC@))
override DEFAULT_CC := @CC@
$(eval $(call DEFAULT_VAR,CC,$(DEFAULT_CC)))
export CC
override MKDIR_P := @MKDIR_P@
@ -45,6 +55,12 @@ export MKDIR_P
override INSTALL := @INSTALL@
export INSTALL
override INSTALL_PROGRAM := @INSTALL_PROGRAM@
export INSTALL_PROGRAM
override INSTALL_DATA := @INSTALL_DATA@
export INSTALL_DATA
override GREP := @GREP@
export GREP
@ -54,22 +70,45 @@ export SED
override AWK := @AWK@
export AWK
CFLAGS ?= @CFLAGS@
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
LDFLAGS ?= @LDFLAGS@
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
CROSS_CFLAGS ?= @CROSS_CFLAGS@
export CROSS_CFLAGS
CROSS_LDFLAGS ?= @CROSS_LDFLAGS@
export CROSS_LDFLAGS
override WERROR_FLAG := @WERROR_FLAG@
export WERROR_FLAG
override DEFAULT_CFLAGS_FOR_TARGET := @CFLAGS_FOR_TARGET@
$(eval $(call DEFAULT_VAR,CFLAGS_FOR_TARGET,$(DEFAULT_CFLAGS_FOR_TARGET)))
export CFLAGS_FOR_TARGET
override DEFAULT_CPPFLAGS_FOR_TARGET := @CPPFLAGS_FOR_TARGET@
$(eval $(call DEFAULT_VAR,CPPFLAGS_FOR_TARGET,$(DEFAULT_CPPFLAGS_FOR_TARGET)))
export CPPFLAGS_FOR_TARGET
override DEFAULT_LDFLAGS_FOR_TARGET := @LDFLAGS_FOR_TARGET@
$(eval $(call DEFAULT_VAR,LDFLAGS_FOR_TARGET,$(DEFAULT_LDFLAGS_FOR_TARGET)))
export LDFLAGS_FOR_TARGET
override LIMINE_VERSION := @PACKAGE_VERSION@
override STAGE1_FILES := $(shell find '$(call SHESCAPE,$(SRCDIR))/stage1' -type f -name '*.asm')
.PHONY: all
all: limine-version @BUILD_UEFI_X86_64@ @BUILD_UEFI_IA32@ @BUILD_UEFI_AARCH64@ @BUILD_BIOS@
all: $(call MKESCAPE,$(BINDIR))/Makefile
$(MAKE) all1
.PHONY: all1
all1: limine-version limine-enroll-config $(BUILD_UEFI_X86_64) $(BUILD_UEFI_IA32) $(BUILD_UEFI_AARCH64) $(BUILD_BIOS)
$(MAKE) '$(call SHESCAPE,$(BINDIR))/limine-cd-efi.bin'
$(call MKESCAPE,$(BINDIR))/limine-hdd.h: $(call MKESCAPE,$(BINDIR))/limine-hdd.bin
@ -84,8 +123,12 @@ $(call MKESCAPE,$(BINDIR))/limine-version: $(call MKESCAPE,$(BINDIR))/Makefile $
$(SED) 's/@LIMINE_VERSION@/@PACKAGE_VERSION@/g' <'$(call SHESCAPE,$(SRCDIR))/host/limine-version.c' >'$(call SHESCAPE,$(BINDIR))/limine-version.c'
$(MAKE) -C '$(call SHESCAPE,$(BINDIR))' limine-version
$(call MKESCAPE,$(BINDIR))/limine-enroll-config: $(call MKESCAPE,$(BINDIR))/Makefile $(call MKESCAPE,$(SRCDIR))/host/limine-enroll-config.c
cp '$(call SHESCAPE,$(SRCDIR))/host/limine-enroll-config.c' '$(call SHESCAPE,$(BINDIR))/'
$(MAKE) -C '$(call SHESCAPE,$(BINDIR))' limine-enroll-config
$(call MKESCAPE,$(BINDIR))/Makefile: $(call MKESCAPE,$(SRCDIR))/host/Makefile $(call MKESCAPE,$(SRCDIR))/host/.gitignore
$(MKDIR_P) '$(call SHESCAPE,$(BINDIR))'
mkdir -p '$(call SHESCAPE,$(BINDIR))'
cp '$(call SHESCAPE,$(SRCDIR))/host/Makefile' '$(call SHESCAPE,$(SRCDIR))/host/.gitignore' '$(call SHESCAPE,$(BINDIR))/'
.PHONY: limine-deploy
@ -96,51 +139,92 @@ limine-deploy:
limine-version:
$(MAKE) '$(call SHESCAPE,$(BINDIR))/limine-version'
.PHONY: limine-enroll-config
limine-enroll-config:
$(MAKE) '$(call SHESCAPE,$(BINDIR))/limine-enroll-config'
.PHONY: clean
clean: limine-bios-clean limine-uefi-ia32-clean limine-uefi-x86-64-clean limine-uefi-aarch64-clean
rm -rf '$(call SHESCAPE,$(BINDIR))' '$(call SHESCAPE,$(BUILDDIR))/stage1.stamp'
.PHONY: install-data
install-data: all
$(INSTALL) -d '$(call SHESCAPE,$(DESTDIR)$(ACDATAROOTDIR))'
$(INSTALL) -d '$(call SHESCAPE,$(DESTDIR)$(ACDATAROOTDIR))/limine'
$(INSTALL) -m 644 '$(call SHESCAPE,$(BINDIR))/limine.sys' '$(call SHESCAPE,$(DESTDIR)$(ACDATAROOTDIR))/limine/' || true
$(INSTALL) -m 644 '$(call SHESCAPE,$(BINDIR))/limine-cd.bin' '$(call SHESCAPE,$(DESTDIR)$(ACDATAROOTDIR))/limine/' || true
$(INSTALL) -m 644 '$(call SHESCAPE,$(BINDIR))/limine-cd-efi.bin' '$(call SHESCAPE,$(DESTDIR)$(ACDATAROOTDIR))/limine/' || true
$(INSTALL) -m 644 '$(call SHESCAPE,$(BINDIR))/limine-pxe.bin' '$(call SHESCAPE,$(DESTDIR)$(ACDATAROOTDIR))/limine/' || true
$(INSTALL) -m 644 '$(call SHESCAPE,$(BINDIR))/BOOTAA64.EFI' '$(call SHESCAPE,$(DESTDIR)$(ACDATAROOTDIR))/limine/' || true
$(INSTALL) -m 644 '$(call SHESCAPE,$(BINDIR))/BOOTX64.EFI' '$(call SHESCAPE,$(DESTDIR)$(ACDATAROOTDIR))/limine/' || true
$(INSTALL) -m 644 '$(call SHESCAPE,$(BINDIR))/BOOTIA32.EFI' '$(call SHESCAPE,$(DESTDIR)$(ACDATAROOTDIR))/limine/' || true
$(INSTALL) -d '$(call SHESCAPE,$(DESTDIR)$(ACINCLUDEDIR))'
$(INSTALL) -m 644 '$(call SHESCAPE,$(SRCDIR))/limine.h' '$(call SHESCAPE,$(DESTDIR)$(ACINCLUDEDIR))/'
.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))/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))/'
$(INSTALL_DATA) '$(call SHESCAPE,$(SRCDIR))/README.md' '$(call SHESCAPE,$(DESTDIR)$(docdir))/'
$(INSTALL) -d '$(call SHESCAPE,$(DESTDIR)$(mandir))/man1'
$(INSTALL_DATA) '$(call SHESCAPE,$(BUILDDIR))/man/man1/limine-version.1' '$(call SHESCAPE,$(DESTDIR)$(mandir))/man1/'
ifneq ($(BUILD_LIMINE_DEPLOY),no)
$(INSTALL_DATA) '$(call SHESCAPE,$(BUILDDIR))/man/man1/limine-deploy.1' '$(call SHESCAPE,$(DESTDIR)$(mandir))/man1/'
endif
$(INSTALL_DATA) '$(call SHESCAPE,$(BUILDDIR))/man/man1/limine-enroll-config.1' '$(call SHESCAPE,$(DESTDIR)$(mandir))/man1/'
$(INSTALL) -d '$(call SHESCAPE,$(DESTDIR)$(datarootdir))'
$(INSTALL) -d '$(call SHESCAPE,$(DESTDIR)$(datarootdir))/limine'
ifeq ($(BUILD_BIOS),limine-bios)
$(INSTALL_DATA) '$(call SHESCAPE,$(BINDIR))/limine.sys' '$(call SHESCAPE,$(DESTDIR)$(datarootdir))/limine/'
endif
ifneq ($(BUILD_CD),no)
$(INSTALL_DATA) '$(call SHESCAPE,$(BINDIR))/limine-cd.bin' '$(call SHESCAPE,$(DESTDIR)$(datarootdir))/limine/'
endif
ifneq ($(BUILD_CD_EFI),no)
$(INSTALL_DATA) '$(call SHESCAPE,$(BINDIR))/limine-cd-efi.bin' '$(call SHESCAPE,$(DESTDIR)$(datarootdir))/limine/'
endif
ifneq ($(BUILD_PXE),no)
$(INSTALL_DATA) '$(call SHESCAPE,$(BINDIR))/limine-pxe.bin' '$(call SHESCAPE,$(DESTDIR)$(datarootdir))/limine/'
endif
ifeq ($(BUILD_UEFI_AARCH64),limine-uefi-aarch64)
$(INSTALL_DATA) '$(call SHESCAPE,$(BINDIR))/BOOTAA64.EFI' '$(call SHESCAPE,$(DESTDIR)$(datarootdir))/limine/'
endif
ifeq ($(BUILD_UEFI_X86_64),limine-uefi-x86-64)
$(INSTALL_DATA) '$(call SHESCAPE,$(BINDIR))/BOOTX64.EFI' '$(call SHESCAPE,$(DESTDIR)$(datarootdir))/limine/'
endif
ifeq ($(BUILD_UEFI_IA32),limine-uefi-ia32)
$(INSTALL_DATA) '$(call SHESCAPE,$(BINDIR))/BOOTIA32.EFI' '$(call SHESCAPE,$(DESTDIR)$(datarootdir))/limine/'
endif
$(INSTALL) -d '$(call SHESCAPE,$(DESTDIR)$(includedir))'
$(INSTALL_DATA) '$(call SHESCAPE,$(SRCDIR))/limine.h' '$(call SHESCAPE,$(DESTDIR)$(includedir))/'
$(INSTALL) -d '$(call SHESCAPE,$(DESTDIR)$(bindir))'
$(INSTALL_PROGRAM) '$(call SHESCAPE,$(BINDIR))/limine-version' '$(call SHESCAPE,$(DESTDIR)$(bindir))/'
$(INSTALL_PROGRAM) '$(call SHESCAPE,$(BINDIR))/limine-enroll-config' '$(call SHESCAPE,$(DESTDIR)$(bindir))/'
ifneq ($(BUILD_LIMINE_DEPLOY),no)
$(INSTALL_PROGRAM) '$(call SHESCAPE,$(BINDIR))/limine-deploy' '$(call SHESCAPE,$(DESTDIR)$(bindir))/'
endif
.PHONY: install-strip
install-strip: install-data
$(INSTALL) -d '$(call SHESCAPE,$(DESTDIR)$(ACBINDIR))'
$(INSTALL) -s '$(call SHESCAPE,$(BINDIR))/limine-version' '$(call SHESCAPE,$(DESTDIR)$(ACBINDIR))/'
$(INSTALL) -s '$(call SHESCAPE,$(BINDIR))/limine-deploy' '$(call SHESCAPE,$(DESTDIR)$(ACBINDIR))/' || true
.PHONY: install
install: install-data
$(INSTALL) -d '$(call SHESCAPE,$(DESTDIR)$(ACBINDIR))'
$(INSTALL) '$(call SHESCAPE,$(BINDIR))/limine-version' '$(call SHESCAPE,$(DESTDIR)$(ACBINDIR))/'
$(INSTALL) '$(call SHESCAPE,$(BINDIR))/limine-deploy' '$(call SHESCAPE,$(DESTDIR)$(ACBINDIR))/' || true
install-strip: install
$(STRIP) '$(call SHESCAPE,$(DESTDIR)$(bindir))/limine-version'
$(STRIP) '$(call SHESCAPE,$(DESTDIR)$(bindir))/limine-enroll-config'
ifneq ($(BUILD_LIMINE_DEPLOY),no)
$(STRIP) '$(call SHESCAPE,$(DESTDIR)$(bindir))/limine-deploy'
endif
.PHONY: uninstall
uninstall:
rm -f '$(call SHESCAPE,$(DESTDIR)$(ACBINDIR))/limine-version'
rm -f '$(call SHESCAPE,$(DESTDIR)$(ACBINDIR))/limine-deploy'
rm -rf '$(call SHESCAPE,$(DESTDIR)$(ACDATAROOTDIR))/limine'
rm -f '$(call SHESCAPE,$(DESTDIR)$(ACINCLUDEDIR))/limine.h'
rm -f '$(call SHESCAPE,$(DESTDIR)$(docdir))/LICENSE'
rm -f '$(call SHESCAPE,$(DESTDIR)$(docdir))/CONFIG.md'
rm -f '$(call SHESCAPE,$(DESTDIR)$(docdir))/PROTOCOL.md'
rm -f '$(call SHESCAPE,$(DESTDIR)$(docdir))/PHILOSOPHY.md'
rm -f '$(call SHESCAPE,$(DESTDIR)$(docdir))/README.md'
rm -f '$(call SHESCAPE,$(DESTDIR)$(mandir))/man1/limine-version.1'
rm -f '$(call SHESCAPE,$(DESTDIR)$(mandir))/man1/limine-deploy.1'
rm -f '$(call SHESCAPE,$(DESTDIR)$(mandir))/man1/limine-enroll-config.1'
rm -f '$(call SHESCAPE,$(DESTDIR)$(bindir))/limine-version'
rm -f '$(call SHESCAPE,$(DESTDIR)$(bindir))/limine-enroll-config'
rm -f '$(call SHESCAPE,$(DESTDIR)$(bindir))/limine-deploy'
rm -rf '$(call SHESCAPE,$(DESTDIR)$(datarootdir))/limine'
rm -f '$(call SHESCAPE,$(DESTDIR)$(includedir))/limine.h'
$(call MKESCAPE,$(BUILDDIR))/stage1.stamp: $(STAGE1_FILES) $(call MKESCAPE,$(BUILDDIR))/decompressor-build/decompressor.bin $(call MKESCAPE,$(BUILDDIR))/common-bios/stage2.bin.gz
$(MKDIR_P) '$(call SHESCAPE,$(BINDIR))'
cd '$(call SHESCAPE,$(SRCDIR))/stage1/hdd' && nasm bootsect.asm @WERROR@ -fbin -DBUILDDIR="'"'$(call NASMESCAPE,$(BUILDDIR))'"'" -o '$(call SHESCAPE,$(BINDIR))/limine-hdd.bin'
cd '$(call SHESCAPE,$(SRCDIR))/stage1/hdd' && nasm bootsect.asm -Wall $(WERROR_FLAG) -fbin -DBUILDDIR="'"'$(call NASMESCAPE,$(BUILDDIR))'"'" -o '$(call SHESCAPE,$(BINDIR))/limine-hdd.bin'
ifneq ($(BUILD_CD),no)
cd '$(call SHESCAPE,$(SRCDIR))/stage1/cd' && nasm bootsect.asm @WERROR@ -fbin -DBUILDDIR="'"'$(call NASMESCAPE,$(BUILDDIR))'"'" -o '$(call SHESCAPE,$(BINDIR))/limine-cd.bin'
cd '$(call SHESCAPE,$(SRCDIR))/stage1/cd' && nasm bootsect.asm -Wall $(WERROR_FLAG) -fbin -DBUILDDIR="'"'$(call NASMESCAPE,$(BUILDDIR))'"'" -o '$(call SHESCAPE,$(BINDIR))/limine-cd.bin'
endif
ifneq ($(BUILD_PXE),no)
cd '$(call SHESCAPE,$(SRCDIR))/stage1/pxe' && nasm bootsect.asm @WERROR@ -fbin -DBUILDDIR="'"'$(call NASMESCAPE,$(BUILDDIR))'"'" -o '$(call SHESCAPE,$(BINDIR))/limine-pxe.bin'
cd '$(call SHESCAPE,$(SRCDIR))/stage1/pxe' && nasm bootsect.asm -Wall $(WERROR_FLAG) -fbin -DBUILDDIR="'"'$(call NASMESCAPE,$(BUILDDIR))'"'" -o '$(call SHESCAPE,$(BINDIR))/limine-pxe.bin'
endif
cp '$(call SHESCAPE,$(BUILDDIR))/common-bios/limine.sys' '$(call SHESCAPE,$(BINDIR))/'
touch '$(call SHESCAPE,$(BUILDDIR))/stage1.stamp'
@ -152,7 +236,7 @@ ifneq ($(BUILD_LIMINE_DEPLOY),no)
$(MAKE) limine-deploy
endif
$(call MKESCAPE,$(BINDIR))/limine-cd-efi.bin: $(if @BUILD_UEFI_IA32@, $(call MKESCAPE,$(BUILDDIR))/common-uefi-ia32/BOOTIA32.EFI) $(if @BUILD_UEFI_X86_64@, $(call MKESCAPE,$(BUILDDIR))/common-uefi-x86-64/BOOTX64.EFI) $(if @BUILD_UEFI_AARCH64@, $(call MKESCAPE,$(BUILDDIR))/common-uefi-aarch64/BOOTAA64.EFI)
$(call MKESCAPE,$(BINDIR))/limine-cd-efi.bin: $(if $(BUILD_UEFI_IA32),$(call MKESCAPE,$(BUILDDIR))/common-uefi-ia32/BOOTIA32.EFI) $(if $(BUILD_UEFI_X86_64),$(call MKESCAPE,$(BUILDDIR))/common-uefi-x86-64/BOOTX64.EFI) $(if $(BUILD_UEFI_AARCH64),$(call MKESCAPE,$(BUILDDIR))/common-uefi-aarch64/BOOTAA64.EFI)
ifneq ($(BUILD_CD_EFI),no)
$(MKDIR_P) '$(call SHESCAPE,$(BINDIR))'
rm -f '$(call SHESCAPE,$(BINDIR))/limine-cd-efi.bin'
@ -219,10 +303,10 @@ dist:
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)" && ./bootstrap
rm -rf '$(call SHESCAPE,$(BUILDDIR))'/"limine-$(LIMINE_VERSION)/common/flanterm/.git"
rm -rf '$(call SHESCAPE,$(BUILDDIR))'/"limine-$(LIMINE_VERSION)/freestanding-headers/.git"
rm -rf '$(call SHESCAPE,$(BUILDDIR))'/"limine-$(LIMINE_VERSION)/libgcc-binaries/.git"
rm -rf '$(call SHESCAPE,$(BUILDDIR))'/"limine-$(LIMINE_VERSION)/libgcc-binaries/.gitignore"
libgcc_needed="i686 x86_64-no-red-zone aarch64"; \
for f in $$libgcc_needed; do \
mv '$(call SHESCAPE,$(BUILDDIR))'/"limine-$(LIMINE_VERSION)/libgcc-binaries/libgcc-$$f.a" '$(call SHESCAPE,$(BUILDDIR))'/"limine-$(LIMINE_VERSION)/libgcc-binaries/libgcc-$$f.a.save"; \
@ -231,17 +315,14 @@ dist:
for f in $$libgcc_needed; do \
mv '$(call SHESCAPE,$(BUILDDIR))'/"limine-$(LIMINE_VERSION)/libgcc-binaries/libgcc-$$f.a.save" '$(call SHESCAPE,$(BUILDDIR))'/"limine-$(LIMINE_VERSION)/libgcc-binaries/libgcc-$$f.a"; \
done
rm -rf '$(call SHESCAPE,$(BUILDDIR))'/"limine-$(LIMINE_VERSION)/limine-efi/.git"
rm -rf '$(call SHESCAPE,$(BUILDDIR))'/"limine-$(LIMINE_VERSION)/limine-efi/.gitignore"
rm -rf '$(call SHESCAPE,$(BUILDDIR))'/"limine-$(LIMINE_VERSION)/cross-detect/.git"
rm -rf '$(call SHESCAPE,$(BUILDDIR))'/"limine-$(LIMINE_VERSION)/cross-detect/.gitignore"
rm -rf '$(call SHESCAPE,$(BUILDDIR))'/"limine-$(LIMINE_VERSION)/.git"
rm -rf '$(call SHESCAPE,$(BUILDDIR))'/"limine-$(LIMINE_VERSION)/.gitignore"
rm -rf '$(call SHESCAPE,$(BUILDDIR))'/"limine-$(LIMINE_VERSION)/.github"
rm -rf '$(call SHESCAPE,$(BUILDDIR))'/"limine-$(LIMINE_VERSION)/autom4te.cache"
rm -rf '$(call SHESCAPE,$(BUILDDIR))'/"limine-$(LIMINE_VERSION)/cross-detect/autom4te.cache"
rm -rf '$(call SHESCAPE,$(BUILDDIR))'/"limine-$(LIMINE_VERSION)/test"
rm -rf '$(call SHESCAPE,$(BUILDDIR))'/"limine-$(LIMINE_VERSION)/test.mk"
rm -rf '$(call SHESCAPE,$(BUILDDIR))'/"limine-$(LIMINE_VERSION)/screenshot.png"
rm -rf '$(call SHESCAPE,$(BUILDDIR))'/"limine-$(LIMINE_VERSION)/bochsrc"
echo "$(LIMINE_VERSION)" > '$(call SHESCAPE,$(BUILDDIR))'/"limine-$(LIMINE_VERSION)/version"
@ -251,16 +332,16 @@ dist:
.PHONY: distclean
distclean: clean
rm -rf ovmf* config.log config.status GNUmakefile config.h cross-files
rm -rf ovmf* config.log config.status GNUmakefile config.h toolchain-files man/man1/limine-version.1 man/man1/limine-deploy.1 man/man1/limine-enroll-config.1
.PHONY: maintainer-clean
maintainer-clean: distclean
cd '$(call SHESCAPE,$(SRCDIR))' && rm -rf freestanding-headers libgcc-binaries limine-efi cross-detect 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 build-aux *'~' autom4te.cache aclocal.m4 *.tar.xz *.tar.gz
.PHONY: common-uefi-x86-64
common-uefi-x86-64:
$(MAKE) -C '$(call SHESCAPE,$(SRCDIR))/common' all \
CROSS_FILE='$(call SHESCAPE,$(BUILDDIR))/cross-files/x86_64-toolchain.mk' \
TOOLCHAIN_FILE='$(call SHESCAPE,$(BUILDDIR))/toolchain-files/uefi-x86_64-toolchain.mk' \
TARGET=uefi-x86-64 \
BUILDDIR='$(call SHESCAPE,$(BUILDDIR))/common-uefi-x86-64'
@ -271,7 +352,7 @@ common-uefi-x86-64-clean:
.PHONY: common-uefi-aarch64
common-uefi-aarch64:
$(MAKE) -C '$(call SHESCAPE,$(SRCDIR))/common' all \
CROSS_FILE='$(call SHESCAPE,$(BUILDDIR))/cross-files/aarch64-toolchain.mk' \
TOOLCHAIN_FILE='$(call SHESCAPE,$(BUILDDIR))/toolchain-files/uefi-aarch64-toolchain.mk' \
TARGET=uefi-aarch64 \
BUILDDIR='$(call SHESCAPE,$(BUILDDIR))/common-uefi-aarch64'
@ -282,7 +363,7 @@ common-uefi-aarch64-clean:
.PHONY: common-uefi-ia32
common-uefi-ia32:
$(MAKE) -C '$(call SHESCAPE,$(SRCDIR))/common' all \
CROSS_FILE='$(call SHESCAPE,$(BUILDDIR))/cross-files/i686-toolchain.mk' \
TOOLCHAIN_FILE='$(call SHESCAPE,$(BUILDDIR))/toolchain-files/uefi-i686-toolchain.mk' \
TARGET=uefi-ia32 \
BUILDDIR='$(call SHESCAPE,$(BUILDDIR))/common-uefi-ia32'
@ -293,7 +374,7 @@ common-uefi-ia32-clean:
.PHONY: common-bios
common-bios:
$(MAKE) -C '$(call SHESCAPE,$(SRCDIR))/common' all \
CROSS_FILE='$(call SHESCAPE,$(BUILDDIR))/cross-files/i686-toolchain.mk' \
TOOLCHAIN_FILE='$(call SHESCAPE,$(BUILDDIR))/toolchain-files/bios-i686-toolchain.mk' \
TARGET=bios \
BUILDDIR='$(call SHESCAPE,$(BUILDDIR))/common-bios'
@ -304,271 +385,11 @@ common-bios-clean:
.PHONY: decompressor
decompressor:
$(MAKE) -C '$(call SHESCAPE,$(SRCDIR))/decompressor' all \
CROSS_FILE='$(call SHESCAPE,$(BUILDDIR))/cross-files/i686-toolchain.mk' \
TOOLCHAIN_FILE='$(call SHESCAPE,$(BUILDDIR))/toolchain-files/bios-i686-toolchain.mk' \
BUILDDIR='$(call SHESCAPE,$(BUILDDIR))/decompressor-build'
.PHONY: decompressor-clean
decompressor-clean:
rm -rf '$(call SHESCAPE,$(BUILDDIR))/decompressor-build'
.PHONY: test-clean
test-clean:
$(MAKE) -C test clean
rm -rf test_image test.hdd test.iso
ovmf-x64:
$(MKDIR_P) ovmf-x64
cd ovmf-x64 && curl -o OVMF-X64.zip https://efi.akeo.ie/OVMF/OVMF-X64.zip && 7z x OVMF-X64.zip
ovmf-aa64:
mkdir -p ovmf-aa64
cd ovmf-aa64 && curl -o OVMF-AA64.zip https://efi.akeo.ie/OVMF/OVMF-AA64.zip && 7z x OVMF-AA64.zip
ovmf-ia32:
$(MKDIR_P) ovmf-ia32
cd ovmf-ia32 && curl -o OVMF-IA32.zip https://efi.akeo.ie/OVMF/OVMF-IA32.zip && 7z x OVMF-IA32.zip
.PHONY: test.hdd
test.hdd:
rm -f test.hdd
dd if=/dev/zero bs=1M count=0 seek=64 of=test.hdd
parted -s test.hdd mklabel gpt
parted -s test.hdd mkpart primary 2048s 100%
.PHONY: mbrtest.hdd
mbrtest.hdd:
rm -f mbrtest.hdd
dd if=/dev/zero bs=1M count=0 seek=64 of=mbrtest.hdd
echo -e "o\nn\np\n1\n2048\n\nt\n6\na\nw\n" | fdisk mbrtest.hdd -H 16 -S 63
.PHONY: ext2-test
ext2-test:
$(MAKE) test-clean
$(MAKE) test.hdd
$(MAKE) limine-bios
$(MAKE) limine-deploy
$(MAKE) -C test CROSS_FILE='$(call SHESCAPE,$(BUILDDIR))/cross-files/x86_64-toolchain.mk'
rm -rf test_image/
mkdir test_image
sudo losetup -Pf --show test.hdd > loopback_dev
sudo partprobe `cat loopback_dev`
sudo mkfs.ext2 `cat loopback_dev`p1
sudo mount `cat loopback_dev`p1 test_image
sudo mkdir test_image/boot
sudo cp -rv $(BINDIR)/* test_image/boot/
sudo cp -rv test/* test_image/boot/
sync
sudo umount test_image/
sudo losetup -d `cat loopback_dev`
rm -rf test_image loopback_dev
$(BINDIR)/limine-deploy test.hdd
qemu-system-x86_64 -net none -smp 4 -hda test.hdd -debugcon stdio
.PHONY: fat12-test
fat12-test:
$(MAKE) test-clean
$(MAKE) test.hdd
$(MAKE) limine-bios
$(MAKE) limine-deploy
$(MAKE) -C test CROSS_FILE='$(call SHESCAPE,$(BUILDDIR))/cross-files/x86_64-toolchain.mk'
rm -rf test_image/
mkdir test_image
sudo losetup -Pf --show test.hdd > loopback_dev
sudo partprobe `cat loopback_dev`
sudo mkfs.fat -F 12 `cat loopback_dev`p1
sudo mount `cat loopback_dev`p1 test_image
sudo mkdir test_image/boot
sudo cp -rv $(BINDIR)/* test_image/boot/
sudo cp -rv test/* test_image/boot/
sync
sudo umount test_image/
sudo losetup -d `cat loopback_dev`
rm -rf test_image loopback_dev
$(BINDIR)/limine-deploy test.hdd
qemu-system-x86_64 -net none -smp 4 -hda test.hdd -debugcon stdio
.PHONY: fat16-test
fat16-test:
$(MAKE) test-clean
$(MAKE) test.hdd
$(MAKE) limine-bios
$(MAKE) limine-deploy
$(MAKE) -C test CROSS_FILE='$(call SHESCAPE,$(BUILDDIR))/cross-files/x86_64-toolchain.mk'
rm -rf test_image/
mkdir test_image
sudo losetup -Pf --show test.hdd > loopback_dev
sudo partprobe `cat loopback_dev`
sudo mkfs.fat -F 16 `cat loopback_dev`p1
sudo mount `cat loopback_dev`p1 test_image
sudo mkdir test_image/boot
sudo cp -rv $(BINDIR)/* test_image/boot/
sudo cp -rv test/* test_image/boot/
sync
sudo umount test_image/
sudo losetup -d `cat loopback_dev`
rm -rf test_image loopback_dev
$(BINDIR)/limine-deploy test.hdd
qemu-system-x86_64 -net none -smp 4 -hda test.hdd -debugcon stdio
.PHONY: legacy-fat16-test
legacy-fat16-test:
$(MAKE) test-clean
$(MAKE) mbrtest.hdd
fdisk -l mbrtest.hdd
$(MAKE) limine-bios
$(MAKE) limine-deploy
$(MAKE) -C test CROSS_FILE='$(call SHESCAPE,$(BUILDDIR))/cross-files/x86_64-toolchain.mk'
rm -rf test_image/
mkdir test_image
sudo losetup -Pf --show mbrtest.hdd > loopback_dev
sudo partprobe `cat loopback_dev`
sudo mkfs.fat -F 16 `cat loopback_dev`p1
sudo mount `cat loopback_dev`p1 test_image
sudo mkdir test_image/boot
sudo cp -rv $(BINDIR)/* test_image/boot/
sudo cp -rv test/* test_image/boot/
sync
sudo umount test_image/
sudo losetup -d `cat loopback_dev`
rm -rf test_image loopback_dev
$(BINDIR)/limine-deploy mbrtest.hdd
qemu-system-i386 -cpu pentium2 -m 16M -M isapc -net none -hda mbrtest.hdd -debugcon stdio
.PHONY: fat32-test
fat32-test:
$(MAKE) test-clean
$(MAKE) test.hdd
$(MAKE) limine-bios
$(MAKE) limine-deploy
$(MAKE) -C test CROSS_FILE='$(call SHESCAPE,$(BUILDDIR))/cross-files/x86_64-toolchain.mk'
rm -rf test_image/
mkdir test_image
sudo losetup -Pf --show test.hdd > loopback_dev
sudo partprobe `cat loopback_dev`
sudo mkfs.fat -F 32 `cat loopback_dev`p1
sudo mount `cat loopback_dev`p1 test_image
sudo mkdir test_image/boot
sudo cp -rv $(BINDIR)/* test_image/boot/
sudo cp -rv test/* test_image/boot/
sync
sudo umount test_image/
sudo losetup -d `cat loopback_dev`
rm -rf test_image loopback_dev
$(BINDIR)/limine-deploy test.hdd
qemu-system-x86_64 -net none -smp 4 -hda test.hdd -debugcon stdio
.PHONY: iso9660-test
iso9660-test:
$(MAKE) test-clean
$(MAKE) test.hdd
$(MAKE) limine-bios
$(MAKE) -C test CROSS_FILE='$(call SHESCAPE,$(BUILDDIR))/cross-files/x86_64-toolchain.mk'
rm -rf test_image/
$(MKDIR_P) test_image/boot
sudo cp -rv $(BINDIR)/* test_image/boot/
sudo cp -rv test/* test_image/boot/
xorriso -as mkisofs -b boot/limine-cd.bin -no-emul-boot -boot-load-size 4 -boot-info-table test_image/ -o test.iso
qemu-system-x86_64 -net none -smp 4 -cdrom test.iso -debugcon stdio
.PHONY: full-hybrid-test
full-hybrid-test:
$(MAKE) ovmf-x64
$(MAKE) ovmf-ia32
$(MAKE) test-clean
$(MAKE) all
$(MAKE) -C test CROSS_FILE='$(call SHESCAPE,$(BUILDDIR))/cross-files/x86_64-toolchain.mk'
rm -rf test_image/
$(MKDIR_P) test_image/boot
sudo cp -rv $(BINDIR)/* test_image/boot/
sudo cp -rv test/* test_image/boot/
xorriso -as mkisofs -b boot/limine-cd.bin -no-emul-boot -boot-load-size 4 -boot-info-table --efi-boot boot/limine-cd-efi.bin -efi-boot-part --efi-boot-image --protective-msdos-label test_image/ -o test.iso
$(BINDIR)/limine-deploy test.iso
qemu-system-x86_64 -m 512M -M q35 -bios ovmf-x64/OVMF.fd -net none -smp 4 -cdrom test.iso -debugcon stdio
qemu-system-x86_64 -m 512M -M q35 -bios ovmf-x64/OVMF.fd -net none -smp 4 -hda test.iso -debugcon stdio
qemu-system-x86_64 -m 512M -M q35 -bios ovmf-ia32/OVMF.fd -net none -smp 4 -cdrom test.iso -debugcon stdio
qemu-system-x86_64 -m 512M -M q35 -bios ovmf-ia32/OVMF.fd -net none -smp 4 -hda test.iso -debugcon stdio
qemu-system-x86_64 -m 512M -M q35 -net none -smp 4 -cdrom test.iso -debugcon stdio
qemu-system-x86_64 -m 512M -M q35 -net none -smp 4 -hda test.iso -debugcon stdio
.PHONY: pxe-test
pxe-test:
$(MAKE) test-clean
$(MAKE) limine-bios
$(MAKE) -C test CROSS_FILE='$(call SHESCAPE,$(BUILDDIR))/cross-files/x86_64-toolchain.mk'
rm -rf test_image/
$(MKDIR_P) test_image/boot
sudo cp -rv $(BINDIR)/* test_image/boot/
sudo cp -rv test/* test_image/boot/
qemu-system-x86_64 -smp 4 -netdev user,id=n0,tftp=./test_image,bootfile=boot/limine-pxe.bin -device rtl8139,netdev=n0,mac=00:00:00:11:11:11 -debugcon stdio
.PHONY: uefi-x86-64-test
uefi-x86-64-test:
$(MAKE) ovmf-x64
$(MAKE) test-clean
$(MAKE) test.hdd
$(MAKE) limine-uefi-x86-64
$(MAKE) -C test CROSS_FILE='$(call SHESCAPE,$(BUILDDIR))/cross-files/x86_64-toolchain.mk'
rm -rf test_image/
mkdir test_image
sudo losetup -Pf --show test.hdd > loopback_dev
sudo partprobe `cat loopback_dev`
sudo mkfs.fat -F 32 `cat loopback_dev`p1
sudo mount `cat loopback_dev`p1 test_image
sudo mkdir test_image/boot
sudo cp -rv $(BINDIR)/* test_image/boot/
sudo cp -rv test/* test_image/boot/
sudo $(MKDIR_P) test_image/EFI/BOOT
sudo cp $(BINDIR)/BOOTX64.EFI test_image/EFI/BOOT/
sync
sudo umount test_image/
sudo losetup -d `cat loopback_dev`
rm -rf test_image loopback_dev
qemu-system-x86_64 -m 512M -M q35 -bios ovmf-x64/OVMF.fd -net none -smp 4 -hda test.hdd -debugcon stdio
.PHONY: uefi-aa64-test
uefi-aa64-test:
$(MAKE) ovmf-aa64
$(MAKE) test-clean
$(MAKE) test.hdd
$(MAKE) limine-uefi-aarch64
$(MAKE) -C test CROSS_FILE='$(call SHESCAPE,$(BUILDDIR))/cross-files/aarch64-toolchain.mk'
rm -rf test_image/
mkdir test_image
sudo losetup -Pf --show test.hdd > loopback_dev
sudo partprobe `cat loopback_dev`
sudo mkfs.fat -F 32 `cat loopback_dev`p1
sudo mount `cat loopback_dev`p1 test_image
sudo mkdir test_image/boot
sudo cp -rv $(BINDIR)/* test_image/boot/
sudo cp -rv test/* test_image/boot/
sudo $(MKDIR_P) test_image/EFI/BOOT
sudo cp $(BINDIR)/BOOTAA64.EFI test_image/EFI/BOOT/
sync
sudo umount test_image/
sudo losetup -d `cat loopback_dev`
rm -rf test_image loopback_dev
qemu-system-aarch64 -m 512M -M virt -cpu cortex-a72 -bios ovmf-aa64/OVMF.fd -net none -smp 4 -device ramfb -device qemu-xhci -device usb-kbd -hda test.hdd -serial stdio
.PHONY: uefi-ia32-test
uefi-ia32-test:
$(MAKE) ovmf-ia32
$(MAKE) test-clean
$(MAKE) test.hdd
$(MAKE) limine-uefi-ia32
$(MAKE) -C test CROSS_FILE='$(call SHESCAPE,$(BUILDDIR))/cross-files/x86_64-toolchain.mk'
rm -rf test_image/
mkdir test_image
sudo losetup -Pf --show test.hdd > loopback_dev
sudo partprobe `cat loopback_dev`
sudo mkfs.fat -F 32 `cat loopback_dev`p1
sudo mount `cat loopback_dev`p1 test_image
sudo mkdir test_image/boot
sudo cp -rv $(BINDIR)/* test_image/boot/
sudo cp -rv test/* test_image/boot/
sudo $(MKDIR_P) test_image/EFI/BOOT
sudo cp $(BINDIR)/BOOTIA32.EFI test_image/EFI/BOOT/
sync
sudo umount test_image/
sudo losetup -d `cat loopback_dev`
rm -rf test_image loopback_dev
qemu-system-x86_64 -m 512M -M q35 -bios ovmf-ia32/OVMF.fd -net none -smp 4 -hda test.hdd -debugcon stdio
-include test.mk

View File

@ -1,4 +1,4 @@
Copyright 2019, 2020, 2021, 2022 mintsuki and contributors.
Copyright (C) 2019-2023 mintsuki and contributors.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

31
PHILOSOPHY.md Normal file
View File

@ -0,0 +1,31 @@
# Limine's Design Philosophy
### Why not support filesystem X or feature Y? (eg: LUKS, LVM)
The idea with Limine is to remove the responsibility of parsing filesystems and formats, aside from the bare minimum necessities (eg: FAT*, ISO9660),
from the bootloader itself.
It is a needless duplication of efforts to have bootloaders support all possible filesystems and formats, and it leads to massive, bloated
bootloaders as a result (eg: GRUB2).
What is needed is to simply make sure the bootloader is capable of reading its own files, configuration, and be able to load kernel/module files
from disk. The kernel should be responsible for parsing everything else as it sees fit.
### What about LUKS? What about security? Encrypt the kernel!
Simply put, this is unnecessary. Putting the kernel/modules in a readable FAT32 partition and letting Limine know about their BLAKE2B checksums
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 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?
This is explicitly against the philosophy, but it is a pragmatic compromise since a lot of Linux distros and setups expect it to "work that way".
### But I don't want to have a separate FAT boot partition! I don't want it!!!
Well tough luck. It is `$year_following_2012` now and most PCs are equipped with UEFI and simply won't boot without a FAT EFI system partition
anyways. It is not unreasonable to share the EFI system partition with the OS's /boot and store kernels and initramfses there.

View File

@ -87,20 +87,21 @@ 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. In order to determine
No specific physical memory placement is guaranteed, except that the kernel
is guaranteed to be physically contiguous. In order to determine
where the kernel is loaded in physical memory, see the Kernel Address feature
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
@ -111,9 +112,60 @@ 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,
@ -122,7 +174,7 @@ 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.
The GDT register is loaded to point to a GDT, in bootloader-reserved memory,
The GDT register is loaded to point to a GDT, in bootloader-reclaimable memory,
with at least the following entries, starting at offset 0:
- Null descriptor
@ -145,11 +197,12 @@ 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.
`rsp` is set to point to a stack, in bootloader-reserved memory, which is
`rsp` 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). An invalid return address of 0 is pushed
to the stack before jumping to the kernel.
@ -162,27 +215,25 @@ All other general purpose registers are set to 0.
unless the an 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.
@ -190,11 +241,40 @@ The used translation granule size is undefined.
If booted by EFI/UEFI, boot services are exited.
`SP` is set to point to a stack, in bootloader-reserved memory, which is
`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).
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.
`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 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.
If booted by EFI/UEFI, boot services are exited.
`stvec` is in an undefined state. `sstatus.SIE` and `sie` are set to 0.
`sstatus.FS` and `sstatus.XS` are both set to `Off`.
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.
## Feature List
@ -249,7 +329,7 @@ struct limine_stack_size_request {
};
```
* `stack_size` - The requested stack size (also used for SMP processors).
* `stack_size` - The requested stack size in bytes (also used for SMP processors).
Response:
```c
@ -287,6 +367,8 @@ direct map.
### Terminal Feature
Note: *This feature is deprecated, do not use if possible.*
ID:
```c
#define LIMINE_TERMINAL_REQUEST { LIMINE_COMMON_MAGIC, 0xc8ac59310c2b0844, 0xa68d0c7265d38878 }
@ -444,10 +526,14 @@ context, and refresh the terminal fully.
In order to achieve this, special values for the `length` argument are
passed. These values are:
```c
/* Response revision 0 */
#define LIMINE_TERMINAL_CTX_SIZE ((uint64_t)(-1))
#define LIMINE_TERMINAL_CTX_SAVE ((uint64_t)(-2))
#define LIMINE_TERMINAL_CTX_RESTORE ((uint64_t)(-3))
#define LIMINE_TERMINAL_FULL_REFRESH ((uint64_t)(-4))
/* Response revision 1 */
#define LIMINE_TERMINAL_OOB_OUTPUT_GET ((uint64_t)(-10))
#define LIMINE_TERMINAL_OOB_OUTPUT_SET ((uint64_t)(-11))
```
For `CTX_SIZE`, the `ptr` variable has to point to a location to which the
@ -464,7 +550,26 @@ For `FULL_REFRESH`, the `ptr` variable is unused. This routine is to be used
after control of the framebuffer is taken over and the bootloader's terminal
has to *fully* repaint the framebuffer to avoid inconsistencies.
#### x86_64
If the response revision is equal or greater than 1
`OOB_OUTPUT_GET` and `OOB_OUTPUT_SET` allow getting and setting the
out-of-band terminal output settings. `ptr` points to a location to where
the terminal will *write* or *read* a single `uint64_t` value containing the
bits representing the settings.
The possible settings are as follows:
```c
#define LIMINE_TERMINAL_OOB_OUTPUT_OCRNL (1 << 0)
#define LIMINE_TERMINAL_OOB_OUTPUT_OFDEL (1 << 1)
#define LIMINE_TERMINAL_OOB_OUTPUT_OFILL (1 << 2)
#define LIMINE_TERMINAL_OOB_OUTPUT_OLCUC (1 << 3)
#define LIMINE_TERMINAL_OOB_OUTPUT_ONLCR (1 << 4)
#define LIMINE_TERMINAL_OOB_OUTPUT_ONLRET (1 << 5)
#define LIMINE_TERMINAL_OOB_OUTPUT_ONOCR (1 << 6)
#define LIMINE_TERMINAL_OOB_OUTPUT_OPOST (1 << 7)
```
The effect of each of these options matches the effect of the `stty(1)`
options by the same name.
#### x86-64
Additionally, the kernel must ensure, when calling `write()`, that:
@ -580,11 +685,119 @@ struct limine_framebuffer {
uint8_t unused[7];
uint64_t edid_size;
void *edid;
/* Response revision 1 */
uint64_t mode_count;
struct limine_video_mode **modes;
};
```
`modes` is an array of `mode_count` pointers to `struct limine_video_mode` describing the
available video modes for the given framebuffer.
```c
struct limine_video_mode {
uint64_t pitch;
uint64_t width;
uint64_t height;
uint16_t bpp;
uint8_t memory_model;
uint8_t red_mask_size;
uint8_t red_mask_shift;
uint8_t green_mask_size;
uint8_t green_mask_shift;
uint8_t blue_mask_size;
uint8_t blue_mask_shift;
};
```
### Paging Mode Feature
The Paging Mode feature allows the kernel to control which paging mode is enabled
before control is passed to it.
ID:
```c
#define LIMINE_PAGING_MODE_REQUEST { LIMINE_COMMON_MAGIC, 0x95c1a0edab0944cb, 0xa4e5cb3842f7488a }
```
Request:
```c
struct limine_paging_mode_request {
uint64_t id[4];
uint64_t revision;
struct limine_paging_mode_response *response;
uint64_t mode;
uint64_t flags;
};
```
Both the `mode` and `flags` fields are architecture-specific.
The `LIMINE_PAGING_MODE_DEFAULT` macro is provided by all architectures to select
the default paging mode (see below).
Response:
```c
struct limine_paging_mode_response {
uint64_t revision;
uint64_t mode;
uint64_t flags;
};
```
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
Values for `mode`:
```c
#define LIMINE_PAGING_MODE_X86_64_4LVL 0
#define LIMINE_PAGING_MODE_X86_64_5LVL 1
#define LIMINE_PAGING_MODE_DEFAULT LIMINE_PAGING_MODE_X86_64_4LVL
```
No `flags` are currently defined.
The default mode (when this request is not provided) is `LIMINE_PAGING_MODE_X86_64_4LVL`.
#### aarch64
Values for `mode`:
```c
#define LIMINE_PAGING_MODE_AARCH64_4LVL 0
#define LIMINE_PAGING_MODE_AARCH64_5LVL 1
#define LIMINE_PAGING_MODE_DEFAULT LIMINE_PAGING_MODE_AARCH64_4LVL
```
No `flags` are currently defined.
The default mode (when this request is not provided) is `LIMINE_PAGING_MODE_AARCH64_4LVL`.
#### riscv64
Values for `mode`:
```c
#define LIMINE_PAGING_MODE_RISCV_SV39 0
#define LIMINE_PAGING_MODE_RISCV_SV48 1
#define LIMINE_PAGING_MODE_RISCV_SV57 2
#define LIMINE_PAGING_MODE_DEFAULT LIMINE_PAGING_MODE_RISCV_SV48
```
No `flags` are currently defined.
The default mode (when this request is not provided) is `LIMINE_PAGING_MODE_RISCV_SV48`.
### 5-Level Paging Feature
Note: *This feature has been deprecated in favor of the [Paging Mode feature](#paging-mode-feature)
and will be removed entirely in a future release.*
ID:
```c
#define LIMINE_5_LEVEL_PAGING_REQUEST { LIMINE_COMMON_MAGIC, 0x94469551da9b3192, 0xebe5e86db7382888 }
@ -607,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
@ -627,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:
@ -684,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;
@ -726,6 +939,53 @@ processor. This field is unused for the structure describing the bootstrap
processor.
* `extra_argument` - A free for use field.
#### riscv64
Response:
```c
struct limine_smp_response {
uint64_t revision;
uint64_t flags;
uint64_t bsp_hartid;
uint64_t cpu_count;
struct limine_smp_info **cpus;
};
```
* `flags` - Always zero
* `bsp_hartid` - Hart ID of the bootstrap processor as reported by the UEFI RISC-V Boot Protocol or the SBI.
* `cpu_count` - How many CPUs are present. It includes the bootstrap processor.
* `cpus` - Pointer to an array of `cpu_count` pointers to
`struct limine_smp_info` structures.
Notes: The presence of this request will prompt the bootloader to bootstrap
the secondary processors. This will not be done if this request is not present.
```c
struct limine_smp_info;
typedef void (*limine_goto_address)(struct limine_smp_info *);
struct limine_smp_info {
uint64_t processor_id;
uint64_t hartid;
uint64_t reserved;
limine_goto_address goto_address;
uint64_t extra_argument;
};
```
* `processor_id` - ACPI Processor UID as specified by the MADT (always 0 on non-ACPI systems).
* `hartid` - Hart ID of the processor as specified by the MADT or Device Tree.
* `goto_address` - An atomic write to this field causes the parked CPU to
jump to the written address, on a 64KiB (or Stack Size Request size) stack. A pointer to the
`struct limine_smp_info` structure of the CPU is passed in `x10`(`a0`). Other than
that, the CPU state will be the same as described for the bootstrap
processor. This field is unused for the structure describing the bootstrap
processor.
* `extra_argument` - A free for use field.
### Memory Map Feature
ID:
@ -847,13 +1107,43 @@ ID:
Request:
```c
#define LIMINE_INTERNAL_MODULE_REQUIRED (1 << 0)
struct limine_internal_module {
const char *path;
const char *cmdline;
uint64_t flags;
};
struct limine_module_request {
uint64_t id[4];
uint64_t revision;
struct limine_module_response *response;
/* Request revision 1 */
uint64_t internal_module_count;
struct limine_internal_module **internal_modules;
};
```
* `internal_module_count` - How many internal modules are passed by the kernel.
* `internal_modules` - Pointer to an array of `internal_module_count` pointers to
`struct limine_internal_module` structures.
Note: Internal modules are honoured if the module response has revision >= 1.
As part of `struct limine_internal_module`:
* `path` - Path to the module to load. This path is *relative* to the location of
the kernel.
* `cmdline` - Command line for the given module.
* `flags` - Flags changing module loading behaviour:
- `LIMINE_INTERNAL_MODULE_REQUIRED`: Fail if the requested module is not found.
Internal Limine modules are guaranteed to be loaded *before* user-specified
(configuration) modules, and thus they are guaranteed to appear before user-specified
modules in the `modules` array in the response.
Response:
```c
struct limine_module_response {
@ -900,7 +1190,7 @@ struct limine_file {
```
* `revision` - Revision of the `struct limine_file` structure.
* `address` - The address of the file.
* `address` - The address of the file. This is always at least 4KiB aligned.
* `size` - The size of the file.
* `path` - The path of the file within the volume, with a leading slash.
* `cmdline` - A command line associated with the file.
@ -1079,5 +1369,7 @@ struct limine_dtb_response {
* `dtb_ptr` - Virtual pointer to the device tree blob.
Note: If the DTB cannot be found, the response will *not* be generated.
Note: Information contained in the `/chosen` node may not reflect the information
given by bootloader tags, and as such the `/chosen` node properties should be ignored.

View File

@ -2,18 +2,26 @@
### What is Limine?
Limine is a modern, advanced, portable, multiprotocol bootloader, also used
Limine (pronounced as shown [here](https://www.merriam-webster.com/dictionary/in%20limine))
is a modern, advanced, portable, multiprotocol bootloader, also used
as the reference implementation for the [Limine boot protocol](/PROTOCOL.md).
### Donate
If you want to support the work I (@mintsuki) do on Limine, feel free to donate to me on Liberapay:
<a href="https://liberapay.com/mintsuki/donate"><img alt="Donate using Liberapay" src="https://liberapay.com/assets/widgets/donate.svg"></a>
Donations welcome, but absolutely not mandatory!
### Limine's boot menu
![Reference screenshot](/screenshot.png?raw=true "Reference screenshot")
[Photo by Lívia Bittencourt](https://www.pexels.com/photo/big-sea-waves-under-rainbow-and-cloudy-sky-4636525/)
[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)
### Supported boot protocols
@ -23,25 +31,28 @@ as the reference implementation for the [Limine boot protocol](/PROTOCOL.md).
* Multiboot 2
* Chainloading
### Supported filesystems
* ext2/3/4
* FAT12/16/32
* ISO9660 (CDs/DVDs)
Even though these are the filesystems Limine supports directly, *any*
filesystem can be utilised by the kernel provided that the kernel (and any
needed modules) are on a directly supported filesystem.
### Supported partitioning schemes
* MBR
* GPT
* Unpartitioned media
### Supported filesystems
* ext2/3/4
* FAT12/16/32
* ISO9660 (CDs/DVDs)
If your filesystem isn't listed here, please read [the philosophy](/PHILOSOPHY.md) first, especially before
opening issues or pull requests related to this.
### Minimum system requirements
For 32-bit x86 systems, support is only ensured starting with those with
Pentium Pro (i686) class CPUs.
All x86_64 and aarch64 (UEFI) systems are supported.
All x86-64 and aarch64 (UEFI) systems are supported.
## Packaging status
[![Packaging status](https://repology.org/badge/vertical-allrepos/limine.svg)](https://repology.org/project/limine/versions)
## Binary releases
@ -54,15 +65,15 @@ For example, to clone the latest binary release of the `v4.x` branch one can do
```bash
git clone https://github.com/limine-bootloader/limine.git --branch=v4.x-branch-binary --depth=1
```
or, to clone a specific binary point release (for example `v4.0`)
or, to clone a specific binary point release (for example `v4.20231024.eol`)
```bash
git clone https://github.com/limine-bootloader/limine.git --branch=v4.0-binary --depth=1
git clone https://github.com/limine-bootloader/limine.git --branch=v4.20231024.eol-binary --depth=1
```
In order to rebuild `limine-deploy`, simply run `make` in the binary
In order to rebuild host utilities like `limine-deploy`, simply run `make` in the binary
release directory.
`limine-deploy.exe` binaries are provided for Windows.
Host utility binaries are provided for Windows.
## Building the bootloader
@ -92,11 +103,9 @@ these, run `./configure --help`.
**`./configure` by default does not build any Limine port. Make sure to read the**
**output of `./configure --help` and enable any or all ports!**
To build using the LLVM toolchain, pass `CROSS_TOOLCHAIN=llvm` to `./configure`.
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
@ -122,14 +131,21 @@ make install # (or gmake where applicable)
## How to use
### UEFI
The `BOOT{IA32,X64,AA64}.EFI` files are vaild EFI applications that can be simply copied to
The `BOOT*.EFI` files are valid EFI applications that can be simply copied to
the `/EFI/BOOT` directory of a FAT formatted EFI system partition. These files can
be installed there and coexist with a BIOS installation of Limine (see below) so
that the disk will be bootable on both BIOS and UEFI systems.
The boot device must to contain the `limine.cfg` file in
either the root or the `boot` directory of one of the partitions, formatted
with a supported file system (the ESP partition is recommended).
The boot device must contain the `limine.cfg` files in
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 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).
### BIOS/MBR
In order to install Limine on a MBR device (which can just be a raw image file),
@ -139,9 +155,9 @@ run `limine-deploy` as such:
limine-deploy <path to device/image>
```
The boot device must to contain the `limine.sys` and `limine.cfg` files in
either the root or the `boot` directory of one of the partitions, formatted
with a supported file system.
The boot device must contain the `limine.sys` and `limine.cfg` files in
either the root, `limine`, `boot`, or `boot/limine` directory of one of the
partitions, formatted with a supported file system.
### BIOS/GPT
If using a GPT formatted device, there are 2 options one can follow for
@ -161,18 +177,21 @@ In case one wants to let `limine-deploy` embed stage 2 within GPT's structures,
simply omit the partition number, and invoke `limine-deploy` the same as one
would do for an MBR partitioned device.
The boot device must to contain the `limine.sys` and `limine.cfg` files in
either the root or the `boot` directory of one of the partitions, formatted
with a supported file system.
The boot device must contain the `limine.sys` and `limine.cfg` files in
either the root, `limine`, `boot`, or `boot/limine` directory of one of the
partitions, formatted with a supported file system.
### BIOS/UEFI hybrid ISO creation
In order to create a hybrid ISO with Limine, place the
`limine-cd-efi.bin`, `limine-cd.bin`, `limine.sys`, and `limine.cfg` files
into a directory which will serve as the root of the created ISO.
(`limine.sys` and `limine.cfg` must either be in the root or inside a `boot`
subdirectory; `limine-cd-efi.bin` and `limine-cd.bin` can reside
(`limine.sys` and `limine.cfg` must either be in the root, `limine`, `boot`, or
`boot/limine` directory; `limine-cd-efi.bin` and `limine-cd.bin` can reside
anywhere).
After that, create a `<ISO root directory>/EFI/BOOT` directory and copy the
relevant Limine EFI executables over (such as `BOOTX64.EFI`).
Place any other file you want to be on the final ISO in said directory, then
run:
```
@ -209,6 +228,11 @@ server or your existing DHCP server and a proxy DHCP server such as dnsmasq.
`limine.cfg` and `limine.sys` are expected to be on the server used for boot.
### UEFI/PXE boot
The `BOOT*.EFI` files are compatible with UEFI PXE.
The steps needed to boot Limine are the same as with BIOS PXE,
except that the `limine.sys` file is not needed on the server.
### Configuration
The `limine.cfg` file contains Limine's configuration.
@ -217,7 +241,9 @@ An example `limine.cfg` file can be found in [`test/limine.cfg`](https://github.
More info on the format of `limine.cfg` can be found in [`CONFIG.md`](https://github.com/limine-bootloader/limine/blob/trunk/CONFIG.md).
## Acknowledgments
Limine uses a stripped-down version of [tinf](https://github.com/jibsen/tinf).
Limine uses a stripped-down version of [tinf](https://github.com/jibsen/tinf) for early GZIP decompression.
Limine relies on [stb_image](https://github.com/nothings/stb/blob/dev/stb_image.h) for runtime GZIP decompression and image loading.
## Discord server
We have a [Discord server](https://discord.gg/QEeZMz4) if you need support,

View File

@ -7,14 +7,26 @@ test -z "$srcdir" && srcdir=.
cd "$srcdir"
[ -d cross-detect ] || git clone https://github.com/mintsuki/cross-detect.git
[ -d freestanding-headers ] || git clone https://github.com/mintsuki/freestanding-headers.git
[ -d limine-efi ] || git clone https://github.com/limine-bootloader/limine-efi.git
[ -d libgcc-binaries ] || git clone https://github.com/mintsuki/libgcc-binaries.git
if [ -z "$BOOTSTRAP_NO_SHALLOW_CLONES" ]; then
SHALLOW_CLONE_FLAG="--depth=1"
fi
automake_libdir="$(automake --print-libdir)"
[ -d common/flanterm ] || git clone https://github.com/mintsuki/flanterm.git common/flanterm $SHALLOW_CLONE_FLAG
[ -f common/stb/stb_image.h ] || ( curl -Lo common/stb/stb_image.h https://github.com/nothings/stb/raw/dev/stb_image.h && patch -p0 < common/stb_image.patch )
[ -d decompressor/tinf ] || (
set -e
mkdir -p decompressor/tinf
curl -Lo decompressor/tinf/tinf.h https://github.com/jibsen/tinf/raw/master/src/tinf.h
curl -Lo decompressor/tinf/tinflate.c https://github.com/jibsen/tinf/raw/master/src/tinflate.c
curl -Lo decompressor/tinf/tinfgzip.c https://github.com/jibsen/tinf/raw/master/src/tinfgzip.c
patch -p0 < decompressor/tinf.patch
)
[ -f freestanding-toolchain ] || ( curl -Lo freestanding-toolchain https://github.com/mintsuki/freestanding-toolchain/raw/trunk/freestanding-toolchain && chmod +x freestanding-toolchain )
[ -d freestanding-headers ] || git clone https://github.com/mintsuki/freestanding-headers.git $SHALLOW_CLONE_FLAG
[ -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
mkdir -p build-aux
cp "${automake_libdir}/install-sh" build-aux
cp "$(automake --print-libdir)/install-sh" build-aux
autoreconf -fvi
autoreconf -fvi -Wall

View File

@ -1,4 +1,11 @@
include $(CROSS_FILE)
override MAKEFLAGS += -rR
include $(TOOLCHAIN_FILE)
export CC_FOR_TARGET
export LD_FOR_TARGET
export OBJDUMP_FOR_TARGET
export OBJCOPY_FOR_TARGET
export READELF_FOR_TARGET
TARGET ?=
BUILDDIR ?=
@ -15,27 +22,21 @@ 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
$(error Invalid target)
endif
COM_OUTPUT ?= false
E9_OUTPUT ?= false
override S2CFLAGS := -Os
override BASE_CFLAGS := $(CROSS_CFLAGS)
override BASE_CFLAGS := $(CFLAGS_FOR_TARGET)
override CROSS_CFLAGS += \
override CFLAGS_FOR_TARGET += \
-g \
-Wall \
-Wextra \
-Wshadow \
-Wvla \
-Wno-deprecated-declarations \
$(WERROR_FLAG) \
-std=gnu11 \
-nostdinc \
-ffreestanding \
@ -43,85 +44,95 @@ override CROSS_CFLAGS += \
-fno-stack-check \
-fno-omit-frame-pointer \
-fno-strict-aliasing \
-fno-lto \
-Wshadow \
-Wvla \
$(WERROR) \
-MMD \
-DCOM_OUTPUT=$(COM_OUTPUT) \
-DE9_OUTPUT=$(E9_OUTPUT) \
-fno-lto
override CPPFLAGS_FOR_TARGET := \
-I../freestanding-headers \
-I'$(call SHESCAPE,$(BUILDDIR))/tinf' \
-I'$(call SHESCAPE,$(BUILDDIR))/..' \
-I. \
-I..
$(CPPFLAGS_FOR_TARGET) \
-DCOM_OUTPUT=$(COM_OUTPUT) \
-DE9_OUTPUT=$(E9_OUTPUT) \
-MMD \
-MP
$(call MKESCAPE,$(BUILDDIR))/./flanterm/backends/fb.o: override CPPFLAGS_FOR_TARGET += \
-DFLANTERM_FB_DISABLE_BUMP_ALLOC \
-DFLANTERM_FB_SUPPORT_BPP
ifeq ($(TARGET),bios)
override CROSS_CFLAGS += \
-fno-pie \
-fno-pic \
override CFLAGS_FOR_TARGET += \
-fno-PIE \
-fno-PIC \
-m32 \
-march=i686 \
-mabi=sysv \
-mno-80387 \
-mno-80387
override CPPFLAGS_FOR_TARGET := \
$(CPPFLAGS_FOR_TARGET) \
-DBIOS
endif
ifeq ($(TARGET),uefi-x86-64)
override CROSS_CFLAGS += \
-fpie \
override CFLAGS_FOR_TARGET += \
-fPIE \
-fshort-wchar \
-m64 \
-march=x86-64 \
-mabi=sysv \
-mno-80387 \
-mno-mmx \
-mno-sse \
-mno-sse2 \
-mno-red-zone \
-DUEFI \
-DGNU_EFI_USE_MS_ABI \
-mno-red-zone
override CPPFLAGS_FOR_TARGET := \
-I'$(call SHESCAPE,$(BUILDDIR))/limine-efi/inc' \
-I'$(call SHESCAPE,$(BUILDDIR))/limine-efi/inc/x86_64'
-I'$(call SHESCAPE,$(BUILDDIR))/limine-efi/inc/x86_64' \
$(CPPFLAGS_FOR_TARGET) \
-DUEFI
endif
ifeq ($(TARGET),uefi-ia32)
override CROSS_CFLAGS += \
-fpie \
override CFLAGS_FOR_TARGET += \
-fPIE \
-fshort-wchar \
-m32 \
-march=i686 \
-mabi=sysv \
-mno-80387 \
-DUEFI \
-mno-80387
override CPPFLAGS_FOR_TARGET := \
-I'$(call SHESCAPE,$(BUILDDIR))/limine-efi/inc' \
-I'$(call SHESCAPE,$(BUILDDIR))/limine-efi/inc/ia32'
-I'$(call SHESCAPE,$(BUILDDIR))/limine-efi/inc/ia32' \
$(CPPFLAGS_FOR_TARGET) \
-DUEFI
endif
ifeq ($(TARGET),uefi-aarch64)
override CROSS_CFLAGS += \
-fpie \
-mgeneral-regs-only \
-DUEFI \
override CFLAGS_FOR_TARGET += \
-fPIE \
-fshort-wchar \
-mgeneral-regs-only
override CPPFLAGS_FOR_TARGET := \
-I'$(call SHESCAPE,$(BUILDDIR))/limine-efi/inc' \
-I'$(call SHESCAPE,$(BUILDDIR))/limine-efi/inc/aarch64'
-I'$(call SHESCAPE,$(BUILDDIR))/limine-efi/inc/aarch64' \
$(CPPFLAGS_FOR_TARGET) \
-DUEFI
endif
override CROSS_LDFLAGS += \
override LDFLAGS_FOR_TARGET += \
-nostdlib \
-z max-page-size=0x1000
ifeq ($(TARGET),bios)
override CROSS_LDFLAGS += \
override LDFLAGS_FOR_TARGET += \
-m elf_i386 \
-static \
--build-id=sha1
ifeq ($(CROSS_LD_HAS_NO_PIE),yes)
override CROSS_LDFLAGS += -no-pie
ifeq ($(LD_FOR_TARGET_HAS_NO_PIE),yes)
override LDFLAGS_FOR_TARGET += -no-pie
endif
endif
ifeq ($(TARGET),uefi-x86-64)
override CROSS_LDFLAGS += \
override LDFLAGS_FOR_TARGET += \
-m elf_x86_64 \
-static \
-pie \
@ -130,7 +141,7 @@ ifeq ($(TARGET),uefi-x86-64)
endif
ifeq ($(TARGET),uefi-ia32)
override CROSS_LDFLAGS += \
override LDFLAGS_FOR_TARGET += \
-m elf_i386 \
-static \
-pie \
@ -139,7 +150,7 @@ ifeq ($(TARGET),uefi-ia32)
endif
ifeq ($(TARGET),uefi-aarch64)
override CROSS_LDFLAGS += \
override LDFLAGS_FOR_TARGET += \
-m aarch64elf \
-static \
-pie \
@ -191,86 +202,96 @@ else ifeq ($(TARGET),uefi-aarch64)
all: $(call MKESCAPE,$(BUILDDIR))/BOOTAA64.EFI
endif
$(call MKESCAPE,$(BUILDDIR))/font.o: font.bin
$(MKDIR_P) "$$(dirname '$(call SHESCAPE,$@)')"
$(CROSS_OBJCOPY) -I binary $(OBJCOPY2ELF_FLAGS) font.bin '$(call SHESCAPE,$@)'
$(call MKESCAPE,$(BUILDDIR))/tinf-copied: ../tinf/*
rm -rf '$(call SHESCAPE,$(BUILDDIR))/tinf'
$(MKDIR_P) '$(call SHESCAPE,$(BUILDDIR))'
cp -r ../tinf '$(call SHESCAPE,$(BUILDDIR))/'
touch '$(call SHESCAPE,$(BUILDDIR))/tinf-copied'
$(call MKESCAPE,$(BUILDDIR))/tinf/tinfgzip.o: $(call MKESCAPE,$(BUILDDIR))/tinf-copied
$(MKDIR_P) "$$(dirname '$(call SHESCAPE,$@)')"
$(CROSS_CC) $(CROSS_CFLAGS) -c '$(call SHESCAPE,$(@:.o=.c))' -o '$(call SHESCAPE,$@)'
$(call MKESCAPE,$(BUILDDIR))/tinf/tinflate.o: $(call MKESCAPE,$(BUILDDIR))/tinf-copied
$(MKDIR_P) "$$(dirname '$(call SHESCAPE,$@)')"
$(CROSS_CC) $(CROSS_CFLAGS) -c '$(call SHESCAPE,$(@:.o=.c))' -o '$(call SHESCAPE,$@)'
ifeq ($(TARGET),bios)
$(call MKESCAPE,$(BUILDDIR))/stage2.bin.gz: $(call MKESCAPE,$(BUILDDIR))/stage2.bin
gzip -n -9 < '$(call SHESCAPE,$<)' > '$(call SHESCAPE,$@)'
$(call MKESCAPE,$(BUILDDIR))/stage2.bin: $(call MKESCAPE,$(BUILDDIR))/limine.sys
dd if='$(call SHESCAPE,$<)' bs=$$(( 0x$$("$(CROSS_READELF)" -S '$(call SHESCAPE,$(BUILDDIR))/limine.elf' | $(GREP) .text.stage3 | $(SED) 's/^.*] //' | $(AWK) '{print $$3}' | $(SED) 's/^0*//') - 0x8000 )) count=1 of='$(call SHESCAPE,$@)' 2>/dev/null
dd if='$(call SHESCAPE,$<)' bs=$$(( 0x$$("$(READELF_FOR_TARGET)" -S '$(call SHESCAPE,$(BUILDDIR))/limine.elf' | $(GREP) '\.text\.stage3' | $(SED) 's/^.*] //' | $(AWK) '{print $$3}' | $(SED) 's/^0*//') - 0xf000 )) count=1 of='$(call SHESCAPE,$@)' 2>/dev/null
$(call MKESCAPE,$(BUILDDIR))/stage2.map.o: $(call MKESCAPE,$(BUILDDIR))/limine_stage2only.elf
$(call MKESCAPE,$(BUILDDIR))/stage2.map.o: $(call MKESCAPE,$(BUILDDIR))/limine_nomap.elf
cd '$(call SHESCAPE,$(BUILDDIR))' && \
'$(call SHESCAPE,$(SRCDIR))/gensyms.sh' '$(call SHESCAPE,$<)' stage2 32 '\.text'
$(CROSS_CC) $(CROSS_CFLAGS) -c '$(call SHESCAPE,$(BUILDDIR))/stage2.map.S' -o '$(call SHESCAPE,$@)'
'$(call SHESCAPE,$(SRCDIR))/gensyms.sh' '$(call SHESCAPE,$<)' stage2 32 '\.text\.stage2'
$(CC_FOR_TARGET) $(CFLAGS_FOR_TARGET) $(CPPFLAGS_FOR_TARGET) -c '$(call SHESCAPE,$(BUILDDIR))/stage2.map.S' -o '$(call SHESCAPE,$@)'
rm -f '$(call SHESCAPE,$(BUILDDIR))/stage2.map.S' '$(call SHESCAPE,$(BUILDDIR))/stage2.map.d'
$(call MKESCAPE,$(BUILDDIR))/full.map.o: $(call MKESCAPE,$(BUILDDIR))/limine_nomap.elf
$(call MKESCAPE,$(BUILDDIR))/full.map.o: $(call MKESCAPE,$(BUILDDIR))/limine_nos3map.elf
cd '$(call SHESCAPE,$(BUILDDIR))' && \
'$(call SHESCAPE,$(SRCDIR))/gensyms.sh' '$(call SHESCAPE,$<)' full 32 '\.text'
$(CROSS_CC) $(CROSS_CFLAGS) -c '$(call SHESCAPE,$(BUILDDIR))/full.map.S' -o '$(call SHESCAPE,$@)'
$(CC_FOR_TARGET) $(CFLAGS_FOR_TARGET) $(CPPFLAGS_FOR_TARGET) -c '$(call SHESCAPE,$(BUILDDIR))/full.map.S' -o '$(call SHESCAPE,$@)'
rm -f '$(call SHESCAPE,$(BUILDDIR))/full.map.S' '$(call SHESCAPE,$(BUILDDIR))/full.map.d'
$(call MKESCAPE,$(BUILDDIR))/limine.sys: $(call MKESCAPE,$(BUILDDIR))/limine.elf
$(CROSS_OBJCOPY) -O binary '$(call SHESCAPE,$<)' '$(call SHESCAPE,$@)'
$(call MKESCAPE,$(BUILDDIR))/limine.sys: $(call MKESCAPE,$(BUILDDIR))/limine_stage2only.elf $(call MKESCAPE,$(BUILDDIR))/limine.elf
$(OBJCOPY_FOR_TARGET) -O binary '$(call SHESCAPE,$(BUILDDIR))/limine.elf' '$(call SHESCAPE,$@)'
chmod -x '$(call SHESCAPE,$@)'
$(call MKESCAPE,$(BUILDDIR))/linker_stage2only.ld: linker_bios.ld.in
$(MKDIR_P) '$(call SHESCAPE,$(BUILDDIR))'
$(CROSS_CC) -x c -E -P -undef -DLINKER_STAGE2ONLY linker_bios.ld.in -o '$(call SHESCAPE,$(BUILDDIR))/linker_stage2only.ld'
$(CC_FOR_TARGET) -x c -E -P -undef -DLINKER_STAGE2ONLY linker_bios.ld.in -o '$(call SHESCAPE,$(BUILDDIR))/linker_stage2only.ld'
$(call MKESCAPE,$(BUILDDIR))/limine_stage2only.elf: $(OBJ_S2) ../libgcc-binaries/libgcc-i686.a
$(MAKE) '$(call SHESCAPE,$(BUILDDIR))/linker_stage2only.ld'
$(CROSS_LD) '$(call OBJESCAPE,$^)' $(CROSS_LDFLAGS) -T'$(call SHESCAPE,$(BUILDDIR))/linker_stage2only.ld' -o '$(call SHESCAPE,$@)' || \
$(LD_FOR_TARGET) '$(call OBJESCAPE,$^)' $(LDFLAGS_FOR_TARGET) -T'$(call SHESCAPE,$(BUILDDIR))/linker_stage2only.ld' -o '$(call SHESCAPE,$@)' || \
( echo "This error may mean that stage 2 was trying to use stage 3 symbols before loading stage 3" && \
false )
$(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 -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 -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
$(MKDIR_P) '$(call SHESCAPE,$(BUILDDIR))'
$(CROSS_CC) -x c -E -P -undef -DLINKER_NOMAP linker_bios.ld.in -o '$(call SHESCAPE,$(BUILDDIR))/linker_nomap.ld'
$(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_nomap.elf: $(OBJ) ../libgcc-binaries/libgcc-i686.a $(call MKESCAPE,$(BUILDDIR))/tinf/tinfgzip.o $(call MKESCAPE,$(BUILDDIR))/tinf/tinflate.o $(call MKESCAPE,$(BUILDDIR))/font.o $(call MKESCAPE,$(BUILDDIR))/stage2.map.o
$(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'
$(CROSS_LD) '$(call OBJESCAPE,$^)' $(CROSS_LDFLAGS) -T'$(call SHESCAPE,$(BUILDDIR))/linker_nomap.ld' -o '$(call SHESCAPE,$@)'
$(CROSS_OBJCOPY) -O binary --only-section=.note.gnu.build-id '$(call SHESCAPE,$@)' '$(call SHESCAPE,$(BUILDDIR))/build-id.s2.bin'
$(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))' && \
$(CROSS_OBJCOPY) -I binary $(OBJCOPY2ELF_FLAGS) build-id.s2.bin build-id.s2.o
$(CROSS_OBJCOPY) -O binary --only-section=.note.gnu.build-id '$(call SHESCAPE,$@)' '$(call SHESCAPE,$(BUILDDIR))/build-id.s3.bin'
$(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))' && \
$(CROSS_OBJCOPY) -I binary $(OBJCOPY2ELF_FLAGS) build-id.s3.bin build-id.s3.o
$(CROSS_LD) '$(call OBJESCAPE,$^)' '$(call SHESCAPE,$(BUILDDIR))/build-id.s2.o' '$(call SHESCAPE,$(BUILDDIR))/build-id.s3.o' $(CROSS_LDFLAGS) -T'$(call SHESCAPE,$(BUILDDIR))/linker_nomap.ld' -o '$(call SHESCAPE,$@)'
$(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
$(MKDIR_P) '$(call SHESCAPE,$(BUILDDIR))'
$(CROSS_CC) -x c -E -P -undef linker_bios.ld.in -o '$(call SHESCAPE,$(BUILDDIR))/linker.ld'
$(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))/tinf/tinfgzip.o $(call MKESCAPE,$(BUILDDIR))/tinf/tinflate.o $(call MKESCAPE,$(BUILDDIR))/font.o $(call MKESCAPE,$(BUILDDIR))/stage2.map.o $(call MKESCAPE,$(BUILDDIR))/full.map.o
$(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'
$(CROSS_LD) '$(call OBJESCAPE,$^)' $(CROSS_LDFLAGS) -T'$(call SHESCAPE,$(BUILDDIR))/linker.ld' -o '$(call SHESCAPE,$@)'
$(CROSS_OBJCOPY) -O binary --only-section=.note.gnu.build-id '$(call SHESCAPE,$@)' '$(call SHESCAPE,$(BUILDDIR))/build-id.s2.bin'
$(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))' && \
$(CROSS_OBJCOPY) -I binary $(OBJCOPY2ELF_FLAGS) build-id.s2.bin build-id.s2.o
$(CROSS_OBJCOPY) -O binary --only-section=.note.gnu.build-id '$(call SHESCAPE,$@)' '$(call SHESCAPE,$(BUILDDIR))/build-id.s3.bin'
$(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))' && \
$(CROSS_OBJCOPY) -I binary $(OBJCOPY2ELF_FLAGS) build-id.s3.bin build-id.s3.o
$(CROSS_LD) '$(call OBJESCAPE,$^)' '$(call SHESCAPE,$(BUILDDIR))/build-id.s2.o' '$(call SHESCAPE,$(BUILDDIR))/build-id.s3.o' $(CROSS_LDFLAGS) -T'$(call SHESCAPE,$(BUILDDIR))/linker.ld' -o '$(call SHESCAPE,$@)'
$(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
@ -283,39 +304,44 @@ ifeq ($(TARGET),uefi-x86-64)
$(call MKESCAPE,$(BUILDDIR))/full.map.o: $(call MKESCAPE,$(BUILDDIR))/limine_nomap.elf
cd '$(call SHESCAPE,$(BUILDDIR))' && \
'$(call SHESCAPE,$(SRCDIR))/gensyms.sh' '$(call SHESCAPE,$<)' full 64 '\.text'
$(CROSS_CC) $(CROSS_CFLAGS) -c '$(call SHESCAPE,$(BUILDDIR))/full.map.S' -o '$(call SHESCAPE,$@)'
$(CC_FOR_TARGET) $(CFLAGS_FOR_TARGET) $(CPPFLAGS_FOR_TARGET) -c '$(call SHESCAPE,$(BUILDDIR))/full.map.S' -o '$(call SHESCAPE,$@)'
rm -f '$(call SHESCAPE,$(BUILDDIR))/full.map.S' '$(call SHESCAPE,$(BUILDDIR))/full.map.d'
$(call MKESCAPE,$(BUILDDIR))/BOOTX64.EFI: $(call MKESCAPE,$(BUILDDIR))/limine.elf
$(CROSS_OBJCOPY) -O binary '$(call SHESCAPE,$<)' '$(call SHESCAPE,$@)'
$(OBJCOPY_FOR_TARGET) -O binary '$(call SHESCAPE,$<)' '$(call SHESCAPE,$@)'
chmod -x '$(call SHESCAPE,$@)'
$(call MKESCAPE,$(BUILDDIR))/limine-efi/gnuefi/crt0-efi-x86_64.o $(call MKESCAPE,$(BUILDDIR))/limine-efi/gnuefi/reloc_x86_64.o: $(call MKESCAPE,$(BUILDDIR))/limine-efi
unset CPPFLAGS; \
$(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="$(CROSS_CC)" \
CC="$(CC_FOR_TARGET)" \
CFLAGS="$(BASE_CFLAGS)" \
CPPFLAGS='-nostdinc -I$(call SHESCAPE,$(SRCDIR))/../freestanding-headers' \
ARCH=x86_64
$(call MKESCAPE,$(BUILDDIR))/linker_nomap.ld: linker_uefi_x86_64.ld.in
$(MKDIR_P) '$(call SHESCAPE,$(BUILDDIR))'
$(CROSS_CC) -x c -E -P -undef -DLINKER_NOMAP linker_uefi_x86_64.ld.in -o '$(call SHESCAPE,$(BUILDDIR))/linker_nomap.ld'
$(CC_FOR_TARGET) -x c -E -P -undef -DLINKER_NOMAP linker_uefi_x86_64.ld.in -o '$(call SHESCAPE,$(BUILDDIR))/linker_nomap.ld'
$(call MKESCAPE,$(BUILDDIR))/limine_nomap.elf: $(call MKESCAPE,$(BUILDDIR))/limine-efi/gnuefi/crt0-efi-x86_64.o $(call MKESCAPE,$(BUILDDIR))/limine-efi/gnuefi/reloc_x86_64.o $(OBJ) ../libgcc-binaries/libgcc-x86_64-no-red-zone.a $(call MKESCAPE,$(BUILDDIR))/tinf/tinfgzip.o $(call MKESCAPE,$(BUILDDIR))/tinf/tinflate.o $(call MKESCAPE,$(BUILDDIR))/font.o
$(call MKESCAPE,$(BUILDDIR))/limine_nomap.elf: $(call MKESCAPE,$(BUILDDIR))/limine-efi/gnuefi/crt0-efi-x86_64.S.o $(call MKESCAPE,$(BUILDDIR))/limine-efi/gnuefi/reloc_x86_64.c.o $(OBJ) ../libgcc-binaries/libgcc-x86_64-no-red-zone.a
$(MAKE) '$(call SHESCAPE,$(BUILDDIR))/linker_nomap.ld'
$(CROSS_LD) \
$(LD_FOR_TARGET) \
-T'$(call SHESCAPE,$(BUILDDIR))/linker_nomap.ld' \
'$(call OBJESCAPE,$^)' $(CROSS_LDFLAGS) -o '$(call SHESCAPE,$@)'
'$(call OBJESCAPE,$^)' $(LDFLAGS_FOR_TARGET) -o '$(call SHESCAPE,$@)'
$(call MKESCAPE,$(BUILDDIR))/linker.ld: linker_uefi_x86_64.ld.in
$(MKDIR_P) '$(call SHESCAPE,$(BUILDDIR))'
$(CROSS_CC) -x c -E -P -undef linker_uefi_x86_64.ld.in -o '$(call SHESCAPE,$(BUILDDIR))/linker.ld'
$(CC_FOR_TARGET) -x c -E -P -undef linker_uefi_x86_64.ld.in -o '$(call SHESCAPE,$(BUILDDIR))/linker.ld'
$(call MKESCAPE,$(BUILDDIR))/limine.elf: $(call MKESCAPE,$(BUILDDIR))/limine-efi/gnuefi/crt0-efi-x86_64.o $(call MKESCAPE,$(BUILDDIR))/limine-efi/gnuefi/reloc_x86_64.o $(OBJ) ../libgcc-binaries/libgcc-x86_64-no-red-zone.a $(call MKESCAPE,$(BUILDDIR))/tinf/tinfgzip.o $(call MKESCAPE,$(BUILDDIR))/tinf/tinflate.o $(call MKESCAPE,$(BUILDDIR))/font.o $(call MKESCAPE,$(BUILDDIR))/full.map.o
$(call MKESCAPE,$(BUILDDIR))/limine.elf: $(call MKESCAPE,$(BUILDDIR))/limine-efi/gnuefi/crt0-efi-x86_64.S.o $(call MKESCAPE,$(BUILDDIR))/limine-efi/gnuefi/reloc_x86_64.c.o $(OBJ) ../libgcc-binaries/libgcc-x86_64-no-red-zone.a $(call MKESCAPE,$(BUILDDIR))/full.map.o
$(MAKE) '$(call SHESCAPE,$(BUILDDIR))/linker.ld'
$(CROSS_LD) \
$(LD_FOR_TARGET) \
-T'$(call SHESCAPE,$(BUILDDIR))/linker.ld' \
'$(call OBJESCAPE,$^)' $(CROSS_LDFLAGS) -o '$(call SHESCAPE,$@)'
'$(call OBJESCAPE,$^)' $(LDFLAGS_FOR_TARGET) -o '$(call SHESCAPE,$@)'
endif
@ -324,39 +350,44 @@ ifeq ($(TARGET),uefi-aarch64)
$(call MKESCAPE,$(BUILDDIR))/full.map.o: $(call MKESCAPE,$(BUILDDIR))/limine_nomap.elf
cd '$(call SHESCAPE,$(BUILDDIR))' && \
'$(call SHESCAPE,$(SRCDIR))/gensyms.sh' '$(call SHESCAPE,$<)' full 64 '\.text'
$(CROSS_CC) $(CROSS_CFLAGS) -c '$(call SHESCAPE,$(BUILDDIR))/full.map.S' -o '$(call SHESCAPE,$@)'
$(CC_FOR_TARGET) $(CFLAGS_FOR_TARGET) $(CPPFLAGS_FOR_TARGET) -c '$(call SHESCAPE,$(BUILDDIR))/full.map.S' -o '$(call SHESCAPE,$@)'
rm -f '$(call SHESCAPE,$(BUILDDIR))/full.map.S' '$(call SHESCAPE,$(BUILDDIR))/full.map.d'
$(call MKESCAPE,$(BUILDDIR))/BOOTAA64.EFI: $(call MKESCAPE,$(BUILDDIR))/limine.elf
$(CROSS_OBJCOPY) -O binary '$(call SHESCAPE,$<)' '$(call SHESCAPE,$@)'
$(OBJCOPY_FOR_TARGET) -O binary '$(call SHESCAPE,$<)' '$(call SHESCAPE,$@)'
chmod -x '$(call SHESCAPE,$@)'
$(call MKESCAPE,$(BUILDDIR))/limine-efi/gnuefi/crt0-efi-aarch64.o $(call MKESCAPE,$(BUILDDIR))/limine-efi/gnuefi/reloc_aarch64.o: $(call MKESCAPE,$(BUILDDIR))/limine-efi
unset CPPFLAGS; \
$(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="$(CROSS_CC)" \
CC="$(CC_FOR_TARGET)" \
CFLAGS="$(BASE_CFLAGS)" \
CPPFLAGS='-nostdinc -I$(call SHESCAPE,$(SRCDIR))/../freestanding-headers' \
ARCH=aarch64
$(call MKESCAPE,$(BUILDDIR))/linker_nomap.ld: linker_uefi_aarch64.ld.in
$(MKDIR_P) '$(call SHESCAPE,$(BUILDDIR))'
$(CROSS_CC) -x c -E -P -undef -DLINKER_NOMAP linker_uefi_aarch64.ld.in -o '$(call SHESCAPE,$(BUILDDIR))/linker_nomap.ld'
$(CC_FOR_TARGET) -x c -E -P -undef -DLINKER_NOMAP linker_uefi_aarch64.ld.in -o '$(call SHESCAPE,$(BUILDDIR))/linker_nomap.ld'
$(call MKESCAPE,$(BUILDDIR))/limine_nomap.elf: $(call MKESCAPE,$(BUILDDIR))/limine-efi/gnuefi/crt0-efi-aarch64.o $(call MKESCAPE,$(BUILDDIR))/limine-efi/gnuefi/reloc_aarch64.o $(OBJ) ../libgcc-binaries/libgcc-aarch64.a $(call MKESCAPE,$(BUILDDIR))/tinf/tinfgzip.o $(call MKESCAPE,$(BUILDDIR))/tinf/tinflate.o $(call MKESCAPE,$(BUILDDIR))/font.o
$(call MKESCAPE,$(BUILDDIR))/limine_nomap.elf: $(call MKESCAPE,$(BUILDDIR))/limine-efi/gnuefi/crt0-efi-aarch64.S.o $(call MKESCAPE,$(BUILDDIR))/limine-efi/gnuefi/reloc_aarch64.c.o $(OBJ) ../libgcc-binaries/libgcc-aarch64.a
$(MAKE) '$(call SHESCAPE,$(BUILDDIR))/linker_nomap.ld'
$(CROSS_LD) \
$(LD_FOR_TARGET) \
-T'$(call SHESCAPE,$(BUILDDIR))/linker_nomap.ld' \
'$(call OBJESCAPE,$^)' $(CROSS_LDFLAGS) -o '$(call SHESCAPE,$@)'
'$(call OBJESCAPE,$^)' $(LDFLAGS_FOR_TARGET) -o '$(call SHESCAPE,$@)'
$(call MKESCAPE,$(BUILDDIR))/linker.ld: linker_uefi_aarch64.ld.in
$(MKDIR_P) '$(call SHESCAPE,$(BUILDDIR))'
$(CROSS_CC) -x c -E -P -undef linker_uefi_aarch64.ld.in -o '$(call SHESCAPE,$(BUILDDIR))/linker.ld'
$(CC_FOR_TARGET) -x c -E -P -undef linker_uefi_aarch64.ld.in -o '$(call SHESCAPE,$(BUILDDIR))/linker.ld'
$(call MKESCAPE,$(BUILDDIR))/limine.elf: $(call MKESCAPE,$(BUILDDIR))/limine-efi/gnuefi/crt0-efi-aarch64.o $(call MKESCAPE,$(BUILDDIR))/limine-efi/gnuefi/reloc_aarch64.o $(OBJ) ../libgcc-binaries/libgcc-aarch64.a $(call MKESCAPE,$(BUILDDIR))/tinf/tinfgzip.o $(call MKESCAPE,$(BUILDDIR))/tinf/tinflate.o $(call MKESCAPE,$(BUILDDIR))/font.o $(call MKESCAPE,$(BUILDDIR))/full.map.o
$(call MKESCAPE,$(BUILDDIR))/limine.elf: $(call MKESCAPE,$(BUILDDIR))/limine-efi/gnuefi/crt0-efi-aarch64.S.o $(call MKESCAPE,$(BUILDDIR))/limine-efi/gnuefi/reloc_aarch64.c.o $(OBJ) ../libgcc-binaries/libgcc-aarch64.a $(call MKESCAPE,$(BUILDDIR))/full.map.o
$(MAKE) '$(call SHESCAPE,$(BUILDDIR))/linker.ld'
$(CROSS_LD) \
$(LD_FOR_TARGET) \
-T'$(call SHESCAPE,$(BUILDDIR))/linker.ld' \
'$(call OBJESCAPE,$^)' $(CROSS_LDFLAGS) -o '$(call SHESCAPE,$@)'
'$(call OBJESCAPE,$^)' $(LDFLAGS_FOR_TARGET) -o '$(call SHESCAPE,$@)'
endif
ifeq ($(TARGET),uefi-ia32)
@ -364,66 +395,71 @@ ifeq ($(TARGET),uefi-ia32)
$(call MKESCAPE,$(BUILDDIR))/full.map.o: $(call MKESCAPE,$(BUILDDIR))/limine_nomap.elf
cd '$(call SHESCAPE,$(BUILDDIR))' && \
'$(call SHESCAPE,$(SRCDIR))/gensyms.sh' '$(call SHESCAPE,$<)' full 32 '\.text'
$(CROSS_CC) $(CROSS_CFLAGS) -c '$(call SHESCAPE,$(BUILDDIR))/full.map.S' -o '$(call SHESCAPE,$@)'
$(CC_FOR_TARGET) $(CFLAGS_FOR_TARGET) $(CPPFLAGS_FOR_TARGET) -c '$(call SHESCAPE,$(BUILDDIR))/full.map.S' -o '$(call SHESCAPE,$@)'
rm -f '$(call SHESCAPE,$(BUILDDIR))/full.map.S' '$(call SHESCAPE,$(BUILDDIR))/full.map.d'
$(call MKESCAPE,$(BUILDDIR))/BOOTIA32.EFI: $(call MKESCAPE,$(BUILDDIR))/limine.elf
$(CROSS_OBJCOPY) -O binary '$(call SHESCAPE,$<)' '$(call SHESCAPE,$@)'
$(OBJCOPY_FOR_TARGET) -O binary '$(call SHESCAPE,$<)' '$(call SHESCAPE,$@)'
chmod -x '$(call SHESCAPE,$@)'
$(call MKESCAPE,$(BUILDDIR))/limine-efi/gnuefi/crt0-efi-ia32.o $(call MKESCAPE,$(BUILDDIR))/limine-efi/gnuefi/reloc_ia32.o: $(call MKESCAPE,$(BUILDDIR))/limine-efi
unset CPPFLAGS; \
$(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="$(CROSS_CC)" \
CC="$(CC_FOR_TARGET)" \
CFLAGS="$(BASE_CFLAGS)" \
CPPFLAGS='-nostdinc -I$(call SHESCAPE,$(SRCDIR))/../freestanding-headers' \
ARCH=ia32
$(call MKESCAPE,$(BUILDDIR))/linker_nomap.ld: linker_uefi_ia32.ld.in
$(MKDIR_P) '$(call SHESCAPE,$(BUILDDIR))'
$(CROSS_CC) -x c -E -P -undef -DLINKER_NOMAP linker_uefi_ia32.ld.in -o '$(call SHESCAPE,$(BUILDDIR))/linker_nomap.ld'
$(CC_FOR_TARGET) -x c -E -P -undef -DLINKER_NOMAP linker_uefi_ia32.ld.in -o '$(call SHESCAPE,$(BUILDDIR))/linker_nomap.ld'
$(call MKESCAPE,$(BUILDDIR))/limine_nomap.elf: $(call MKESCAPE,$(BUILDDIR))/limine-efi/gnuefi/crt0-efi-ia32.o $(call MKESCAPE,$(BUILDDIR))/limine-efi/gnuefi/reloc_ia32.o $(OBJ) ../libgcc-binaries/libgcc-i686.a $(call MKESCAPE,$(BUILDDIR))/tinf/tinfgzip.o $(call MKESCAPE,$(BUILDDIR))/tinf/tinflate.o $(call MKESCAPE,$(BUILDDIR))/font.o
$(call MKESCAPE,$(BUILDDIR))/limine_nomap.elf: $(call MKESCAPE,$(BUILDDIR))/limine-efi/gnuefi/crt0-efi-ia32.S.o $(call MKESCAPE,$(BUILDDIR))/limine-efi/gnuefi/reloc_ia32.c.o $(OBJ) ../libgcc-binaries/libgcc-i686.a
$(MAKE) '$(call SHESCAPE,$(BUILDDIR))/linker_nomap.ld'
$(CROSS_LD) \
$(LD_FOR_TARGET) \
-T'$(call SHESCAPE,$(BUILDDIR))/linker_nomap.ld' \
'$(call OBJESCAPE,$^)' $(CROSS_LDFLAGS) -o '$(call SHESCAPE,$@)'
'$(call OBJESCAPE,$^)' $(LDFLAGS_FOR_TARGET) -o '$(call SHESCAPE,$@)'
$(call MKESCAPE,$(BUILDDIR))/linker.ld: linker_uefi_ia32.ld.in
$(MKDIR_P) '$(call SHESCAPE,$(BUILDDIR))'
$(CROSS_CC) -x c -E -P -undef linker_uefi_ia32.ld.in -o '$(call SHESCAPE,$(BUILDDIR))/linker.ld'
$(CC_FOR_TARGET) -x c -E -P -undef linker_uefi_ia32.ld.in -o '$(call SHESCAPE,$(BUILDDIR))/linker.ld'
$(call MKESCAPE,$(BUILDDIR))/limine.elf: $(call MKESCAPE,$(BUILDDIR))/limine-efi/gnuefi/crt0-efi-ia32.o $(call MKESCAPE,$(BUILDDIR))/limine-efi/gnuefi/reloc_ia32.o $(OBJ) ../libgcc-binaries/libgcc-i686.a $(call MKESCAPE,$(BUILDDIR))/tinf/tinfgzip.o $(call MKESCAPE,$(BUILDDIR))/tinf/tinflate.o $(call MKESCAPE,$(BUILDDIR))/font.o $(call MKESCAPE,$(BUILDDIR))/full.map.o
$(call MKESCAPE,$(BUILDDIR))/limine.elf: $(call MKESCAPE,$(BUILDDIR))/limine-efi/gnuefi/crt0-efi-ia32.S.o $(call MKESCAPE,$(BUILDDIR))/limine-efi/gnuefi/reloc_ia32.c.o $(OBJ) ../libgcc-binaries/libgcc-i686.a $(call MKESCAPE,$(BUILDDIR))/full.map.o
$(MAKE) '$(call SHESCAPE,$(BUILDDIR))/linker.ld'
$(CROSS_LD) \
$(LD_FOR_TARGET) \
-T'$(call SHESCAPE,$(BUILDDIR))/linker.ld' \
'$(call OBJESCAPE,$^)' $(CROSS_LDFLAGS) -o '$(call SHESCAPE,$@)'
'$(call OBJESCAPE,$^)' $(LDFLAGS_FOR_TARGET) -o '$(call SHESCAPE,$@)'
endif
-include $(HEADER_DEPS)
ifeq ($(TARGET),uefi-x86-64)
$(call MKESCAPE,$(BUILDDIR))/%.o: %.c $(call MKESCAPE,$(BUILDDIR))/tinf-copied $(call MKESCAPE,$(BUILDDIR))/limine-efi
$(call MKESCAPE,$(BUILDDIR))/%.o: %.c $(call MKESCAPE,$(BUILDDIR))/limine-efi
$(MKDIR_P) "$$(dirname '$(call SHESCAPE,$@)')"
$(CROSS_CC) $(CROSS_CFLAGS) -c '$(call SHESCAPE,$<)' -o '$(call SHESCAPE,$@)'
$(CC_FOR_TARGET) $(CFLAGS_FOR_TARGET) $(CPPFLAGS_FOR_TARGET) -c '$(call SHESCAPE,$<)' -o '$(call SHESCAPE,$@)'
endif
ifeq ($(TARGET),uefi-aarch64)
$(call MKESCAPE,$(BUILDDIR))/%.o: %.c $(call MKESCAPE,$(BUILDDIR))/tinf-copied $(call MKESCAPE,$(BUILDDIR))/limine-efi
$(call MKESCAPE,$(BUILDDIR))/%.o: %.c $(call MKESCAPE,$(BUILDDIR))/limine-efi
$(MKDIR_P) "$$(dirname '$(call SHESCAPE,$@)')"
$(CROSS_CC) $(CROSS_CFLAGS) -c '$(call SHESCAPE,$<)' -o '$(call SHESCAPE,$@)'
$(CC_FOR_TARGET) $(CFLAGS_FOR_TARGET) $(CPPFLAGS_FOR_TARGET) -c '$(call SHESCAPE,$<)' -o '$(call SHESCAPE,$@)'
endif
ifeq ($(TARGET),uefi-ia32)
$(call MKESCAPE,$(BUILDDIR))/%.o: %.c $(call MKESCAPE,$(BUILDDIR))/tinf-copied $(call MKESCAPE,$(BUILDDIR))/limine-efi
$(call MKESCAPE,$(BUILDDIR))/%.o: %.c $(call MKESCAPE,$(BUILDDIR))/limine-efi
$(MKDIR_P) "$$(dirname '$(call SHESCAPE,$@)')"
$(CROSS_CC) $(CROSS_CFLAGS) -c '$(call SHESCAPE,$<)' -o '$(call SHESCAPE,$@)'
$(CC_FOR_TARGET) $(CFLAGS_FOR_TARGET) $(CPPFLAGS_FOR_TARGET) -c '$(call SHESCAPE,$<)' -o '$(call SHESCAPE,$@)'
endif
ifeq ($(TARGET),bios)
$(call MKESCAPE,$(BUILDDIR))/%.o: %.c $(call MKESCAPE,$(BUILDDIR))/tinf-copied
$(call MKESCAPE,$(BUILDDIR))/%.o: %.c
$(MKDIR_P) "$$(dirname '$(call SHESCAPE,$@)')"
$(CROSS_CC) $(CROSS_CFLAGS) -c '$(call SHESCAPE,$<)' -o '$(call SHESCAPE,$@)'
$(CC_FOR_TARGET) $(CFLAGS_FOR_TARGET) $(CPPFLAGS_FOR_TARGET) -c '$(call SHESCAPE,$<)' -o '$(call SHESCAPE,$@)'
endif
-include $(HEADER_DEPS)
@ -431,7 +467,7 @@ endif
ifeq ($(TARGET),bios)
$(call MKESCAPE,$(BUILDDIR))/%.s2.o: %.s2.c
$(MKDIR_P) "$$(dirname '$(call SHESCAPE,$@)')"
$(CROSS_CC) $(CROSS_CFLAGS) $(S2CFLAGS) -c '$(call SHESCAPE,$<)' -o '$(call SHESCAPE,$@)'
$(CC_FOR_TARGET) $(CFLAGS_FOR_TARGET) $(S2CFLAGS) $(CPPFLAGS_FOR_TARGET) -c '$(call SHESCAPE,$<)' -o '$(call SHESCAPE,$@)'
endif
-include $(HEADER_DEPS)
@ -439,51 +475,51 @@ endif
ifeq ($(TARGET),bios)
$(call MKESCAPE,$(BUILDDIR))/%.o: %.asm_ia32
$(MKDIR_P) "$$(dirname '$(call SHESCAPE,$@)')"
nasm '$(call SHESCAPE,$<)' -F dwarf -g $(WERROR) -f elf32 -o '$(call SHESCAPE,$@)'
nasm '$(call SHESCAPE,$<)' -F dwarf -g -Wall $(WERROR_FLAG) -f elf32 -o '$(call SHESCAPE,$@)'
$(call MKESCAPE,$(BUILDDIR))/%.o: %.asm_bios_ia32
$(MKDIR_P) "$$(dirname '$(call SHESCAPE,$@)')"
nasm '$(call SHESCAPE,$<)' -F dwarf -g $(WERROR) -f elf32 -o '$(call SHESCAPE,$@)'
nasm '$(call SHESCAPE,$<)' -F dwarf -g -Wall $(WERROR_FLAG) -f elf32 -o '$(call SHESCAPE,$@)'
$(call MKESCAPE,$(BUILDDIR))/%.o: %.asm_x86
$(MKDIR_P) "$$(dirname '$(call SHESCAPE,$@)')"
nasm '$(call SHESCAPE,$<)' -F dwarf -g $(WERROR) -f elf32 -o '$(call SHESCAPE,$@)'
nasm '$(call SHESCAPE,$<)' -F dwarf -g -Wall $(WERROR_FLAG) -f elf32 -o '$(call SHESCAPE,$@)'
endif
ifeq ($(TARGET),uefi-x86-64)
$(call MKESCAPE,$(BUILDDIR))/%.o: %.asm_x86_64
$(MKDIR_P) "$$(dirname '$(call SHESCAPE,$@)')"
nasm '$(call SHESCAPE,$<)' -F dwarf -g $(WERROR) -f elf64 -o '$(call SHESCAPE,$@)'
nasm '$(call SHESCAPE,$<)' -F dwarf -g -Wall $(WERROR_FLAG) -f elf64 -o '$(call SHESCAPE,$@)'
$(call MKESCAPE,$(BUILDDIR))/%.o: %.asm_uefi_x86_64
$(MKDIR_P) "$$(dirname '$(call SHESCAPE,$@)')"
nasm '$(call SHESCAPE,$<)' -F dwarf -g $(WERROR) -f elf64 -o '$(call SHESCAPE,$@)'
nasm '$(call SHESCAPE,$<)' -F dwarf -g -Wall $(WERROR_FLAG) -f elf64 -o '$(call SHESCAPE,$@)'
$(call MKESCAPE,$(BUILDDIR))/%.o: %.asm_x86
$(MKDIR_P) "$$(dirname '$(call SHESCAPE,$@)')"
nasm '$(call SHESCAPE,$<)' -F dwarf -g $(WERROR) -f elf64 -o '$(call SHESCAPE,$@)'
nasm '$(call SHESCAPE,$<)' -F dwarf -g -Wall $(WERROR_FLAG) -f elf64 -o '$(call SHESCAPE,$@)'
endif
ifeq ($(TARGET),uefi-aarch64)
$(call MKESCAPE,$(BUILDDIR))/%.o: %.asm_aarch64
$(MKDIR_P) "$$(dirname '$(call SHESCAPE,$@)')"
$(CROSS_CC) $(CROSS_CFLAGS) -x assembler-with-cpp -c '$(call SHESCAPE,$<)' -o '$(call SHESCAPE,$@)'
$(CC_FOR_TARGET) $(CFLAGS_FOR_TARGET) $(CPPFLAGS_FOR_TARGET) -x assembler-with-cpp -c '$(call SHESCAPE,$<)' -o '$(call SHESCAPE,$@)'
$(call MKESCAPE,$(BUILDDIR))/%.o: %.asm_uefi_aarch64
$(MKDIR_P) "$$(dirname '$(call SHESCAPE,$@)')"
$(CROSS_CC) $(CROSS_CFLAGS) -x assembler-with-cpp -c '$(call SHESCAPE,$<)' -o '$(call SHESCAPE,$@)'
$(CC_FOR_TARGET) $(CFLAGS_FOR_TARGET) $(CPPFLAGS_FOR_TARGET) -x assembler-with-cpp -c '$(call SHESCAPE,$<)' -o '$(call SHESCAPE,$@)'
endif
ifeq ($(TARGET),uefi-ia32)
$(call MKESCAPE,$(BUILDDIR))/%.o: %.asm_ia32
$(MKDIR_P) "$$(dirname '$(call SHESCAPE,$@)')"
nasm '$(call SHESCAPE,$<)' -F dwarf -g $(WERROR) -f elf32 -o '$(call SHESCAPE,$@)'
nasm '$(call SHESCAPE,$<)' -F dwarf -g -Wall $(WERROR_FLAG) -f elf32 -o '$(call SHESCAPE,$@)'
$(call MKESCAPE,$(BUILDDIR))/%.o: %.asm_uefi_ia32
$(MKDIR_P) "$$(dirname '$(call SHESCAPE,$@)')"
nasm '$(call SHESCAPE,$<)' -F dwarf -g $(WERROR) -f elf32 -o '$(call SHESCAPE,$@)'
nasm '$(call SHESCAPE,$<)' -F dwarf -g -Wall $(WERROR_FLAG) -f elf32 -o '$(call SHESCAPE,$@)'
$(call MKESCAPE,$(BUILDDIR))/%.o: %.asm_x86
$(MKDIR_P) "$$(dirname '$(call SHESCAPE,$@)')"
nasm '$(call SHESCAPE,$<)' -F dwarf -g $(WERROR) -f elf32 -o '$(call SHESCAPE,$@)'
nasm '$(call SHESCAPE,$<)' -F dwarf -g -Wall $(WERROR_FLAG) -f elf32 -o '$(call SHESCAPE,$@)'
endif

View File

@ -1,7 +1,8 @@
/*
* tinfgzip - tiny gzip decompressor
* originally from tinfgzip - tiny gzip decompressor
*
* Copyright (c) 2003-2019 Joergen Ibsen
* Copyright (c) 2023 mintsuki and contributors to the Limine project
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
@ -23,7 +24,8 @@
* distribution.
*/
#include "tinf.h"
#include <stdint.h>
#include <stb/stb_image.h>
typedef enum {
FTEXT = 1,
@ -31,31 +33,29 @@ typedef enum {
FEXTRA = 4,
FNAME = 8,
FCOMMENT = 16
} tinf_gzip_flag;
} gzip_flag;
int tinf_gzip_uncompress(void *dest,
const void *source, unsigned int sourceLen) {
const unsigned char *src = (const unsigned char *) source;
unsigned char *dst = (unsigned char *) dest;
const unsigned char *start;
void *gzip_uncompress(const void *source, uint64_t sourceLen, uint64_t *outsize) {
const uint8_t *src = (const uint8_t *) source;
const uint8_t *start;
int res;
unsigned char flg;
uint8_t flg;
/* -- Check header -- */
/* Check room for at least 10 byte header and 8 byte trailer */
if (sourceLen < 18) {
return TINF_DATA_ERROR;
return NULL;
}
/* Check id bytes */
if (src[0] != 0x1F || src[1] != 0x8B) {
return TINF_DATA_ERROR;
return NULL;
}
/* Check method is deflate */
if (src[2] != 8) {
return TINF_DATA_ERROR;
return NULL;
}
/* Get flag byte */
@ -63,7 +63,7 @@ int tinf_gzip_uncompress(void *dest,
/* Check that reserved bits are zero */
if (flg & 0xE0) {
return TINF_DATA_ERROR;
return NULL;
}
/* -- Find start of compressed data -- */
@ -73,10 +73,10 @@ int tinf_gzip_uncompress(void *dest,
/* Skip extra data if present */
if (flg & FEXTRA) {
unsigned int xlen = *start;
uint64_t xlen = *((uint16_t *)start);
if (xlen > sourceLen - 12) {
return TINF_DATA_ERROR;
return NULL;
}
start += xlen + 2;
@ -85,8 +85,8 @@ int tinf_gzip_uncompress(void *dest,
/* Skip file name if present */
if (flg & FNAME) {
do {
if (((unsigned int)(start - src)) >= sourceLen) {
return TINF_DATA_ERROR;
if (((uint64_t)(start - src)) >= sourceLen) {
return NULL;
}
} while (*start++);
}
@ -94,8 +94,8 @@ int tinf_gzip_uncompress(void *dest,
/* Skip file comment if present */
if (flg & FCOMMENT) {
do {
if (((unsigned int)(start - src)) >= sourceLen) {
return TINF_DATA_ERROR;
if (((uint64_t)(start - src)) >= sourceLen) {
return NULL;
}
} while (*start++);
}
@ -104,17 +104,25 @@ int tinf_gzip_uncompress(void *dest,
start += 2;
}
/* -- Get decompressed length -- */
uint32_t dlen = *((uint32_t *)&src[sourceLen - 4]);
/* -- Decompress data -- */
if ((src + sourceLen) - start < 8) {
return TINF_DATA_ERROR;
return NULL;
}
res = tinf_uncompress(dst, start,
(src + sourceLen) - start - 8);
void *buf = ext_mem_alloc(dlen);
if (res != TINF_OK) {
return TINF_DATA_ERROR;
res = stbi_zlib_decode_noheader_buffer(buf, dlen, (const char *)start, (src + sourceLen) - start - 8);
if (res == -1) {
pmm_free(buf, dlen);
return NULL;
}
return TINF_OK;
*outsize = (uint64_t)dlen;
return buf;
}

8
common/compress/gzip.h Normal file
View File

@ -0,0 +1,8 @@
#ifndef __COMPRESS__GZIP_H__
#define __COMPRESS__GZIP_H__
#include <stdint.h>
void *gzip_uncompress(const void *source, uint64_t sourceLen, uint64_t *outsize);
#endif

View File

@ -19,6 +19,10 @@ static void console_help(void) {
"clear -- Clear the console.\n"
"%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",
@ -26,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");
@ -49,6 +57,18 @@ void console(void) {
config_ready = true;
boot(new_entry);
}
} else if (strcmp(prompt, "firmware") == 0) {
#if defined (BIOS)
print("BIOS\n");
#elif defined (UEFI)
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");
} else if (strcmp(prompt, "copyright") == 0) {

209
common/crypt/blake2b.c Normal file
View File

@ -0,0 +1,209 @@
// This blake2b implementation comes from the GNU coreutils project.
// https://github.com/coreutils/coreutils/blob/master/src/blake2/blake2b-ref.c
#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>
#include <crypt/blake2b.h>
#include <lib/libc.h>
#define BLAKE2B_BLOCK_BYTES 128
#define BLAKE2B_KEY_BYTES 64
#define BLAKE2B_SALT_BYTES 16
#define BLAKE2B_PERSONAL_BYTES 16
static const uint64_t blake2b_iv[8] = {
0x6a09e667f3bcc908,
0xbb67ae8584caa73b,
0x3c6ef372fe94f82b,
0xa54ff53a5f1d36f1,
0x510e527fade682d1,
0x9b05688c2b3e6c1f,
0x1f83d9abfb41bd6b,
0x5be0cd19137e2179,
};
static const uint8_t blake2b_sigma[12][16] = {
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
{ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 },
{ 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 },
{ 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 },
{ 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 },
{ 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 },
{ 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 },
{ 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 },
{ 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 },
{ 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 },
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
{ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 },
};
struct blake2b_state {
uint64_t h[8];
uint64_t t[2];
uint64_t f[2];
uint8_t buf[BLAKE2B_BLOCK_BYTES];
size_t buf_len;
uint8_t last_node;
};
struct blake2b_param {
uint8_t digest_length;
uint8_t key_length;
uint8_t fan_out;
uint8_t depth;
uint32_t leaf_length;
uint32_t node_offset;
uint32_t xof_length;
uint8_t node_depth;
uint8_t inner_length;
uint8_t reserved[14];
uint8_t salt[BLAKE2B_SALT_BYTES];
uint8_t personal[BLAKE2B_PERSONAL_BYTES];
} __attribute__((packed));
static void blake2b_increment_counter(struct blake2b_state *state, uint64_t inc) {
state->t[0] += inc;
state->t[1] += state->t[0] < inc;
}
static inline uint64_t rotr64(uint64_t w, unsigned c) {
return (w >> c) | (w << (64 - c));
}
#define G(r, i, a, b, c, d) do { \
a = a + b + m[blake2b_sigma[r][2 * i + 0]]; \
d = rotr64(d ^ a, 32); \
c = c + d; \
b = rotr64(b ^ c, 24); \
a = a + b + m[blake2b_sigma[r][2 * i + 1]]; \
d = rotr64(d ^ a, 16); \
c = c + d; \
b = rotr64(b ^ c, 63); \
} while (0)
#define ROUND(r) do { \
G(r, 0, v[0], v[4], v[8], v[12]); \
G(r, 1, v[1], v[5], v[9], v[13]); \
G(r, 2, v[2], v[6], v[10], v[14]); \
G(r, 3, v[3], v[7], v[11], v[15]); \
G(r, 4, v[0], v[5], v[10], v[15]); \
G(r, 5, v[1], v[6], v[11], v[12]); \
G(r, 6, v[2], v[7], v[8], v[13]); \
G(r, 7, v[3], v[4], v[9], v[14]); \
} while (0)
static void blake2b_compress(struct blake2b_state *state, const uint8_t block[static BLAKE2B_BLOCK_BYTES]) {
uint64_t m[16];
uint64_t v[16];
for (int i = 0; i < 16; i++) {
m[i] = *(uint64_t *)(block + i * sizeof(m[i]));
}
for (int i = 0; i < 8; i++) {
v[i] = state->h[i];
}
v[8] = blake2b_iv[0];
v[9] = blake2b_iv[1];
v[10] = blake2b_iv[2];
v[11] = blake2b_iv[3];
v[12] = blake2b_iv[4] ^ state->t[0];
v[13] = blake2b_iv[5] ^ state->t[1];
v[14] = blake2b_iv[6] ^ state->f[0];
v[15] = blake2b_iv[7] ^ state->f[1];
ROUND(0);
ROUND(1);
ROUND(2);
ROUND(3);
ROUND(4);
ROUND(5);
ROUND(6);
ROUND(7);
ROUND(8);
ROUND(9);
ROUND(10);
ROUND(11);
for (int i = 0; i < 8; i++) {
state->h[i] = state->h[i] ^ v[i] ^ v[i + 8];
}
}
#undef G
#undef ROUND
static void blake2b_init(struct blake2b_state *state) {
struct blake2b_param param = {0};
param.digest_length = BLAKE2B_OUT_BYTES;
param.fan_out = 1;
param.depth = 1;
memset(state, 0, sizeof(struct blake2b_state));
for (int i = 0; i < 8; i++) {
state->h[i] = blake2b_iv[i];
}
for (int i = 0; i < 8; i++) {
state->h[i] ^= *(uint64_t *)((void *)&param + sizeof(state->h[i]) * i);
}
}
static void blake2b_update(struct blake2b_state *state, const void *in, size_t in_len) {
if (in_len == 0) {
return;
}
size_t left = state->buf_len;
size_t fill = BLAKE2B_BLOCK_BYTES - left;
if (in_len > fill) {
state->buf_len = 0;
memcpy(state->buf + left, in, fill);
blake2b_increment_counter(state, BLAKE2B_BLOCK_BYTES);
blake2b_compress(state, state->buf);
in += fill;
in_len -= fill;
while (in_len > BLAKE2B_BLOCK_BYTES) {
blake2b_increment_counter(state, BLAKE2B_BLOCK_BYTES);
blake2b_compress(state, in);
in += fill;
in_len -= fill;
}
}
memcpy(state->buf + state->buf_len, in, in_len);
state->buf_len += in_len;
}
static void blake2b_final(struct blake2b_state *state, void *out) {
uint8_t buffer[BLAKE2B_OUT_BYTES] = {0};
blake2b_increment_counter(state, state->buf_len);
state->f[0] = (uint64_t)-1;
memset(state->buf + state->buf_len, 0, BLAKE2B_BLOCK_BYTES - state->buf_len);
blake2b_compress(state, state->buf);
for (int i = 0; i < 8; i++) {
*(uint64_t *)(buffer + sizeof(state->h[i]) * i) = state->h[i];
}
memcpy(out, buffer, BLAKE2B_OUT_BYTES);
memset(buffer, 0, sizeof(buffer));
}
void blake2b(void *out, const void *in, size_t in_len) {
struct blake2b_state state = {0};
blake2b_init(&state);
blake2b_update(&state, in, in_len);
blake2b_final(&state, out);
}

10
common/crypt/blake2b.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef __CRYPT__BLAKE2B_H__
#define __CRYPT__BLAKE2B_H__
#include <stddef.h>
#define BLAKE2B_OUT_BYTES 64
void blake2b(void *out, const void *in, size_t in_len);
#endif

View File

@ -7,12 +7,14 @@
# include <lib/real.h>
#elif defined (UEFI)
# include <efi.h>
# include <crypt/blake2b.h>
#endif
#include <lib/misc.h>
#include <lib/print.h>
#include <lib/rand.h>
#include <mm/pmm.h>
#include <sys/cpu.h>
#include <pxe/pxe.h>
#define DEFAULT_FASTEST_XFER_SIZE 64
#define MAX_FASTEST_XFER_SIZE 512
@ -125,6 +127,39 @@ int disk_read_sectors(struct volume *volume, void *buf, uint64_t block, size_t c
return DISK_SUCCESS;
}
static int disk_write_sectors(struct volume *volume, void *buf, uint64_t block, size_t count) {
struct dap dap = {0};
if (count * volume->sector_size > XFER_BUF_SIZE)
panic(false, "XFER");
if (xfer_buf == NULL)
xfer_buf = conv_mem_alloc(XFER_BUF_SIZE);
dap.size = 16;
dap.count = count;
dap.segment = rm_seg(xfer_buf);
dap.offset = rm_off(xfer_buf);
dap.lba = block;
struct rm_regs r = {0};
r.eax = 0x4301;
r.edx = volume->drive;
r.esi = (uint32_t)rm_off(&dap);
r.ds = rm_seg(&dap);
if (buf != NULL)
memcpy(xfer_buf, buf, count * volume->sector_size);
rm_int(0x13, &r, &r);
if (r.eflags & EFLAGS_CF) {
return DISK_FAILURE;
}
return DISK_SUCCESS;
}
static bool detect_sector_size(struct volume *volume) {
struct dap dap = {0};
@ -183,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;
}
@ -192,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;
@ -225,14 +259,14 @@ void disk_create_index(void) {
continue;
}
if (drive_params.info_flags & (1 << 2) && drive > 0x8f) {
// The medium could not be present (e.g.: CD-ROMs)
// Do a test run to see if we can actually read it
if (disk_read_sectors(block, NULL, 0, 1) != DISK_SUCCESS) {
continue;
}
if (disk_read_sectors(block, xfer_buf, 0, 1) != DISK_SUCCESS) {
continue;
}
block->is_optical = disk_write_sectors(block, xfer_buf, 0, 1) != DISK_SUCCESS;
if (block->is_optical) {
block->index = optical_indices++;
block->is_optical = true;
} else {
block->index = hdd_indices++;
}
@ -243,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++) {
@ -254,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++;
@ -279,6 +321,38 @@ int disk_read_sectors(struct volume *volume, void *buf, uint64_t block, size_t c
}
}
static struct volume *pxe_from_efi_handle(EFI_HANDLE efi_handle) {
static struct volume *vol = NULL;
// There's only one PXE volume
if (vol) {
return vol;
}
EFI_STATUS status;
EFI_GUID pxe_base_code_guid = EFI_PXE_BASE_CODE_PROTOCOL_GUID;
EFI_PXE_BASE_CODE *pxe_base_code = NULL;
status = gBS->HandleProtocol(efi_handle, &pxe_base_code_guid, (void **)&pxe_base_code);
if (status) {
return NULL;
}
if (!pxe_base_code->Mode->DhcpDiscoverValid) {
print("PXE somehow didn't use DHCP?\n");
return NULL;
}
if (pxe_base_code->Mode->UsingIpv6) {
print("Sorry, unsupported: PXE IPv6\n");
return NULL;
}
vol = pxe_bind_volume(efi_handle, pxe_base_code);
return vol;
}
static alignas(4096) uint8_t unique_sector_pool[4096];
struct volume *disk_volume_from_efi_handle(EFI_HANDLE efi_handle) {
@ -289,9 +363,11 @@ struct volume *disk_volume_from_efi_handle(EFI_HANDLE efi_handle) {
status = gBS->HandleProtocol(efi_handle, &block_io_guid, (void **)&block_io);
if (status) {
return NULL;
return pxe_from_efi_handle(efi_handle);
}
block_io->Media->WriteCaching = false;
for (size_t i = 0; i < volume_index_i; i++) {
if (volume_index[i]->unique_sector_valid == false) {
continue;
@ -311,33 +387,29 @@ struct volume *disk_volume_from_efi_handle(EFI_HANDLE efi_handle) {
continue;
}
uint32_t crc32 = get_crc32(unique_sector_pool, 4096);
uint8_t b2b[BLAKE2B_OUT_BYTES];
blake2b(b2b, unique_sector_pool, 4096);
if (crc32 == volume_index[i]->unique_sector_crc32) {
if (memcmp(b2b, volume_index[i]->unique_sector_b2b, BLAKE2B_OUT_BYTES) == 0) {
return volume_index[i];
}
}
// Fallback to read-back method
EFI_GUID disk_io_guid = DISK_IO_PROTOCOL;
EFI_DISK_IO *disk_io = NULL;
status = gBS->HandleProtocol(efi_handle, &disk_io_guid, (void **)&disk_io);
if (status)
return NULL;
uint64_t signature = rand64();
uint64_t new_signature;
do { new_signature = rand64(); } while (new_signature == signature);
uint64_t orig;
status = disk_io->ReadDisk(disk_io, block_io->Media->MediaId, 0, sizeof(uint64_t), &orig);
status = block_io->ReadBlocks(block_io, block_io->Media->MediaId, 0, 4096, unique_sector_pool);
orig = *(uint64_t *)unique_sector_pool;
if (status) {
return NULL;
}
status = disk_io->WriteDisk(disk_io, block_io->Media->MediaId, 0, sizeof(uint64_t), &signature);
*(uint64_t *)unique_sector_pool = signature;
status = block_io->WriteBlocks(block_io, block_io->Media->MediaId, 0, 4096, unique_sector_pool);
if (status) {
return NULL;
}
@ -346,35 +418,59 @@ struct volume *disk_volume_from_efi_handle(EFI_HANDLE efi_handle) {
for (size_t i = 0; i < volume_index_i; i++) {
uint64_t compare;
EFI_DISK_IO *cur_disk_io = NULL;
gBS->HandleProtocol(volume_index[i]->efi_handle,
&disk_io_guid, (void **)&cur_disk_io);
cur_disk_io->ReadDisk(cur_disk_io,
status = volume_index[i]->block_io->ReadBlocks(volume_index[i]->block_io,
volume_index[i]->block_io->Media->MediaId,
0 + volume_index[i]->first_sect * 512,
sizeof(uint64_t), &compare);
(volume_index[i]->first_sect * 512) / volume_index[i]->sector_size,
4096, unique_sector_pool);
compare = *(uint64_t *)unique_sector_pool;
if (status) {
continue;
}
if (compare == signature) {
// Double check
status = disk_io->WriteDisk(disk_io, block_io->Media->MediaId, 0, sizeof(uint64_t), &new_signature);
status = block_io->ReadBlocks(block_io, block_io->Media->MediaId, 0, 4096, unique_sector_pool);
if (status) {
break;
}
*(uint64_t *)unique_sector_pool = new_signature;
status = block_io->WriteBlocks(block_io, block_io->Media->MediaId, 0, 4096, unique_sector_pool);
if (status) {
break;
}
cur_disk_io->ReadDisk(cur_disk_io,
status = volume_index[i]->block_io->ReadBlocks(volume_index[i]->block_io,
volume_index[i]->block_io->Media->MediaId,
0 + volume_index[i]->first_sect * 512,
sizeof(uint64_t), &compare);
(volume_index[i]->first_sect * 512) / volume_index[i]->sector_size,
4096, unique_sector_pool);
compare = *(uint64_t *)unique_sector_pool;
if (status) {
continue;
}
if (compare == new_signature) {
ret = volume_index[i];
break;
}
status = disk_io->WriteDisk(disk_io, block_io->Media->MediaId, 0, sizeof(uint64_t), &signature);
status = block_io->ReadBlocks(block_io, block_io->Media->MediaId, 0, 4096, unique_sector_pool);
if (status) {
break;
}
*(uint64_t *)unique_sector_pool = signature;
status = block_io->WriteBlocks(block_io, block_io->Media->MediaId, 0, 4096, unique_sector_pool);
if (status) {
break;
}
}
}
status = disk_io->WriteDisk(disk_io, block_io->Media->MediaId, 0, sizeof(uint64_t), &orig);
status = block_io->ReadBlocks(block_io, block_io->Media->MediaId, 0, 4096, unique_sector_pool);
if (status) {
return NULL;
}
*(uint64_t *)unique_sector_pool = orig;
status = block_io->WriteBlocks(block_io, block_io->Media->MediaId, 0, 4096, unique_sector_pool);
if (status) {
return NULL;
}
@ -386,14 +482,14 @@ struct volume *disk_volume_from_efi_handle(EFI_HANDLE efi_handle) {
return NULL;
}
static struct volume *volume_by_unique_sector(uint64_t sect, uint32_t crc32) {
static struct volume *volume_by_unique_sector(uint64_t sect, void *b2b) {
for (size_t i = 0; i < volume_index_i; i++) {
if (volume_index[i]->unique_sector_valid == false) {
continue;
}
if (volume_index[i]->unique_sector == sect
&& volume_index[i]->unique_sector_crc32 == crc32) {
&& memcmp(volume_index[i]->unique_sector_b2b, b2b, BLAKE2B_OUT_BYTES) == 0) {
return volume_index[i];
}
}
@ -424,14 +520,15 @@ static void find_unique_sectors(void) {
break;
}
uint32_t crc32 = get_crc32(unique_sector_pool, 4096);
uint8_t b2b[BLAKE2B_OUT_BYTES];
blake2b(b2b, unique_sector_pool, 4096);
uint64_t uniq = (uint64_t)j * volume_index[i]->block_io->Media->BlockSize;
if (volume_by_unique_sector(uniq, crc32) == NULL) {
if (volume_by_unique_sector(uniq, b2b) == NULL) {
volume_index[i]->unique_sector_valid = true;
volume_index[i]->unique_sector = uniq;
volume_index[i]->unique_sector_crc32 = crc32;
memcpy(volume_index[i]->unique_sector_b2b, b2b, BLAKE2B_OUT_BYTES);
break;
}
}
@ -455,11 +552,19 @@ void disk_create_index(void) {
EFI_GUID block_io_guid = BLOCK_IO_PROTOCOL;
EFI_HANDLE *handles = tmp_handles;
UINTN handles_size = sizeof(EFI_HANDLE);
UINTN handles_size = sizeof(tmp_handles);
status = gBS->LocateHandle(ByProtocol, &block_io_guid, NULL, &handles_size, handles);
// we only care about the first handle, so ignore if we get EFI_BUFFER_TOO_SMALL
if (status != EFI_BUFFER_TOO_SMALL && status != EFI_SUCCESS) {
EFI_GUID pxe_guid = EFI_PXE_BASE_CODE_PROTOCOL_GUID;
status = gBS->LocateHandle(ByProtocol, &pxe_guid, NULL, &handles_size, handles);
// likewise, all that matters is that the protocol is present
if (status == EFI_BUFFER_TOO_SMALL || status == EFI_SUCCESS) {
return;
}
goto fail;
}
@ -479,16 +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_GUID disk_io_guid = DISK_IO_PROTOCOL;
EFI_DISK_IO *disk_io = NULL;
gBS->HandleProtocol(handles[i], &disk_io_guid, (void **)&disk_io);
EFI_BLOCK_IO *drive = NULL;
status = gBS->HandleProtocol(handles[i], &block_io_guid, (void **)&drive);
@ -499,13 +594,18 @@ fail:
if (drive->Media->LogicalPartition)
continue;
uint64_t orig;
disk_io->ReadDisk(disk_io, drive->Media->MediaId, 0, sizeof(uint64_t), &orig);
status = disk_io->WriteDisk(disk_io, drive->Media->MediaId, 0, sizeof(uint64_t), &orig);
drive->Media->WriteCaching = false;
status = drive->ReadBlocks(drive, drive->Media->MediaId, 0, 4096, unique_sector_pool);
if (status) {
continue;
}
status = drive->WriteBlocks(drive, drive->Media->MediaId, 0, 4096, unique_sector_pool);
struct volume *block = ext_mem_alloc(sizeof(struct volume));
if (status) {
if (status || drive->Media->ReadOnly) {
block->index = optical_indices++;
block->is_optical = true;
} else {
@ -534,17 +634,29 @@ 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++) {
struct volume *p = ext_mem_alloc(sizeof(struct volume));
int ret = part_get(p, block, part);
struct volume _p = {0};
int ret = part_get(&_p, block, part);
if (ret == END_OF_TABLE || ret == INVALID_TABLE)
break;
if (ret == NO_PARTITION)
continue;
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

@ -1,5 +1,6 @@
#include <stdint.h>
#include <stddef.h>
#include <drivers/gop.h>
#include <drivers/edid.h>
#include <mm/pmm.h>
#include <lib/misc.h>
@ -49,33 +50,15 @@ success:
#include <efi.h>
struct edid_info_struct *get_edid_info(void) {
struct edid_info_struct *get_edid_info(EFI_HANDLE gop_handle) {
struct edid_info_struct *buf = ext_mem_alloc(sizeof(struct edid_info_struct));
EFI_STATUS status;
EFI_HANDLE tmp_handles[1];
EFI_HANDLE *handles = tmp_handles;
UINTN handles_size = sizeof(EFI_HANDLE);
EFI_GUID gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
status = gBS->LocateHandle(ByProtocol, &gop_guid, NULL, &handles_size, handles);
if (status != EFI_SUCCESS && status != EFI_BUFFER_TOO_SMALL)
goto fail_n;
handles = ext_mem_alloc(handles_size);
status = gBS->LocateHandle(ByProtocol, &gop_guid, NULL, &handles_size, handles);
if (status)
goto fail;
EFI_EDID_ACTIVE_PROTOCOL *edid = NULL;
EFI_GUID edid_guid = EFI_EDID_ACTIVE_PROTOCOL_GUID;
status = gBS->HandleProtocol(handles[0], &edid_guid, (void **)&edid);
status = gBS->HandleProtocol(gop_handle, &edid_guid, (void **)&edid);
if (status)
goto fail;
@ -90,13 +73,10 @@ struct edid_info_struct *get_edid_info(void) {
goto success;
fail:
pmm_free(handles, handles_size);
fail_n:
printv("edid: Could not fetch EDID data.\n");
return NULL;
success:
pmm_free(handles, handles_size);
printv("edid: Success.\n");
return buf;
}

View File

@ -30,6 +30,14 @@ struct edid_info_struct {
uint8_t checksum;
} __attribute__((packed));
#if defined (UEFI)
#include <efi.h>
struct edid_info_struct *get_edid_info(EFI_HANDLE gop_handle);
#endif
#if defined (BIOS)
struct edid_info_struct *get_edid_info(void);
#endif
#endif

View File

@ -37,10 +37,7 @@ static void linear_mask_to_mask_shift(
// Most of this code taken from https://wiki.osdev.org/GOP
bool gop_force_16 = false;
static bool try_mode(EFI_GRAPHICS_OUTPUT_PROTOCOL *gop,
struct fb_info *ret, size_t mode, uint64_t width, uint64_t height, int bpp) {
static bool mode_to_fb_info(struct fb_info *ret, EFI_GRAPHICS_OUTPUT_PROTOCOL *gop, size_t mode) {
EFI_STATUS status;
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *mode_info;
@ -48,8 +45,9 @@ static bool try_mode(EFI_GRAPHICS_OUTPUT_PROTOCOL *gop,
status = gop->QueryMode(gop, mode, &mode_info_size, &mode_info);
if (status)
if (status) {
return false;
}
switch (mode_info->PixelFormat) {
case PixelBlueGreenRedReserved8BitPerColor:
@ -87,59 +85,104 @@ static bool try_mode(EFI_GRAPHICS_OUTPUT_PROTOCOL *gop,
mode_info->PixelInformation.BlueMask);
break;
default:
panic(false, "gop: Invalid PixelFormat");
}
if (width != 0 && height != 0 && bpp != 0) {
if ((uint64_t)mode_info->HorizontalResolution != width
|| (uint64_t)mode_info->VerticalResolution != height
|| (int)ret->framebuffer_bpp != bpp)
return false;
}
ret->memory_model = 0x06;
ret->framebuffer_pitch = mode_info->PixelsPerScanLine * (ret->framebuffer_bpp / 8);
ret->framebuffer_width = mode_info->HorizontalResolution;
ret->framebuffer_height = mode_info->VerticalResolution;
return true;
}
bool gop_force_16 = false;
static bool try_mode(struct fb_info *ret, EFI_GRAPHICS_OUTPUT_PROTOCOL *gop,
size_t mode, uint64_t width, uint64_t height, int bpp,
struct fb_info *fbs, size_t fbs_count) {
EFI_STATUS status;
if (!mode_to_fb_info(ret, gop, mode)) {
return false;
}
if (width != 0 && height != 0 && bpp != 0) {
if (ret->framebuffer_width != width
|| ret->framebuffer_height != height
|| ret->framebuffer_bpp != bpp) {
return false;
}
}
if (gop_force_16) {
if (mode_info->HorizontalResolution >= 65536
|| mode_info->VerticalResolution >= 65536
|| mode_info->PixelsPerScanLine * (ret->framebuffer_bpp / 8) >= 65536) {
if (ret->framebuffer_width >= 65536
|| ret->framebuffer_height >= 65536
|| ret->framebuffer_pitch >= 65536) {
return false;
}
}
for (size_t i = 0; i < fbs_count; i++) {
if (gop->Mode->FrameBufferBase == fbs[i].framebuffer_addr) {
return false;
}
}
printv("gop: Found matching mode %x, attempting to set...\n", mode);
if ((int)mode == current_video_mode) {
if (mode == gop->Mode->Mode) {
printv("gop: Mode was already set, perfect!\n");
} else {
status = gop->SetMode(gop, mode);
if (status) {
current_video_mode = -1;
printv("gop: Failed to set video mode %x, moving on...\n", mode);
return false;
}
}
current_video_mode = mode;
ret->memory_model = 0x06;
ret->framebuffer_addr = gop->Mode->FrameBufferBase;
ret->framebuffer_pitch = gop->Mode->Info->PixelsPerScanLine * (ret->framebuffer_bpp / 8);
ret->framebuffer_width = gop->Mode->Info->HorizontalResolution;
ret->framebuffer_height = gop->Mode->Info->VerticalResolution;
fb_clear(ret);
return true;
}
#define INVALID_PRESET_MODE 0xffffffff
static struct fb_info *get_mode_list(size_t *count, EFI_GRAPHICS_OUTPUT_PROTOCOL *gop) {
UINTN modes_count = gop->Mode->MaxMode;
static no_unwind size_t preset_mode = INVALID_PRESET_MODE;
static no_unwind EFI_GRAPHICS_OUTPUT_MODE_INFORMATION preset_mode_info;
struct fb_info *ret = ext_mem_alloc(modes_count * sizeof(struct fb_info));
bool init_gop(struct fb_info *ret,
size_t actual_count = 0;
for (size_t i = 0; i < modes_count; i++) {
if (mode_to_fb_info(&ret[actual_count], gop, i)) {
actual_count++;
}
}
struct fb_info *tmp = ext_mem_alloc(actual_count * sizeof(struct fb_info));
memcpy(tmp, ret, actual_count * sizeof(struct fb_info));
pmm_free(ret, modes_count * sizeof(struct fb_info));
ret = tmp;
*count = modes_count;
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) {
ret->default_res = false;
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;
@ -152,7 +195,8 @@ bool init_gop(struct fb_info *ret,
status = gBS->LocateHandle(ByProtocol, &gop_guid, NULL, &handles_size, handles);
if (status != EFI_SUCCESS && status != EFI_BUFFER_TOO_SMALL) {
return false;
*_fbs_count = 0;
return;
}
handles = ext_mem_alloc(handles_size);
@ -160,45 +204,15 @@ bool init_gop(struct fb_info *ret,
status = gBS->LocateHandle(ByProtocol, &gop_guid, NULL, &handles_size, handles);
if (status != EFI_SUCCESS) {
pmm_free(handles, handles_size);
return false;
*_fbs_count = 0;
return;
}
EFI_HANDLE gop_handle = handles[0];
pmm_free(handles, handles_size);
size_t handles_count = handles_size / sizeof(EFI_HANDLE);
EFI_GRAPHICS_OUTPUT_PROTOCOL *gop;
*ret = ext_mem_alloc(handles_count * sizeof(struct fb_info));
status = gBS->HandleProtocol(gop_handle, &gop_guid, (void **)&gop);
if (status != EFI_SUCCESS) {
return false;
}
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *mode_info;
UINTN mode_info_size;
status = gop->QueryMode(gop, gop->Mode == NULL ? 0 : gop->Mode->Mode,
&mode_info_size, &mode_info);
if (status == EFI_NOT_STARTED) {
status = gop->SetMode(gop, 0);
if (status) {
panic(false, "gop: Initialisation failed");
}
status = gop->QueryMode(gop, gop->Mode == NULL ? 0 : gop->Mode->Mode,
&mode_info_size, &mode_info);
}
if (status) {
panic(false, "gop: Initialisation failed");
}
if (preset_mode == INVALID_PRESET_MODE) {
preset_mode = gop->Mode->Mode;
memcpy(&preset_mode_info, mode_info, mode_info_size);
current_video_mode = preset_mode;
}
struct resolution fallback_resolutions[] = {
const struct resolution fallback_resolutions[] = {
{ 0, 0, 0 }, // Overridden by EDID
{ 0, 0, 0 }, // Overridden by preset
{ 1024, 768, 32 },
@ -212,67 +226,115 @@ bool init_gop(struct fb_info *ret,
{ 640, 480, 16 }
};
UINTN modes_count = gop->Mode->MaxMode;
size_t fbs_count = 0;
for (size_t i = 0; i < handles_count && i < MAX_PRESET_MODES; i++) {
struct fb_info *fb = &(*ret)[fbs_count];
size_t current_fallback = 0;
uint64_t _target_width = target_width;
uint64_t _target_height = target_height;
uint64_t _target_bpp = target_bpp;
if (!target_width || !target_height || !target_bpp) {
goto fallback;
} else {
printv("gop: Requested resolution of %ux%ux%u\n",
target_width, target_height, target_bpp);
}
EFI_GRAPHICS_OUTPUT_PROTOCOL *gop;
status = gBS->HandleProtocol(handles[i], &gop_guid, (void **)&gop);
if (status != EFI_SUCCESS) {
continue;
}
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *mode_info;
UINTN mode_info_size;
status = gop->QueryMode(gop, gop->Mode == NULL ? 0 : gop->Mode->Mode,
&mode_info_size, &mode_info);
if (status == EFI_NOT_STARTED) {
status = gop->SetMode(gop, 0);
if (status) {
continue;
}
status = gop->QueryMode(gop, gop->Mode == NULL ? 0 : gop->Mode->Mode,
&mode_info_size, &mode_info);
}
if (status) {
continue;
}
if (preset_modes[i] == -1) {
preset_modes[i] = gop->Mode->Mode;
}
fb->edid = get_edid_info(handles[i]);
UINTN modes_count = gop->Mode->MaxMode;
size_t current_fallback = 0;
if (!_target_width || !_target_height || !_target_bpp) {
goto fallback;
} else {
printv("gop: Requested resolution of %ux%ux%u\n",
_target_width, _target_height, _target_bpp);
}
retry:
for (size_t i = 0; i < modes_count; i++) {
if (try_mode(gop, ret, i, target_width, target_height, target_bpp)) {
gop_force_16 = false;
return true;
}
}
fallback:
ret->default_res = true;
if (current_fallback == 0) {
current_fallback++;
struct edid_info_struct *edid_info = get_edid_info();
if (edid_info != NULL) {
uint64_t edid_width = (uint64_t)edid_info->det_timing_desc1[2];
edid_width += ((uint64_t)edid_info->det_timing_desc1[4] & 0xf0) << 4;
uint64_t edid_height = (uint64_t)edid_info->det_timing_desc1[5];
edid_height += ((uint64_t)edid_info->det_timing_desc1[7] & 0xf0) << 4;
if (edid_width >= preset_mode_info.HorizontalResolution
&& edid_height >= preset_mode_info.VerticalResolution) {
target_width = edid_width;
target_height = edid_height;
target_bpp = 32;
goto retry;
for (size_t j = 0; j < modes_count; j++) {
if (try_mode(fb, gop, j, _target_width, _target_height, _target_bpp, *ret, fbs_count)) {
goto success;
}
}
}
if (current_fallback == 1) {
current_fallback++;
fallback:
if (current_fallback == 0) {
current_fallback++;
if (try_mode(gop, ret, preset_mode, 0, 0, 0)) {
gop_force_16 = false;
return true;
if (fb->edid != NULL) {
uint64_t edid_width = (uint64_t)fb->edid->det_timing_desc1[2];
edid_width += ((uint64_t)fb->edid->det_timing_desc1[4] & 0xf0) << 4;
uint64_t edid_height = (uint64_t)fb->edid->det_timing_desc1[5];
edid_height += ((uint64_t)fb->edid->det_timing_desc1[7] & 0xf0) << 4;
if (edid_width >= mode_info->HorizontalResolution
&& edid_height >= mode_info->VerticalResolution) {
_target_width = edid_width;
_target_height = edid_height;
_target_bpp = 32;
goto retry;
}
}
}
if (current_fallback == 1) {
current_fallback++;
if (try_mode(fb, gop, preset_modes[i], 0, 0, 0, *ret, fbs_count)) {
goto success;
}
}
if (current_fallback < SIZEOF_ARRAY(fallback_resolutions)) {
current_fallback++;
_target_width = fallback_resolutions[current_fallback].width;
_target_height = fallback_resolutions[current_fallback].height;
_target_bpp = fallback_resolutions[current_fallback].bpp;
goto retry;
}
continue;
success:;
size_t mode_count;
fb->mode_list = get_mode_list(&mode_count, gop);
fb->mode_count = mode_count;
fbs_count++;
}
if (current_fallback < SIZEOF_ARRAY(fallback_resolutions)) {
current_fallback++;
target_width = fallback_resolutions[current_fallback].width;
target_height = fallback_resolutions[current_fallback].height;
target_bpp = fallback_resolutions[current_fallback].bpp;
goto retry;
}
pmm_free(handles, handles_size);
gop_force_16 = false;
return false;
*_fbs_count = fbs_count;
}
#endif

View File

@ -4,11 +4,11 @@
#if defined (UEFI)
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <efi.h>
#include <lib/fb.h>
bool init_gop(struct fb_info *ret,
void init_gop(struct fb_info **ret, size_t *_fbs_count,
uint64_t target_width, uint64_t target_height, uint16_t target_bpp);
extern bool gop_force_16;

View File

@ -1,12 +1,13 @@
#ifndef __DRIVERS__SERIAL_H__
#define __DRIVERS__SERIAL_H__
#if defined (BIOS)
#include <stdint.h>
void serial_out(uint8_t b);
#if defined (BIOS)
int serial_in(void);
#endif
#endif

View File

@ -1,38 +1,19 @@
#if defined (BIOS)
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <drivers/serial.h>
#include <sys/cpu.h>
#include <lib/misc.h>
#if defined (UEFI)
# include <efi.h>
#endif
static bool serial_initialised = false;
#if defined (UEFI)
static EFI_SERIAL_IO_PROTOCOL *serial_protocol;
#endif
static void serial_initialise(void) {
if (serial_initialised) {
return;
}
#if defined (UEFI)
EFI_STATUS status;
EFI_GUID serial_guid = EFI_SERIAL_IO_PROTOCOL_GUID;
status = gBS->LocateProtocol(&serial_guid, NULL, (void **)&serial_protocol);
if (status) {
return;
}
serial_protocol->Reset(serial_protocol);
#endif
#if defined (BIOS)
// Init com1
outb(0x3f8 + 3, 0x00);
outb(0x3f8 + 1, 0x00);
@ -42,30 +23,17 @@ static void serial_initialise(void) {
outb(0x3f8 + 3, 0x03);
outb(0x3f8 + 2, 0xc7);
outb(0x3f8 + 4, 0x0b);
#endif
serial_initialised = true;
}
void serial_out(uint8_t b) {
#if defined (UEFI)
if (efi_boot_services_exited) {
return;
}
#endif
serial_initialise();
#if defined (UEFI)
UINTN bsize = 1;
serial_protocol->Write(serial_protocol, &bsize, &b);
#elif defined (BIOS)
while ((inb(0x3f8 + 5) & 0x20) == 0);
outb(0x3f8, b);
#endif
}
#if defined (BIOS)
int serial_in(void) {
serial_initialise();
@ -74,4 +42,5 @@ int serial_in(void) {
}
return inb(0x3f8);
}
#endif

View File

@ -116,12 +116,77 @@ static int set_vbe_mode(uint16_t mode) {
return r.eax & 0xff;
}
struct fb_info *vbe_get_mode_list(size_t *count) {
struct vbe_info_struct vbe_info;
get_vbe_info(&vbe_info);
uint16_t *vid_modes = (uint16_t *)rm_desegment(vbe_info.vid_modes_seg,
vbe_info.vid_modes_off);
size_t modes_count = 0;
for (size_t i = 0; vid_modes[i] != 0xffff; i++) {
struct vbe_mode_info_struct vbe_mode_info;
get_vbe_mode_info(&vbe_mode_info, vid_modes[i]);
// We only support RGB for now
if (vbe_mode_info.memory_model != 0x06)
continue;
// We only support linear modes
if (!(vbe_mode_info.mode_attributes & (1 << 7)))
continue;
modes_count++;
}
struct fb_info *ret = ext_mem_alloc(modes_count * sizeof(struct fb_info));
for (size_t i = 0, j = 0; vid_modes[i] != 0xffff; i++) {
struct vbe_mode_info_struct vbe_mode_info;
get_vbe_mode_info(&vbe_mode_info, vid_modes[i]);
// We only support RGB for now
if (vbe_mode_info.memory_model != 0x06)
continue;
// We only support linear modes
if (!(vbe_mode_info.mode_attributes & (1 << 7)))
continue;
ret[j].memory_model = vbe_mode_info.memory_model;
ret[j].framebuffer_width = vbe_mode_info.res_x;
ret[j].framebuffer_height = vbe_mode_info.res_y;
ret[j].framebuffer_bpp = vbe_mode_info.bpp;
if (vbe_info.version_maj < 3) {
ret[j].framebuffer_pitch = vbe_mode_info.bytes_per_scanline;
ret[j].red_mask_size = vbe_mode_info.red_mask_size;
ret[j].red_mask_shift = vbe_mode_info.red_mask_shift;
ret[j].green_mask_size = vbe_mode_info.green_mask_size;
ret[j].green_mask_shift = vbe_mode_info.green_mask_shift;
ret[j].blue_mask_size = vbe_mode_info.blue_mask_size;
ret[j].blue_mask_shift = vbe_mode_info.blue_mask_shift;
} else {
ret[j].framebuffer_pitch = vbe_mode_info.lin_bytes_per_scanline;
ret[j].red_mask_size = vbe_mode_info.lin_red_mask_size;
ret[j].red_mask_shift = vbe_mode_info.lin_red_mask_shift;
ret[j].green_mask_size = vbe_mode_info.lin_green_mask_size;
ret[j].green_mask_shift = vbe_mode_info.lin_green_mask_shift;
ret[j].blue_mask_size = vbe_mode_info.lin_blue_mask_size;
ret[j].blue_mask_shift = vbe_mode_info.lin_blue_mask_shift;
}
j++;
}
*count = modes_count;
return ret;
}
bool init_vbe(struct fb_info *ret,
uint16_t target_width, uint16_t target_height, uint16_t target_bpp) {
printv("vbe: Initialising...\n");
ret->default_res = false;
size_t current_fallback = 0;
struct vbe_info_struct vbe_info;
@ -149,8 +214,6 @@ bool init_vbe(struct fb_info *ret,
};
if (!target_width || !target_height || !target_bpp) {
ret->default_res = true;
struct edid_info_struct *edid_info = get_edid_info();
if (edid_info != NULL) {
int edid_width = (int)edid_info->det_timing_desc1[2];
@ -226,8 +289,6 @@ retry:
}
fallback:
ret->default_res = true;
if (current_fallback < SIZEOF_ARRAY(fallback_resolutions)) {
target_width = fallback_resolutions[current_fallback].width;
target_height = fallback_resolutions[current_fallback].height;

View File

@ -2,10 +2,13 @@
#define __DRIVERS__VBE_H__
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <lib/fb.h>
bool init_vbe(struct fb_info *ret,
uint16_t target_width, uint16_t target_height, uint16_t target_bpp);
struct fb_info *vbe_get_mode_list(size_t *count);
#endif

View File

@ -12,156 +12,250 @@
#include <mm/pmm.h>
#define VIDEO_BOTTOM ((VD_ROWS * VD_COLS) - 1)
#define VD_COLS (80 * 2)
#define VD_ROWS 25
static volatile uint8_t *video_mem = (uint8_t *)0xb8000;
static uint8_t *back_buffer = NULL;
static uint8_t *front_buffer = NULL;
static struct context {
size_t cursor_offset;
#define cursor_offset context.cursor_offset
bool cursor_status;
#define cursor_status context.cursor_status
uint8_t text_palette;
#define text_palette context.text_palette
bool scroll_enabled;
#define scroll_enabled context.scroll_enabled
uint8_t saved_state_text_palette;
#define saved_state_text_palette context.saved_state_text_palette
size_t saved_state_cursor_offset;
#define saved_state_cursor_offset context.saved_state_cursor_offset
} context;
static size_t old_cursor_offset = 0;
static void draw_cursor(void) {
uint8_t pal = back_buffer[cursor_offset + 1];
video_mem[cursor_offset + 1] = ((pal & 0xf0) >> 4) | ((pal & 0x0f) << 4);
static void draw_cursor(struct textmode_context *ctx) {
uint8_t pal = ctx->back_buffer[ctx->cursor_offset + 1];
ctx->video_mem[ctx->cursor_offset + 1] = ((pal & 0xf0) >> 4) | ((pal & 0x0f) << 4);
}
void text_save_state(void) {
saved_state_text_palette = text_palette;
saved_state_cursor_offset = cursor_offset;
static void text_save_state(struct flanterm_context *_ctx) {
struct textmode_context *ctx = (void *)_ctx;
ctx->saved_state_text_palette = ctx->text_palette;
ctx->saved_state_cursor_offset = ctx->cursor_offset;
}
void text_restore_state(void) {
text_palette = saved_state_text_palette;
cursor_offset = saved_state_cursor_offset;
static void text_restore_state(struct flanterm_context *_ctx) {
struct textmode_context *ctx = (void *)_ctx;
ctx->text_palette = ctx->saved_state_text_palette;
ctx->cursor_offset = ctx->saved_state_cursor_offset;
}
void text_swap_palette(void) {
text_palette = (text_palette << 4) | (text_palette >> 4);
static void text_swap_palette(struct flanterm_context *_ctx) {
struct textmode_context *ctx = (void *)_ctx;
ctx->text_palette = (ctx->text_palette << 4) | (ctx->text_palette >> 4);
}
bool text_scroll_disable(void) {
bool ret = scroll_enabled;
scroll_enabled = false;
return ret;
}
static void text_scroll(struct flanterm_context *_ctx) {
struct textmode_context *ctx = (void *)_ctx;
void text_scroll_enable(void) {
scroll_enabled = true;
}
void text_scroll(void) {
// move the text up by one row
for (size_t i = term_context.scroll_top_margin * VD_COLS;
i < (term_context.scroll_bottom_margin - 1) * VD_COLS; i++) {
back_buffer[i] = back_buffer[i + VD_COLS];
for (size_t i = _ctx->scroll_top_margin * VD_COLS;
i < (_ctx->scroll_bottom_margin - 1) * VD_COLS; i++) {
ctx->back_buffer[i] = ctx->back_buffer[i + VD_COLS];
}
// clear the last line of the screen
for (size_t i = (term_context.scroll_bottom_margin - 1) * VD_COLS;
i < term_context.scroll_bottom_margin * VD_COLS; i += 2) {
back_buffer[i] = ' ';
back_buffer[i + 1] = text_palette;
for (size_t i = (_ctx->scroll_bottom_margin - 1) * VD_COLS;
i < _ctx->scroll_bottom_margin * VD_COLS; i += 2) {
ctx->back_buffer[i] = ' ';
ctx->back_buffer[i + 1] = ctx->text_palette;
}
}
void text_revscroll(void) {
static void text_revscroll(struct flanterm_context *_ctx) {
struct textmode_context *ctx = (void *)_ctx;
// move the text up by one row
for (size_t i = (term_context.scroll_bottom_margin - 1) * VD_COLS - 2; ; i--) {
back_buffer[i + VD_COLS] = back_buffer[i];
if (i == term_context.scroll_top_margin * VD_COLS) {
for (size_t i = (_ctx->scroll_bottom_margin - 1) * VD_COLS - 2; ; i--) {
ctx->back_buffer[i + VD_COLS] = ctx->back_buffer[i];
if (i == _ctx->scroll_top_margin * VD_COLS) {
break;
}
}
// clear the first line of the screen
for (size_t i = term_context.scroll_top_margin * VD_COLS;
i < (term_context.scroll_top_margin + 1) * VD_COLS; i += 2) {
back_buffer[i] = ' ';
back_buffer[i + 1] = text_palette;
for (size_t i = _ctx->scroll_top_margin * VD_COLS;
i < (_ctx->scroll_top_margin + 1) * VD_COLS; i += 2) {
ctx->back_buffer[i] = ' ';
ctx->back_buffer[i + 1] = ctx->text_palette;
}
}
void text_clear(bool move) {
static void text_clear(struct flanterm_context *_ctx, bool move) {
struct textmode_context *ctx = (void *)_ctx;
for (size_t i = 0; i < VIDEO_BOTTOM; i += 2) {
back_buffer[i] = ' ';
back_buffer[i + 1] = text_palette;
ctx->back_buffer[i] = ' ';
ctx->back_buffer[i + 1] = ctx->text_palette;
}
if (move) {
ctx->cursor_offset = 0;
}
if (move)
cursor_offset = 0;
}
void text_enable_cursor(void) {
cursor_status = true;
}
bool text_disable_cursor(void) {
bool ret = cursor_status;
cursor_status = false;
return ret;
}
uint64_t text_context_size(void) {
uint64_t ret = 0;
ret += sizeof(struct context);
ret += VD_ROWS * VD_COLS; // front buffer
return ret;
}
void text_context_save(uint64_t ptr) {
memcpy32to64(ptr, (uint64_t)(uintptr_t)&context, sizeof(struct context));
ptr += sizeof(struct context);
memcpy32to64(ptr, (uint64_t)(uintptr_t)front_buffer, VD_ROWS * VD_COLS);
}
void text_context_restore(uint64_t ptr) {
memcpy32to64((uint64_t)(uintptr_t)&context, ptr, sizeof(struct context));
ptr += sizeof(struct context);
memcpy32to64((uint64_t)(uintptr_t)front_buffer, ptr, VD_ROWS * VD_COLS);
static void text_full_refresh(struct flanterm_context *_ctx) {
struct textmode_context *ctx = (void *)_ctx;
for (size_t i = 0; i < VD_ROWS * VD_COLS; i++) {
video_mem[i] = front_buffer[i];
back_buffer[i] = front_buffer[i];
ctx->video_mem[i] = ctx->front_buffer[i];
ctx->back_buffer[i] = ctx->front_buffer[i];
}
if (cursor_status) {
draw_cursor();
old_cursor_offset = cursor_offset;
if (_ctx->cursor_enabled) {
draw_cursor(ctx);
ctx->old_cursor_offset = ctx->cursor_offset;
}
}
void text_full_refresh(void) {
static void text_double_buffer_flush(struct flanterm_context *_ctx) {
struct textmode_context *ctx = (void *)_ctx;
if (_ctx->cursor_enabled) {
draw_cursor(ctx);
}
if (ctx->cursor_offset != ctx->old_cursor_offset || _ctx->cursor_enabled == false) {
ctx->video_mem[ctx->old_cursor_offset + 1] = ctx->back_buffer[ctx->old_cursor_offset + 1];
}
for (size_t i = 0; i < VD_ROWS * VD_COLS; i++) {
video_mem[i] = front_buffer[i];
back_buffer[i] = front_buffer[i];
if (ctx->back_buffer[i] == ctx->front_buffer[i]) {
continue;
}
ctx->front_buffer[i] = ctx->back_buffer[i];
if (_ctx->cursor_enabled && i == ctx->cursor_offset + 1) {
continue;
}
ctx->video_mem[i] = ctx->back_buffer[i];
}
if (cursor_status) {
draw_cursor();
old_cursor_offset = cursor_offset;
if (_ctx->cursor_enabled) {
ctx->old_cursor_offset = ctx->cursor_offset;
}
}
void init_vga_textmode(size_t *_rows, size_t *_cols, bool managed) {
static void text_get_cursor_pos(struct flanterm_context *_ctx, size_t *x, size_t *y) {
struct textmode_context *ctx = (void *)_ctx;
*x = (ctx->cursor_offset % VD_COLS) / 2;
*y = ctx->cursor_offset / VD_COLS;
}
static void text_move_character(struct flanterm_context *_ctx, size_t new_x, size_t new_y, size_t old_x, size_t old_y) {
struct textmode_context *ctx = (void *)_ctx;
if (old_x >= VD_COLS / 2 || old_y >= VD_ROWS
|| new_x >= VD_COLS / 2 || new_y >= VD_ROWS) {
return;
}
ctx->back_buffer[new_y * VD_COLS + new_x * 2] = ctx->back_buffer[old_y * VD_COLS + old_x * 2];
}
static void text_set_cursor_pos(struct flanterm_context *_ctx, size_t x, size_t y) {
struct textmode_context *ctx = (void *)_ctx;
if (x >= VD_COLS / 2) {
if ((int)x < 0) {
x = 0;
} else {
x = VD_COLS / 2 - 1;
}
}
if (y >= VD_ROWS) {
if ((int)y < 0) {
y = 0;
} else {
y = VD_ROWS - 1;
}
}
ctx->cursor_offset = y * VD_COLS + x * 2;
}
static uint8_t ansi_colours[] = { 0, 4, 2, 6, 1, 5, 3, 7 };
static void text_set_text_fg(struct flanterm_context *_ctx, size_t fg) {
struct textmode_context *ctx = (void *)_ctx;
ctx->text_palette = (ctx->text_palette & 0xf0) | ansi_colours[fg];
}
static void text_set_text_bg(struct flanterm_context *_ctx, size_t bg) {
struct textmode_context *ctx = (void *)_ctx;
ctx->text_palette = (ctx->text_palette & 0x0f) | (ansi_colours[bg] << 4);
}
static void text_set_text_fg_bright(struct flanterm_context *_ctx, size_t fg) {
struct textmode_context *ctx = (void *)_ctx;
ctx->text_palette = (ctx->text_palette & 0xf0) | (ansi_colours[fg] | (1 << 3));
}
static void text_set_text_bg_bright(struct flanterm_context *_ctx, size_t bg) {
struct textmode_context *ctx = (void *)_ctx;
ctx->text_palette = (ctx->text_palette & 0x0f) | ((ansi_colours[bg] | (1 << 3)) << 4);
}
static void text_set_text_fg_rgb(struct flanterm_context *ctx, uint32_t n) {
(void)ctx;
(void)n;
}
static void text_set_text_bg_rgb(struct flanterm_context *ctx, uint32_t n) {
(void)ctx;
(void)n;
}
static void text_set_text_fg_default(struct flanterm_context *_ctx) {
struct textmode_context *ctx = (void *)_ctx;
ctx->text_palette = (ctx->text_palette & 0xf0) | 7;
}
static void text_set_text_bg_default(struct flanterm_context *_ctx) {
struct textmode_context *ctx = (void *)_ctx;
ctx->text_palette &= 0x0f;
}
static void text_set_text_fg_default_bright(struct flanterm_context *_ctx) {
struct textmode_context *ctx = (void *)_ctx;
ctx->text_palette = (ctx->text_palette & 0xf0) | (7 | (1 << 3));
}
static void text_set_text_bg_default_bright(struct flanterm_context *_ctx) {
struct textmode_context *ctx = (void *)_ctx;
ctx->text_palette = (ctx->text_palette & 0x0f) | ((1 << 3) << 4);
}
static void text_putchar(struct flanterm_context *_ctx, uint8_t c) {
struct textmode_context *ctx = (void *)_ctx;
ctx->back_buffer[ctx->cursor_offset] = c;
ctx->back_buffer[ctx->cursor_offset + 1] = ctx->text_palette;
if (ctx->cursor_offset / VD_COLS == _ctx->scroll_bottom_margin - 1
&& ctx->cursor_offset % VD_COLS == VD_COLS - 2) {
if (_ctx->scroll_enabled) {
text_scroll(_ctx);
ctx->cursor_offset -= ctx->cursor_offset % VD_COLS;
}
} else if (ctx->cursor_offset >= (VIDEO_BOTTOM - 1)) {
ctx->cursor_offset -= ctx->cursor_offset % VD_COLS;
} else {
ctx->cursor_offset += 2;
}
}
static void text_deinit(struct flanterm_context *_ctx, void (*_free)(void *, size_t)) {
struct textmode_context *ctx = (void *)_ctx;
if (ctx->back_buffer != NULL) {
_free(ctx->back_buffer, VD_ROWS * VD_COLS);
ctx->back_buffer = NULL;
}
if (ctx->front_buffer != NULL) {
_free(ctx->front_buffer, VD_ROWS * VD_COLS);
ctx->front_buffer = NULL;
}
pmm_free(ctx, sizeof(struct textmode_context));
}
void vga_textmode_init(bool managed) {
term_notready();
if (quiet) {
return;
}
if (current_video_mode != 0x3) {
struct rm_regs r = {0};
r.eax = 0x0003;
@ -170,31 +264,36 @@ void init_vga_textmode(size_t *_rows, size_t *_cols, bool managed) {
current_video_mode = 0x3;
}
if (back_buffer == NULL) {
back_buffer = ext_mem_alloc(VD_ROWS * VD_COLS);
terms = ext_mem_alloc(sizeof(void *));
terms_i = 1;
terms[0] = ext_mem_alloc(sizeof(struct textmode_context));
struct flanterm_context *term = terms[0];
struct textmode_context *ctx = (void *)term;
if (ctx->back_buffer == NULL) {
ctx->back_buffer = ext_mem_alloc(VD_ROWS * VD_COLS);
} else {
memset(back_buffer, 0, VD_ROWS * VD_COLS);
memset(ctx->back_buffer, 0, VD_ROWS * VD_COLS);
}
if (front_buffer == NULL) {
front_buffer = ext_mem_alloc(VD_ROWS * VD_COLS);
if (ctx->front_buffer == NULL) {
ctx->front_buffer = ext_mem_alloc(VD_ROWS * VD_COLS);
} else {
memset(front_buffer, 0, VD_ROWS * VD_COLS);
memset(ctx->front_buffer, 0, VD_ROWS * VD_COLS);
}
cursor_offset = 0;
cursor_status = true;
text_palette = 0x07;
scroll_enabled = true;
ctx->cursor_offset = 0;
ctx->text_palette = 0x07;
text_clear(false);
ctx->video_mem = (volatile uint8_t *)0xb8000;
*_rows = VD_ROWS;
*_cols = VD_COLS / 2;
text_clear(term, false);
// VGA cursor code taken from: https://wiki.osdev.org/Text_Mode_Cursor
if (!managed) {
text_disable_cursor();
term->cursor_enabled = false;
outb(0x3d4, 0x0a);
outb(0x3d5, (inb(0x3d5) & 0xc0) | 14);
@ -213,107 +312,56 @@ void init_vga_textmode(size_t *_rows, size_t *_cols, bool managed) {
outb(0x3d5, 0x20);
}
text_double_buffer_flush();
}
text_double_buffer_flush(term);
void text_double_buffer_flush(void) {
if (cursor_status) {
draw_cursor();
}
if (cursor_offset != old_cursor_offset || cursor_status == false) {
video_mem[old_cursor_offset + 1] = back_buffer[old_cursor_offset + 1];
}
for (size_t i = 0; i < VD_ROWS * VD_COLS; i++) {
if (back_buffer[i] == front_buffer[i]) {
continue;
}
if (cursor_status && i == cursor_offset + 1) {
continue;
}
front_buffer[i] = back_buffer[i];
video_mem[i] = back_buffer[i];
}
if (cursor_status) {
old_cursor_offset = cursor_offset;
}
}
void text_get_cursor_pos(size_t *x, size_t *y) {
*x = (cursor_offset % VD_COLS) / 2;
*y = cursor_offset / VD_COLS;
}
void text_move_character(size_t new_x, size_t new_y, size_t old_x, size_t old_y) {
if (old_x >= VD_COLS / 2 || old_y >= VD_ROWS
|| new_x >= VD_COLS / 2 || new_y >= VD_ROWS) {
return;
}
back_buffer[new_y * VD_COLS + new_x * 2] = back_buffer[old_y * VD_COLS + old_x * 2];
}
void text_set_cursor_pos(size_t x, size_t y) {
if (x >= VD_COLS / 2) {
if ((int)x < 0) {
x = 0;
} else {
x = VD_COLS / 2 - 1;
}
}
if (y >= VD_ROWS) {
if ((int)y < 0) {
y = 0;
} else {
y = VD_ROWS - 1;
}
}
cursor_offset = y * VD_COLS + x * 2;
}
static uint8_t ansi_colours[] = { 0, 4, 2, 6, 1, 5, 3, 7 };
void text_set_text_fg(size_t fg) {
text_palette = (text_palette & 0xf0) | ansi_colours[fg];
}
void text_set_text_bg(size_t bg) {
text_palette = (text_palette & 0x0f) | (ansi_colours[bg] << 4);
}
void text_set_text_fg_bright(size_t fg) {
text_palette = (text_palette & 0xf0) | (ansi_colours[fg] | (1 << 3));
}
void text_set_text_bg_bright(size_t bg) {
text_palette = (text_palette & 0x0f) | ((ansi_colours[bg] | (1 << 3)) << 4);
}
void text_set_text_fg_default(void) {
text_palette = (text_palette & 0xf0) | 7;
}
void text_set_text_bg_default(void) {
text_palette &= 0x0f;
}
void text_putchar(uint8_t c) {
back_buffer[cursor_offset] = c;
back_buffer[cursor_offset + 1] = text_palette;
if (cursor_offset / VD_COLS == term_context.scroll_bottom_margin - 1
&& cursor_offset % VD_COLS == VD_COLS - 2) {
if (scroll_enabled) {
text_scroll();
cursor_offset -= cursor_offset % VD_COLS;
}
} else if (cursor_offset >= (VIDEO_BOTTOM - 1)) {
cursor_offset -= cursor_offset % VD_COLS;
if (managed && serial) {
term->cols = 80;
term->rows = 24;
} else {
cursor_offset += 2;
term->cols = 80;
term->rows = 25;
}
term->raw_putchar = text_putchar;
term->clear = text_clear;
term->set_cursor_pos = text_set_cursor_pos;
term->get_cursor_pos = text_get_cursor_pos;
term->set_text_fg = text_set_text_fg;
term->set_text_bg = text_set_text_bg;
term->set_text_fg_bright = text_set_text_fg_bright;
term->set_text_bg_bright = text_set_text_bg_bright;
term->set_text_fg_rgb = text_set_text_fg_rgb;
term->set_text_bg_rgb = text_set_text_bg_rgb;
term->set_text_fg_default = text_set_text_fg_default;
term->set_text_bg_default = text_set_text_bg_default;
term->set_text_fg_default_bright = text_set_text_fg_default_bright;
term->set_text_bg_default_bright = text_set_text_bg_default_bright;
term->move_character = text_move_character;
term->scroll = text_scroll;
term->revscroll = text_revscroll;
term->swap_palette = text_swap_palette;
term->save_state = text_save_state;
term->restore_state = text_restore_state;
term->double_buffer_flush = text_double_buffer_flush;
term->full_refresh = text_full_refresh;
term->deinit = text_deinit;
flanterm_context_reinit(term);
if (!managed) {
term->cursor_enabled = false;
}
term->full_refresh(term);
if (!managed) {
term->deinit(term, pmm_free);
pmm_free(terms, sizeof(void *));
terms_i = 0;
terms = NULL;
term_backend = _NOT_READY;
} else {
term_backend = TEXTMODE;
}
}

View File

@ -1,39 +1,35 @@
#ifndef __DRIVERS__VGA_TEXTMODE_H__
#define __DRIVERS__VGA_TEXTMODE_H__
#include <stdbool.h>
#if defined (BIOS)
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <flanterm/flanterm.h>
void init_vga_textmode(size_t *rows, size_t *cols, bool managed);
#define VD_COLS (80 * 2)
#define VD_ROWS 25
void text_putchar(uint8_t c);
void text_clear(bool move);
void text_enable_cursor(void);
bool text_disable_cursor(void);
void text_set_cursor_pos(size_t x, size_t y);
void text_get_cursor_pos(size_t *x, size_t *y);
void text_set_text_fg(size_t fg);
void text_set_text_bg(size_t bg);
void text_set_text_fg_bright(size_t fg);
void text_set_text_bg_bright(size_t bg);
void text_set_text_fg_default(void);
void text_set_text_bg_default(void);
bool text_scroll_disable(void);
void text_scroll_enable(void);
void text_move_character(size_t new_x, size_t new_y, size_t old_x, size_t old_y);
void text_scroll(void);
void text_revscroll(void);
void text_swap_palette(void);
void text_save_state(void);
void text_restore_state(void);
struct textmode_context {
struct flanterm_context term;
void text_double_buffer(bool state);
void text_double_buffer_flush(void);
volatile uint8_t *video_mem;
uint64_t text_context_size(void);
void text_context_save(uint64_t ptr);
void text_context_restore(uint64_t ptr);
void text_full_refresh(void);
uint8_t *back_buffer;
uint8_t *front_buffer;
size_t cursor_offset;
size_t old_cursor_offset;
bool cursor_status;
uint8_t text_palette;
uint8_t saved_state_text_palette;
size_t saved_state_cursor_offset;
};
void vga_textmode_init(bool managed);
#endif
#endif

View File

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

View File

@ -1,6 +1,10 @@
section .text
global efi_main
extern uefi_entry
efi_main:
xor eax, eax
mov [esp], eax
jmp uefi_entry
section .note.GNU-stack noalloc noexec nowrite progbits

View File

@ -1,6 +1,10 @@
section .text
global efi_main
extern uefi_entry
efi_main:
xor eax, eax
mov [rsp], rax
jmp uefi_entry
section .note.GNU-stack noalloc noexec nowrite progbits

View File

@ -42,7 +42,9 @@ static bool stage3_init(struct volume *part) {
bool old_cif = case_insensitive_fopen;
case_insensitive_fopen = true;
if ((stage3 = fopen(part, "/limine.sys")) == NULL
&& (stage3 = fopen(part, "/boot/limine.sys")) == NULL) {
&& (stage3 = fopen(part, "/limine/limine.sys")) == NULL
&& (stage3 = fopen(part, "/boot/limine.sys")) == NULL
&& (stage3 = fopen(part, "/boot/limine/limine.sys")) == NULL) {
case_insensitive_fopen = old_cif;
return false;
}
@ -56,8 +58,8 @@ static bool stage3_init(struct volume *part) {
}
fread(stage3, stage3_addr,
(uintptr_t)stage3_addr - 0x8000,
stage3->size - ((uintptr_t)stage3_addr - 0x8000));
(uintptr_t)stage3_addr - 0xf000,
stage3->size - ((uintptr_t)stage3_addr - 0xf000));
fclose(stage3);
@ -80,12 +82,9 @@ enum {
noreturn void entry(uint8_t boot_drive, int boot_from) {
// XXX DO NOT MOVE A20 ENABLE CALL
if (!a20_enable()) {
term_fallback();
panic(false, "Could not enable A20 line");
}
term_fallback();
init_e820();
init_memmap();
@ -101,7 +100,7 @@ noreturn void entry(uint8_t boot_drive, int boot_from) {
}
if (boot_volume == NULL) {
panic(false, "Could not determine boot drive\n");
panic(false, "Could not determine boot drive");
}
volume_iterate_parts(boot_volume,
@ -113,14 +112,16 @@ noreturn void entry(uint8_t boot_drive, int boot_from) {
if (!stage3_found) {
print("\n"
"!! Stage 3 file not found!\n"
"!! Have you copied limine.sys to the root or /boot directories of\n"
"!! one of the partitions on the boot device?\n\n");
"!! Have you copied limine.sys to the root, /boot, /limine, or /boot/limine\n"
"!! directories of one of the partitions on the boot device?\n\n");
}
if (!stage3_loaded) {
panic(false, "Failed to load stage 3.");
}
term_fallback();
stage3_common();
}

View File

@ -26,7 +26,7 @@
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;
@ -36,23 +36,23 @@ noreturn void uefi_entry(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
EFI_STATUS status;
status = gBS->SetWatchdogTimer(0, 0x10000, 0, NULL);
if (status) {
term_vbe(NULL, 0, 0);
early_term = true;
print("WARNING: Failed to disable watchdog timer!\n");
}
term_notready();
gST->ConOut->EnableCursor(gST->ConOut, false);
init_memmap();
term_fallback();
status = gBS->SetWatchdogTimer(0, 0x10000, 0, NULL);
if (status) {
print("WARNING: Failed to disable watchdog timer!\n");
}
#if defined (__x86_64__) || defined (__i386__)
init_gdt();
#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
@ -62,11 +62,9 @@ noreturn void uefi_entry(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
boot_volume = NULL;
EFI_HANDLE current_handle = ImageHandle;
for (;;) {
for (size_t j = 0; j < 25; j++) {
if (current_handle == NULL) {
term_vbe(NULL, 0, 0);
early_term = true;
could_not_match:
print("WARNING: Could not meaningfully match the boot device handle with a volume.\n");
print(" Using the first volume containing a Limine configuration!\n");
@ -76,7 +74,9 @@ noreturn void uefi_entry(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
bool old_cif = case_insensitive_fopen;
case_insensitive_fopen = true;
if ((f = fopen(volume_index[i], "/limine.cfg")) == NULL
&& (f = fopen(volume_index[i], "/limine/limine.cfg")) == NULL
&& (f = fopen(volume_index[i], "/boot/limine.cfg")) == NULL
&& (f = fopen(volume_index[i], "/boot/limine/limine.cfg")) == NULL
&& (f = fopen(volume_index[i], "/EFI/BOOT/limine.cfg")) == NULL) {
case_insensitive_fopen = old_cif;
continue;
@ -94,8 +94,9 @@ noreturn void uefi_entry(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
break;
}
if (boot_volume != NULL)
if (boot_volume != NULL) {
stage3_common();
}
panic(false, "No volume contained a Limine configuration file");
}
@ -107,26 +108,29 @@ noreturn void uefi_entry(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
(void **)&loaded_image);
if (status) {
panic(false, "HandleProtocol failure (%x)", status);
goto could_not_match;
}
boot_volume = disk_volume_from_efi_handle(loaded_image->DeviceHandle);
if (boot_volume != NULL)
if (boot_volume != NULL) {
stage3_common();
}
current_handle = loaded_image->ParentHandle;
}
goto could_not_match;
}
#endif
noreturn void stage3_common(void) {
term_notready();
#if defined (__x86_64__) || defined (__i386__)
init_flush_irqs();
init_io_apics();
#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

@ -1 +0,0 @@
font.bin originally taken from https://github.com/viler-int10h/vga-text-mode-fonts/raw/master/FONTS/PC-OTHER/TOSH-SAT.F16

Binary file not shown.

View File

@ -553,7 +553,6 @@ static void ext2_close(struct file_handle *file) {
pmm_free(f->alloc_map, f->inode.i_blocks_count * sizeof(uint32_t));
}
pmm_free(f, sizeof(struct ext2_file_handle));
pmm_free(file, sizeof(struct file_handle));
}
static void ext2_read(struct file_handle *file, void *buf, uint64_t loc, uint64_t count) {

View File

@ -525,5 +525,4 @@ static void fat32_close(struct file_handle *file) {
struct fat32_file_handle *f = file->fd;
pmm_free(f->cluster_chain, f->chain_len * sizeof(uint32_t));
pmm_free(f, sizeof(struct fat32_file_handle));
pmm_free(file, sizeof(struct file_handle));
}

View File

@ -19,6 +19,7 @@ struct file_handle {
bool readall;
struct volume *vol;
char *path;
size_t path_len;
void *fd;
void (*read)(void *fd, void *buf, uint64_t loc, uint64_t count);
void (*close)(void *fd);
@ -35,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

@ -49,14 +49,12 @@ struct file_handle *fopen(struct volume *part, const char *filename) {
struct file_handle *ret;
#if defined (BIOS)
if (part->pxe) {
if ((ret = tftp_open(0, 69, filename)) == NULL) {
if ((ret = tftp_open(part, "", filename)) == NULL) {
return NULL;
}
goto success;
return ret;
}
#endif
if ((ret = ext2_open(part, filename)) != NULL) {
goto success;
@ -72,6 +70,7 @@ struct file_handle *fopen(struct volume *part, const char *filename) {
success:
ret->path = (char *)filename;
ret->path_len = filename_new_len;
return ret;
}
@ -81,10 +80,11 @@ void fclose(struct file_handle *fd) {
if (fd->readall == false) {
pmm_free(fd->fd, fd->size);
}
pmm_free(fd, sizeof(struct file_handle));
} else {
fd->close(fd);
}
pmm_free(fd->path, fd->path_len);
pmm_free(fd, sizeof(struct file_handle));
}
void fread(struct file_handle *fd, void *buf, uint64_t loc, uint64_t count) {
@ -96,16 +96,24 @@ 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;
}
memmap_alloc_range((uint64_t)(size_t)fd->fd, ALIGN_UP(fd->size, 4096), type, false, true, false, false);
memmap_alloc_range((uint64_t)(size_t)fd->fd, ALIGN_UP(fd->size, 4096), type, 0, true, false, false);
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;
fd->readall = true;
fd->is_memfile = true;
return ret;
}
}

View File

@ -294,5 +294,4 @@ static void iso9660_read(struct file_handle *file, void *buf, uint64_t loc, uint
static void iso9660_close(struct file_handle *file) {
pmm_free(file->fd, sizeof(struct iso9660_file_handle));
pmm_free(file, sizeof(struct file_handle));
}

View File

@ -28,9 +28,9 @@ TMP4="$(mktemp)"
trap "rm -f '$TMP1' '$TMP2' '$TMP3' '$TMP4'; trap - EXIT; exit" EXIT INT TERM QUIT HUP
"$CROSS_OBJDUMP" -t "$1" | ( "$SED" '/[[:<:]]d[[:>:]]/d' 2>/dev/null || "$SED" '/\bd\b/d' ) | sort > "$TMP1"
"$GREP" "$4" < "$TMP1" | cut -d' ' -f1 > "$TMP2"
"$GREP" "$4" < "$TMP1" | "$AWK" 'NF{ print $NF }' > "$TMP3"
"$OBJDUMP_FOR_TARGET" -t "$1" | ( "$SED" '/[[:<:]]d[[:>:]]/d' 2>/dev/null || "$SED" '/\bd\b/d' ) | sort > "$TMP1"
"$GREP" "F $4" < "$TMP1" | cut -d' ' -f1 > "$TMP2"
"$GREP" "F $4" < "$TMP1" | "$AWK" 'NF{ print $NF }' > "$TMP3"
echo ".section .$2_map" > "$TMP4"
echo ".globl $2_map" >> "$TMP4"
@ -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

@ -1,63 +0,0 @@
#include <stdint.h>
#include <fs/file.h>
#include <lib/image.h>
#include <lib/bmp.h>
#include <lib/libc.h>
#include <lib/misc.h>
#include <mm/pmm.h>
struct bmp_header {
uint16_t bf_signature;
uint32_t bf_size;
uint32_t reserved;
uint32_t bf_offset;
uint32_t bi_size;
uint32_t bi_width;
uint32_t bi_height;
uint16_t bi_planes;
uint16_t bi_bpp;
uint32_t bi_compression;
uint32_t bi_image_size;
uint32_t bi_xcount;
uint32_t bi_ycount;
uint32_t bi_clr_used;
uint32_t bi_clr_important;
uint32_t red_mask;
uint32_t green_mask;
uint32_t blue_mask;
} __attribute__((packed));
bool bmp_open_image(struct image *image, struct file_handle *file) {
struct bmp_header header;
fread(file, &header, 0, sizeof(struct bmp_header));
if (memcmp(&header.bf_signature, "BM", 2) != 0)
return false;
// We don't support bpp lower than 8
if (header.bi_bpp % 8 != 0)
return false;
image->img = ext_mem_alloc(header.bf_size);
uint32_t bf_size;
if (header.bf_offset + header.bf_size > file->size) {
bf_size = file->size - header.bf_offset;
} else {
bf_size = header.bf_size;
}
fread(file, image->img, header.bf_offset, bf_size);
image->allocated_size = header.bf_size;
image->x_size = header.bi_width;
image->y_size = header.bi_height;
image->pitch = ALIGN_UP(header.bi_width * header.bi_bpp, 32) / 8;
image->bpp = header.bi_bpp;
image->img_width = header.bi_width;
image->img_height = header.bi_height;
return true;
}

View File

@ -1,10 +0,0 @@
#ifndef __LIB__BMP_H__
#define __LIB__BMP_H__
#include <stdint.h>
#include <fs/file.h>
#include <lib/image.h>
bool bmp_open_image(struct image *image, struct file_handle *file);
#endif

View File

@ -3,10 +3,18 @@
#include <lib/config.h>
#include <lib/libc.h>
#include <lib/misc.h>
#include <lib/readline.h>
#include <mm/pmm.h>
#include <fs/file.h>
#include <lib/print.h>
#include <pxe/tftp.h>
#include <crypt/blake2b.h>
#include <sys/cpu.h>
#define CONFIG_B2SUM_SIGNATURE "++CONFIG_B2SUM_SIGNATURE++"
#define CONFIG_B2SUM_EMPTY "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
const char *config_b2sum = CONFIG_B2SUM_SIGNATURE CONFIG_B2SUM_EMPTY;
static bool config_get_entry_name(char *ret, size_t index, size_t limit);
static char *config_get_entry(size_t *size, size_t index);
@ -24,7 +32,9 @@ int init_config_disk(struct volume *part) {
bool old_cif = case_insensitive_fopen;
case_insensitive_fopen = true;
if ((f = fopen(part, "/limine.cfg")) == NULL
&& (f = fopen(part, "/limine/limine.cfg")) == NULL
&& (f = fopen(part, "/boot/limine.cfg")) == NULL
&& (f = fopen(part, "/boot/limine/limine.cfg")) == NULL
&& (f = fopen(part, "/EFI/BOOT/limine.cfg")) == NULL) {
case_insensitive_fopen = old_cif;
return -1;
@ -41,22 +51,6 @@ int init_config_disk(struct volume *part) {
return init_config(config_size);
}
#if defined (BIOS)
int init_config_pxe(void) {
struct file_handle *f;
if ((f = tftp_open(0, 69, "limine.cfg")) == NULL) {
return -1;
}
size_t config_size = f->size + 2;
config_addr = ext_mem_alloc(config_size);
fread(f, config_addr, 0, f->size);
return init_config(config_size);
}
#endif
#define NOT_CHILD (-1)
#define DIRECT_CHILD 0
#define INDIRECT_CHILD 1
@ -150,6 +144,24 @@ struct macro {
static struct macro *macros = NULL;
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];
for (size_t i = 0; i < BLAKE2B_OUT_BYTES; i++) {
hash_buf[i] = digit_to_int(config_b2sum[i * 2]) << 4 | digit_to_int(config_b2sum[i * 2 + 1]);
}
if (memcmp(hash_buf, out_buf, BLAKE2B_OUT_BYTES) != 0) {
panic(false, "!!! CHECKSUM MISMATCH FOR CONFIG FILE !!!");
}
}
// add trailing newline if not present
config_addr[config_size - 2] = '\n';
@ -169,6 +181,27 @@ int init_config(size_t config_size) {
}
// Load macros
struct macro *arch_macro = ext_mem_alloc(sizeof(struct macro));
strcpy(arch_macro->name, "ARCH");
#if defined (__x86_64__)
strcpy(arch_macro->value, "x86-64");
#elif defined (__i386__)
{
uint32_t eax, ebx, ecx, edx;
if (!cpuid(0x80000001, 0, &eax, &ebx, &ecx, &edx) || !(edx & (1 << 29))) {
strcpy(arch_macro->value, "ia-32");
} else {
strcpy(arch_macro->value, "x86-64");
}
}
#elif defined (__aarch64__)
strcpy(arch_macro->value, "aarch64");
#else
#error "Unspecified architecture"
#endif
arch_macro->next = macros;
macros = arch_macro;
for (size_t i = 0; i < config_size;) {
if ((config_size - i >= 3 && memcmp(config_addr + i, "\n${", 3) == 0)
|| (config_size - i >= 2 && i == 0 && memcmp(config_addr, "${", 2) == 0)) {

View File

@ -26,7 +26,6 @@ struct conf_tuple {
extern struct menu_entry *menu_tree;
int init_config_disk(struct volume *part);
int init_config_pxe(void);
int init_config(size_t config_size);
char *config_get_value(const char *config, size_t index, const char *key);

View File

@ -20,6 +20,9 @@
#define DT_RELA 0x00000007
#define DT_RELASZ 0x00000008
#define DT_RELAENT 0x00000009
#define DT_FLAGS_1 0x6ffffffb
#define DF_1_PIE 0x08000000
#define ABI_SYSV 0x00
#define ARCH_X86_64 0x3e
@ -76,19 +79,6 @@ struct elf32_phdr {
uint32_t p_align;
};
struct elf32_shdr {
uint32_t sh_name;
uint32_t sh_type;
uint32_t sh_flags;
uint32_t sh_addr;
uint32_t sh_offset;
uint32_t sh_size;
uint32_t sh_link;
uint32_t sh_info;
uint32_t sh_addralign;
uint32_t sh_entsize;
};
struct elf64_rela {
uint64_t r_addr;
uint32_t r_info;
@ -163,6 +153,11 @@ static bool elf64_is_relocatable(uint8_t *elf, struct elf64_hdr *hdr) {
struct elf64_dyn *dyn = (void *)elf + (phdr->p_offset + j * sizeof(struct elf64_dyn));
switch (dyn->d_tag) {
case DT_FLAGS_1:
if (dyn->d_un & DF_1_PIE) {
return true;
}
break;
case DT_RELA:
return true;
}
@ -278,7 +273,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__)
@ -290,6 +285,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)");
}
@ -401,7 +400,7 @@ static void elf64_get_ranges(uint8_t *elf, uint64_t slide, struct elf_range **_r
*_ranges = ranges;
}
bool elf64_load(uint8_t *elf, uint64_t *entry_point, uint64_t *_slide, uint32_t alloc_type, bool kaslr, struct elf_range **ranges, uint64_t *ranges_count, uint64_t *physical_base, uint64_t *virtual_base, uint64_t *_image_size, bool *is_reloc) {
bool elf64_load(uint8_t *elf, uint64_t *entry_point, uint64_t *_slide, uint32_t alloc_type, bool kaslr, struct elf_range **ranges, uint64_t *ranges_count, uint64_t *physical_base, uint64_t *virtual_base, uint64_t *_image_size, uint64_t *_image_size_before_bss, bool *is_reloc) {
struct elf64_hdr *hdr = (void *)elf;
if (strncmp((char *)hdr->ident, "\177ELF", 4)) {
@ -415,7 +414,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) {
@ -457,6 +456,49 @@ bool elf64_load(uint8_t *elf, uint64_t *entry_point, uint64_t *_slide, uint32_t
continue;
}
// check for overlapping phdrs
for (uint16_t j = 0; j < hdr->ph_num; j++) {
struct elf64_phdr *phdr_in = (void *)elf + (hdr->phoff + j * hdr->phdr_size);
if (phdr_in->p_type != PT_LOAD) {
continue;
}
// Drop entries not in the higher half
if (phdr_in->p_vaddr < FIXED_HIGHER_HALF_OFFSET_64) {
continue;
}
if (phdr_in == phdr) {
continue;
}
if ((phdr_in->p_vaddr >= phdr->p_vaddr
&& phdr_in->p_vaddr < phdr->p_vaddr + phdr->p_memsz)
||
(phdr_in->p_vaddr + phdr_in->p_memsz > phdr->p_vaddr
&& 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) {
min_vaddr = phdr->p_vaddr;
}
@ -486,7 +528,7 @@ bool elf64_load(uint8_t *elf, uint64_t *entry_point, uint64_t *_slide, uint32_t
}
again:
if (kaslr) {
if (*is_reloc && kaslr) {
slide = rand32() & ~(max_align - 1);
if ((*virtual_base - FIXED_HIGHER_HALF_OFFSET_64) + slide + image_size >= 0x80000000) {
@ -497,6 +539,8 @@ again:
}
}
uint64_t bss_size = 0;
for (uint16_t i = 0; i < hdr->ph_num; i++) {
struct elf64_phdr *phdr = (void *)elf + (hdr->phoff + i * hdr->phdr_size);
@ -527,16 +571,22 @@ again:
memcpy((void *)(uintptr_t)load_addr, elf + (phdr->p_offset), phdr->p_filesz);
bss_size = phdr->p_memsz - phdr->p_filesz;
if (!elf64_apply_relocations(elf, hdr, (void *)(uintptr_t)load_addr, phdr->p_vaddr, phdr->p_memsz, slide)) {
panic(true, "elf: Failed to apply relocations");
}
#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
}
if (_image_size_before_bss != NULL) {
*_image_size_before_bss = image_size - bss_size;
}
*virtual_base += slide;
*entry_point = entry + slide;
if (_slide) {
@ -640,7 +690,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

@ -30,7 +30,7 @@ struct elf_section_hdr_info elf64_section_hdr_info(uint8_t *elf);
struct elf_section_hdr_info elf32_section_hdr_info(uint8_t *elf);
bool elf64_load_section(uint8_t *elf, void *buffer, const char *name, size_t limit, uint64_t slide);
bool elf64_load(uint8_t *elf, uint64_t *entry_point, uint64_t *_slide, uint32_t alloc_type, bool kaslr, struct elf_range **ranges, uint64_t *ranges_count, uint64_t *physical_base, uint64_t *virtual_base, uint64_t *image_size, bool *is_reloc);
bool elf64_load(uint8_t *elf, uint64_t *entry_point, uint64_t *_slide, uint32_t alloc_type, bool kaslr, struct elf_range **ranges, uint64_t *ranges_count, uint64_t *physical_base, uint64_t *virtual_base, uint64_t *image_size, uint64_t *image_size_before_bss, bool *is_reloc);
bool elf32_load_elsewhere(uint8_t *elf, uint64_t *entry_point,
struct elsewhere_range **ranges,
@ -69,6 +69,19 @@ struct elf64_shdr {
uint64_t sh_entsize;
};
struct elf32_shdr {
uint32_t sh_name;
uint32_t sh_type;
uint32_t sh_flags;
uint32_t sh_addr;
uint32_t sh_offset;
uint32_t sh_size;
uint32_t sh_link;
uint32_t sh_info;
uint32_t sh_addralign;
uint32_t sh_entsize;
};
struct elf64_sym {
uint32_t st_name;
uint8_t st_info;

View File

@ -6,17 +6,24 @@
#include <drivers/gop.h>
#include <mm/pmm.h>
bool fb_init(struct fb_info *ret,
void fb_init(struct fb_info **ret, size_t *_fbs_count,
uint64_t target_width, uint64_t target_height, uint16_t target_bpp) {
bool r;
#if defined (BIOS)
r = init_vbe(ret, target_width, target_height, target_bpp);
#elif defined (UEFI)
r = init_gop(ret, target_width, target_height, target_bpp);
#endif
*ret = ext_mem_alloc(sizeof(struct fb_info));
if (init_vbe(*ret, target_width, target_height, target_bpp)) {
*_fbs_count = 1;
return r;
(*ret)->edid = get_edid_info();
size_t mode_count;
(*ret)->mode_list = vbe_get_mode_list(&mode_count);
(*ret)->mode_count = mode_count;
} else {
*_fbs_count = 0;
pmm_free(*ret, sizeof(struct fb_info));
}
#elif defined (UEFI)
init_gop(ret, _fbs_count, target_width, target_height, target_bpp);
#endif
}
void fb_clear(struct fb_info *fb) {

View File

@ -2,6 +2,8 @@
#define __LIB__FB_H__
#include <stdint.h>
#include <stddef.h>
#include <drivers/edid.h>
struct resolution {
uint64_t width;
@ -10,22 +12,27 @@ struct resolution {
};
struct fb_info {
bool default_res;
uint8_t memory_model;
uint64_t framebuffer_addr;
uint64_t framebuffer_pitch;
uint64_t framebuffer_width;
uint64_t framebuffer_height;
uint16_t framebuffer_bpp;
uint8_t red_mask_size;
uint8_t red_mask_shift;
uint8_t green_mask_size;
uint8_t green_mask_shift;
uint8_t blue_mask_size;
uint8_t blue_mask_shift;
uint8_t memory_model;
uint8_t red_mask_size;
uint8_t red_mask_shift;
uint8_t green_mask_size;
uint8_t green_mask_shift;
uint8_t blue_mask_size;
uint8_t blue_mask_shift;
uint64_t framebuffer_addr;
struct edid_info_struct *edid;
uint64_t mode_count;
struct fb_info *mode_list;
};
bool fb_init(struct fb_info *ret,
void fb_init(struct fb_info **ret, size_t *_fbs_count,
uint64_t target_width, uint64_t target_height, uint16_t target_bpp);
void fb_clear(struct fb_info *fb);

File diff suppressed because it is too large Load Diff

View File

@ -1,44 +1,11 @@
#ifndef __LIB__GTERM_H__
#define __LIB__GTERM_H__
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <lib/image.h>
#include <drivers/vbe.h>
#include <lib/fb.h>
extern struct fb_info fbinfo;
bool gterm_init(char *config, size_t *_rows, size_t *_cols, size_t width, size_t height);
void gterm_deinit(void);
void gterm_putchar(uint8_t c);
void gterm_clear(bool move);
void gterm_enable_cursor(void);
bool gterm_disable_cursor(void);
void gterm_set_cursor_pos(size_t x, size_t y);
void gterm_get_cursor_pos(size_t *x, size_t *y);
void gterm_set_text_fg(size_t fg);
void gterm_set_text_bg(size_t bg);
void gterm_set_text_fg_bright(size_t fg);
void gterm_set_text_bg_bright(size_t bg);
void gterm_set_text_fg_rgb(uint32_t fg);
void gterm_set_text_bg_rgb(uint32_t bg);
void gterm_set_text_fg_default(void);
void gterm_set_text_bg_default(void);
bool gterm_scroll_disable(void);
void gterm_scroll_enable(void);
void gterm_move_character(size_t new_x, size_t new_y, size_t old_x, size_t old_y);
void gterm_scroll(void);
void gterm_revscroll(void);
void gterm_swap_palette(void);
void gterm_save_state(void);
void gterm_restore_state(void);
void gterm_double_buffer_flush(void);
uint64_t gterm_context_size(void);
void gterm_context_save(uint64_t ptr);
void gterm_context_restore(uint64_t ptr);
void gterm_full_refresh(void);
bool gterm_init(struct fb_info **ret, size_t *_fbs_count,
char *config, size_t width, size_t height);
#endif

View File

@ -1,9 +1,10 @@
#include <stdint.h>
#include <stddef.h>
#include <lib/image.h>
#include <lib/config.h>
#include <lib/misc.h>
#include <mm/pmm.h>
#include <lib/bmp.h>
#include <stb/stb_image.h>
void image_make_centered(struct image *image, int frame_x_size, int frame_y_size, uint32_t back_colour) {
image->type = IMAGE_CENTERED;
@ -26,14 +27,38 @@ struct image *image_open(struct file_handle *file) {
image->type = IMAGE_TILED;
if (bmp_open_image(image, file))
return image;
void *src = ext_mem_alloc(file->size);
pmm_free(image, sizeof(struct image));
return NULL;
fread(file, src, 0, file->size);
int x, y, bpp;
image->img = stbi_load_from_memory(src, file->size, &x, &y, &bpp, 4);
pmm_free(src, file->size);
if (image->img == NULL) {
pmm_free(image, sizeof(struct image));
return NULL;
}
// Convert ABGR to XRGB
uint32_t *pptr = (void *)image->img;
for (int i = 0; i < x * y; i++) {
pptr[i] = (pptr[i] & 0x0000ff00) | ((pptr[i] & 0x00ff0000) >> 16) | ((pptr[i] & 0x000000ff) << 16);
}
image->x_size = x;
image->y_size = y;
image->pitch = x * 4;
image->bpp = 32;
image->img_width = x;
image->img_height = y;
return image;
}
void image_close(struct image *image) {
pmm_free(image->img, image->allocated_size);
stbi_image_free(image->img);
pmm_free(image, sizeof(struct image));
}

View File

@ -5,7 +5,6 @@
#include <fs/file.h>
struct image {
size_t allocated_size;
size_t x_size;
size_t y_size;
int type;

View File

@ -6,10 +6,14 @@
bool isprint(int c);
bool isspace(int c);
bool isalpha(int c);
bool isdigit(int c);
int toupper(int c);
int tolower(int c);
int abs(int i);
void *memset(void *, int, size_t);
void *memcpy(void *, const void *, size_t);
int memcmp(const void *, const void *, size_t);
@ -21,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;
@ -26,6 +34,10 @@ int tolower(int c) {
return c;
}
int abs(int i) {
return i < 0 ? -i : i;
}
char *strcpy(char *dest, const char *src) {
size_t i;
@ -80,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

@ -1,66 +0,0 @@
.section .text
.global memcpy
memcpy:
mov x3, x0
0:
cbz x2, 1f
ldrb w4, [x1], #1
strb w4, [x0], #1
sub x2, x2, #1
b 0b
1:
mov x0, x3
ret
.global memset
memset:
mov x3, x0
0:
cbz x2, 1f
strb w1, [x0], #1
sub x2, x2, #1
b 0b
1:
mov x0, x3
ret
.global memmove
memmove:
mov x3, x0
mov x5, x2
cmp x0, x1
b.gt 1f
0:
cbz x2, 2f
ldrb w4, [x1], #1
strb w4, [x0], #1
sub x2, x2, #1
b 0b
1:
sub x5, x5, #1
cbz x2, 2f
ldrb w4, [x1, x5]
strb w4, [x0, x5]
sub x2, x2, #1
b 1b
2:
mov x0, x3
ret
.global memcmp
memcmp:
mov x3, xzr
0:
cbz x2, 1f
ldrb w3, [x0], #1
ldrb w4, [x1], #1
sub w3, w3, w4
cbnz w3, 1f
sub x2, x2, #1
b 0b
1:
sxtw x0, w3
mov x0, x3
ret

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

57
common/lib/memory.s2.c Normal file
View File

@ -0,0 +1,57 @@
#if !defined (__x86_64__) && !defined (__i386__)
#include <stdint.h>
#include <stddef.h>
void *memcpy(void *dest, const void *src, size_t n) {
uint8_t *pdest = (uint8_t *)dest;
const uint8_t *psrc = (const uint8_t *)src;
for (size_t i = 0; i < n; i++) {
pdest[i] = psrc[i];
}
return dest;
}
void *memset(void *s, int c, size_t n) {
uint8_t *p = (uint8_t *)s;
for (size_t i = 0; i < n; i++) {
p[i] = (uint8_t)c;
}
return s;
}
void *memmove(void *dest, const void *src, size_t n) {
uint8_t *pdest = (uint8_t *)dest;
const uint8_t *psrc = (const uint8_t *)src;
if (src > dest) {
for (size_t i = 0; i < n; i++) {
pdest[i] = psrc[i];
}
} else if (src < dest) {
for (size_t i = n; i > 0; i--) {
pdest[i-1] = psrc[i-1];
}
}
return dest;
}
int memcmp(const void *s1, const void *s2, size_t n) {
const uint8_t *p1 = (const uint8_t *)s1;
const uint8_t *p2 = (const uint8_t *)s2;
for (size_t i = 0; i < n; i++) {
if (p1[i] != p2[i]) {
return p1[i] < p2[i] ? -1 : 1;
}
}
return 0;
}
#endif

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};
@ -83,65 +84,6 @@ size_t get_trailing_zeros(uint64_t val) {
return 64;
}
// This table from https://web.mit.edu/freebsd/head/sys/libkern/crc32.c
static const uint32_t crc32_table[] = {
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};
uint32_t get_crc32(void *_stream, size_t len) {
uint8_t *stream = _stream;
uint32_t ret = 0xffffffff;
for (size_t i = 0; i < len; i++) {
ret = (ret >> 8) ^ crc32_table[(ret ^ stream[i]) & 0xff];
}
ret ^= 0xffffffff;
return ret;
}
uint32_t oct2bin(uint8_t *str, uint32_t max) {
uint32_t value = 0;
while (max-- > 0) {
@ -170,8 +112,6 @@ uint32_t hex2bin(uint8_t *str, uint32_t size) {
no_unwind bool efi_boot_services_exited = false;
#define EFI_COPY_MAX_ENTRIES 512
bool efi_exit_boot_services(void) {
EFI_STATUS status;
@ -193,6 +133,14 @@ bool efi_exit_boot_services(void) {
goto fail;
}
EFI_MEMORY_DESCRIPTOR *efi_copy;
status = gBS->AllocatePool(EfiLoaderData, efi_mmap_size * 2, (void **)&efi_copy);
if (status) {
goto fail;
}
const size_t EFI_COPY_MAX_ENTRIES = (efi_mmap_size * 2) / efi_desc_size;
size_t retries = 0;
retry:
@ -219,6 +167,101 @@ retry:
#error Unknown architecture
#endif
// Go through new EFI memmap and free up bootloader entries
size_t entry_count = efi_mmap_size / efi_desc_size;
size_t efi_copy_i = 0;
for (size_t i = 0; i < entry_count; i++) {
EFI_MEMORY_DESCRIPTOR *orig_entry = (void *)efi_mmap + i * efi_desc_size;
EFI_MEMORY_DESCRIPTOR *new_entry = (void *)efi_copy + efi_copy_i * efi_desc_size;
memcpy(new_entry, orig_entry, efi_desc_size);
uint64_t base = orig_entry->PhysicalStart;
uint64_t length = orig_entry->NumberOfPages * 4096;
uint64_t top = base + length;
// Find for a match in the untouched memory map
for (size_t j = 0; j < untouched_memmap_entries; j++) {
if (untouched_memmap[j].type != MEMMAP_USABLE)
continue;
if (top > untouched_memmap[j].base && top <= untouched_memmap[j].base + untouched_memmap[j].length) {
if (untouched_memmap[j].base < base) {
new_entry->NumberOfPages = (base - untouched_memmap[j].base) / 4096;
efi_copy_i++;
if (efi_copy_i == EFI_COPY_MAX_ENTRIES) {
panic(false, "efi: New memory map exhausted");
}
new_entry = (void *)efi_copy + efi_copy_i * efi_desc_size;
memcpy(new_entry, orig_entry, efi_desc_size);
new_entry->NumberOfPages -= (base - untouched_memmap[j].base) / 4096;
new_entry->PhysicalStart = base;
new_entry->VirtualStart = new_entry->PhysicalStart;
length = new_entry->NumberOfPages * 4096;
top = base + length;
}
if (untouched_memmap[j].base > base) {
new_entry->NumberOfPages = (untouched_memmap[j].base - base) / 4096;
efi_copy_i++;
if (efi_copy_i == EFI_COPY_MAX_ENTRIES) {
panic(false, "efi: New memory map exhausted");
}
new_entry = (void *)efi_copy + efi_copy_i * efi_desc_size;
memcpy(new_entry, orig_entry, efi_desc_size);
new_entry->NumberOfPages -= (untouched_memmap[j].base - base) / 4096;
new_entry->PhysicalStart = untouched_memmap[j].base;
new_entry->VirtualStart = new_entry->PhysicalStart;
base = new_entry->PhysicalStart;
length = new_entry->NumberOfPages * 4096;
top = base + length;
}
if (length < untouched_memmap[j].length) {
panic(false, "efi: Memory map corruption");
}
new_entry->Type = EfiConventionalMemory;
if (length == untouched_memmap[j].length) {
// It's a perfect match!
break;
}
new_entry->NumberOfPages = untouched_memmap[j].length / 4096;
efi_copy_i++;
if (efi_copy_i == EFI_COPY_MAX_ENTRIES) {
panic(false, "efi: New memory map exhausted");
}
new_entry = (void *)efi_copy + efi_copy_i * efi_desc_size;
memcpy(new_entry, orig_entry, efi_desc_size);
new_entry->NumberOfPages = (length - untouched_memmap[j].length) / 4096;
new_entry->PhysicalStart = base + untouched_memmap[j].length;
new_entry->VirtualStart = new_entry->PhysicalStart;
break;
}
}
efi_copy_i++;
if (efi_copy_i == EFI_COPY_MAX_ENTRIES) {
panic(false, "efi: New memory map exhausted");
}
}
efi_mmap = efi_copy;
efi_mmap_size = efi_copy_i * efi_desc_size;
efi_boot_services_exited = true;
printv("efi: Exited boot services.\n");

View File

@ -33,14 +33,12 @@ extern struct volume *boot_volume;
extern bool stage3_loaded;
#endif
extern bool quiet, serial, editor_enabled;
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);
void get_absolute_path(char *path_ptr, const char *path, const char *pwd);
uint32_t get_crc32(void *_stream, size_t len);
uint32_t oct2bin(uint8_t *str, uint32_t max);
uint32_t hex2bin(uint8_t *str, uint32_t size);
@ -94,9 +92,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

@ -3,9 +3,10 @@
#include <lib/misc.h>
#include <lib/print.h>
bool verbose = true;
bool verbose = false;
bool quiet = false;
bool serial = false;
bool hash_mismatch_panic = false;
uint8_t bcd_to_int(uint8_t val) {
return (val & 0x0f) + ((val & 0xf0) >> 4) * 10;

View File

@ -21,37 +21,23 @@ noreturn void panic(bool allow_menu, const char *fmt, ...) {
quiet = false;
static bool is_nested = false;
if (is_nested) {
goto nested;
if (
#if defined (BIOS)
stage3_loaded == true &&
#endif
term_backend == _NOT_READY) {
term_fallback();
}
is_nested = true;
if (
#if defined (BIOS)
stage3_loaded == true &&
#endif
term_backend == NOT_READY) {
early_term = true;
term_vbe(NULL, 0, 0);
}
nested:
if (term_backend == NOT_READY) {
term_fallback();
}
#if defined (BIOS)
if (stage3_loaded) {
#endif
term_backend != FALLBACK) {
print("\033[31mPANIC\033[37;1m\033[0m: ");
#if defined (BIOS)
} else {
print("PANIC: ");
}
#endif
vprint(fmt, args);
va_end(args);
@ -68,6 +54,9 @@ nested:
getchar();
// This fixes a crash
term_notready();
menu(false);
/*
fb_clear(&fbinfo);

View File

@ -1,6 +1,7 @@
#include <stddef.h>
#include <lib/part.h>
#include <lib/print.h>
#include <lib/readline.h>
void list_volumes(void) {
for (size_t i = 0; i < volume_index_i; i++) {
@ -13,6 +14,9 @@ void list_volumes(void) {
print("max_partition: %d\n", v->max_partition);
print("first_sect: %U\n", v->first_sect);
print("sect_count: %U\n", v->sect_count);
print("---\n");
if (i < volume_index_i - 1) {
print("--- Press a key to continue ---\n");
getchar();
}
}
}

View File

@ -7,6 +7,7 @@
#include <lib/guid.h>
#if defined (UEFI)
# include <efi.h>
# include <crypt/blake2b.h>
#endif
#define NO_PARTITION (-1)
@ -16,12 +17,17 @@
struct volume {
#if defined (UEFI)
EFI_HANDLE efi_handle;
// Block storage
EFI_HANDLE efi_part_handle;
EFI_BLOCK_IO *block_io;
// PXE
EFI_PXE_BASE_CODE_PROTOCOL *pxe_base_code;
bool unique_sector_valid;
uint64_t unique_sector;
uint32_t unique_sector_crc32;
uint8_t unique_sector_b2b[BLAKE2B_OUT_BYTES];
#elif defined (BIOS)
int drive;
#endif

View File

@ -192,6 +192,25 @@ void vprint(const char *fmt, va_list args) {
char c = (char)va_arg(args, int);
prn_char(print_buf, &print_buf_i, c); }
break;
case '#': {
bool printed = false;
char *str = (char *)va_arg(args, const char *);
for (int i = (int)strlen(str) - 1; i >= 0; i--) {
if (str[i] != '#') {
continue;
}
prn_nstr(print_buf, &print_buf_i, str, i);
printed = true;
break;
}
if (!printed) {
prn_str(print_buf, &print_buf_i, str);
}
break;
}
default:
prn_char(print_buf, &print_buf_i, '?');
break;
@ -199,15 +218,17 @@ void vprint(const char *fmt, va_list args) {
}
out:
if (!quiet) {
#if defined (BIOS)
if (stage3_loaded) {
if (stage3_loaded) {
#endif
term_write((uint64_t)(uintptr_t)print_buf, print_buf_i);
FOR_TERM(flanterm_write(TERM, print_buf, print_buf_i));
#if defined (BIOS)
} else {
s2_print(print_buf, print_buf_i);
} else {
s2_print(print_buf, print_buf_i);
}
#endif
}
#endif
for (size_t i = 0; i < print_buf_i; i++) {
#if defined (__x86_64__) || defined (__i386__)
@ -215,7 +236,8 @@ out:
outb(0xe9, print_buf[i]);
}
#endif
if ((term_backend != NOT_READY && serial) || COM_OUTPUT) {
#if defined (BIOS)
if ((!quiet && serial) || COM_OUTPUT) {
switch (print_buf[i]) {
case '\n':
serial_out('\r');
@ -230,5 +252,6 @@ out:
}
serial_out(print_buf[i]);
}
#endif
}
}

View File

@ -267,7 +267,11 @@ int pit_sleep_and_quit_on_keypress(int seconds) {
if (gBS->HandleProtocol(gST->ConsoleInHandle, &exproto_guid, (void **)&exproto) != EFI_SUCCESS) {
if (gBS->HandleProtocol(gST->ConsoleInHandle, &sproto_guid, (void **)&sproto) != EFI_SUCCESS) {
panic(false, "Your input device doesn't have an input protocol!");
if (gST->ConIn != NULL) {
sproto = gST->ConIn;
} else {
panic(false, "Your input device doesn't have an input protocol!");
}
}
events[0] = sproto->WaitForKey;
@ -348,53 +352,55 @@ again:
static void reprint_string(int x, int y, const char *s) {
size_t orig_x, orig_y;
disable_cursor();
get_cursor_pos(&orig_x, &orig_y);
FOR_TERM(TERM->cursor_enabled = false);
terms[0]->get_cursor_pos(terms[0], &orig_x, &orig_y);
set_cursor_pos_helper(x, y);
print("%s", s);
set_cursor_pos_helper(orig_x, orig_y);
enable_cursor();
FOR_TERM(TERM->cursor_enabled = true);
}
static void cursor_back(void) {
size_t x, y;
get_cursor_pos(&x, &y);
terms[0]->get_cursor_pos(terms[0], &x, &y);
if (x) {
x--;
} else if (y) {
y--;
x = term_cols - 1;
x = terms[0]->cols - 1;
}
set_cursor_pos_helper(x, y);
}
static void cursor_fwd(void) {
size_t x, y;
get_cursor_pos(&x, &y);
if (x < term_cols - 1) {
terms[0]->get_cursor_pos(terms[0], &x, &y);
if (x < terms[0]->cols - 1) {
x++;
} else if (y < term_rows - 1) {
y++;
} else {
x = 0;
if (y < terms[0]->rows - 1) {
y++;
}
}
set_cursor_pos_helper(x, y);
}
void readline(const char *orig_str, char *buf, size_t limit) {
bool prev_autoflush = term_autoflush;
term_autoflush = false;
bool prev_autoflush = terms[0]->autoflush;
FOR_TERM(TERM->autoflush = false);
size_t orig_str_len = strlen(orig_str);
memmove(buf, orig_str, orig_str_len);
buf[orig_str_len] = 0;
size_t orig_x, orig_y;
get_cursor_pos(&orig_x, &orig_y);
terms[0]->get_cursor_pos(terms[0], &orig_x, &orig_y);
print("%s", orig_str);
for (size_t i = orig_str_len; ; ) {
term_double_buffer_flush();
FOR_TERM(TERM->double_buffer_flush(TERM));
int c = getchar();
switch (c) {
case GETCHAR_CURSOR_LEFT:
@ -453,14 +459,21 @@ void readline(const char *orig_str, char *buf, size_t limit) {
}
buf[i] = c;
i++;
size_t prev_x, prev_y;
terms[0]->get_cursor_pos(terms[0], &prev_x, &prev_y);
cursor_fwd();
reprint_string(orig_x, orig_y, buf);
// If cursor has wrapped around, move the line start position up one row
if (prev_x == terms[0]->cols - 1 && prev_y == terms[0]->rows - 1) {
orig_y--;
print("\n\e[J"); // Clear the bottom line
}
}
}
}
}
out:
term_double_buffer_flush();
term_autoflush = prev_autoflush;
FOR_TERM(TERM->double_buffer_flush(TERM));
FOR_TERM(TERM->autoflush = prev_autoflush);
}

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

@ -1,51 +1,6 @@
#include <lib/macros.aarch64_asm.h>
// 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
.section .text
// noreturn void enter_in_el1(uint64_t entry, uint64_t sp, uint64_t sctlr,
// uint64_t mair, uint64_t tcr, uint64_t ttbr0,
@ -106,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

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -3,122 +3,57 @@
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include <lib/image.h>
#include <lib/print.h>
#define TERM_TABSIZE (8)
#define MAX_ESC_VALUES (16)
extern struct term_context {
bool control_sequence;
bool csi;
bool escape;
bool rrr;
bool discard_next;
bool bold;
bool reverse_video;
bool dec_private;
bool insert_mode;
uint8_t g_select;
uint8_t charsets[2];
size_t current_charset;
size_t escape_offset;
size_t esc_values_i;
size_t saved_cursor_x;
size_t saved_cursor_y;
size_t current_primary;
size_t scroll_top_margin;
size_t scroll_bottom_margin;
uint32_t esc_values[MAX_ESC_VALUES];
bool saved_state_bold;
bool saved_state_reverse_video;
size_t saved_state_current_charset;
size_t saved_state_current_primary;
} term_context;
#include <flanterm/flanterm.h>
enum {
NOT_READY,
VBE,
_NOT_READY,
GTERM,
TEXTMODE,
FALLBACK
};
#if defined (BIOS)
extern int current_video_mode;
#endif
extern struct flanterm_context **terms;
extern size_t terms_i;
extern int term_backend;
extern size_t term_rows, term_cols;
extern bool term_runtime;
extern bool early_term;
void term_fallback(void);
void term_reinit(void);
void term_deinit(void);
void term_vbe(char *config, size_t width, size_t height);
void term_textmode(void);
void term_notready(void);
void term_putchar(uint8_t c);
void term_write(uint64_t buf, uint64_t count);
extern void (*raw_putchar)(uint8_t c);
extern void (*clear)(bool move);
extern void (*enable_cursor)(void);
extern bool (*disable_cursor)(void);
extern void (*set_cursor_pos)(size_t x, size_t y);
extern void (*get_cursor_pos)(size_t *x, size_t *y);
extern void (*set_text_fg)(size_t fg);
extern void (*set_text_bg)(size_t bg);
extern void (*set_text_fg_bright)(size_t fg);
extern void (*set_text_bg_bright)(size_t bg);
extern void (*set_text_fg_rgb)(uint32_t fg);
extern void (*set_text_bg_rgb)(uint32_t bg);
extern void (*set_text_fg_default)(void);
extern void (*set_text_bg_default)(void);
extern bool (*scroll_disable)(void);
extern void (*scroll_enable)(void);
extern void (*term_move_character)(size_t new_x, size_t new_y, size_t old_x, size_t old_y);
extern void (*term_scroll)(void);
extern void (*term_revscroll)(void);
extern void (*term_swap_palette)(void);
extern void (*term_save_state)(void);
extern void (*term_restore_state)(void);
extern void (*term_double_buffer_flush)(void);
extern uint64_t (*term_context_size)(void);
extern void (*term_context_save)(uint64_t ptr);
extern void (*term_context_restore)(uint64_t ptr);
extern void (*term_full_refresh)(void);
#define TERM_CB_DEC 10
#define TERM_CB_BELL 20
#define TERM_CB_PRIVATE_ID 30
#define TERM_CB_STATUS_REPORT 40
#define TERM_CB_POS_REPORT 50
#define TERM_CB_KBD_LEDS 60
#define TERM_CB_MODE 70
#define TERM_CB_LINUX 80
#define TERM_CTX_SIZE ((uint64_t)(-1))
#define TERM_CTX_SAVE ((uint64_t)(-2))
#define TERM_CTX_RESTORE ((uint64_t)(-3))
#define TERM_FULL_REFRESH ((uint64_t)(-4))
#define TERM_OOB_OUTPUT_GET ((uint64_t)(-10))
#define TERM_OOB_OUTPUT_SET ((uint64_t)(-11))
extern uint64_t term_arg;
extern void (*term_callback)(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t);
extern bool term_autoflush;
#define FOR_TERM(...) do { \
for (size_t FOR_TERM_i = 0; FOR_TERM_i < terms_i; FOR_TERM_i++) { \
struct flanterm_context *TERM = terms[FOR_TERM_i]; \
__VA_ARGS__ \
; \
} \
} while (0)
inline void reset_term(void) {
term_autoflush = true;
enable_cursor();
print("\e[2J\e[H");
term_double_buffer_flush();
for (size_t i = 0; i < terms_i; i++) {
struct flanterm_context *term = terms[i];
print("\e[2J\e[H");
flanterm_context_reinit(term);
term->cursor_enabled = true;
term->double_buffer_flush(term);
}
}
inline void set_cursor_pos_helper(size_t x, size_t y) {
print("\e[%u;%uH", (int)y + 1, (int)x + 1);
}
void term_notready(void);
void term_fallback(void);
void _term_write(struct flanterm_context *term, uint64_t buf, uint64_t count);
#endif

View File

@ -1,229 +0,0 @@
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <lib/term.h>
#include <lib/misc.h>
#include <lib/real.h>
bool early_term = false;
no_unwind int current_video_mode = -1;
int term_backend = NOT_READY;
size_t term_rows, term_cols;
bool term_runtime = false;
void (*raw_putchar)(uint8_t c);
void (*clear)(bool move);
void (*enable_cursor)(void);
bool (*disable_cursor)(void);
void (*set_cursor_pos)(size_t x, size_t y);
void (*get_cursor_pos)(size_t *x, size_t *y);
void (*set_text_fg)(size_t fg);
void (*set_text_bg)(size_t bg);
void (*set_text_fg_bright)(size_t fg);
void (*set_text_bg_bright)(size_t bg);
void (*set_text_fg_rgb)(uint32_t fg);
void (*set_text_bg_rgb)(uint32_t bg);
void (*set_text_fg_default)(void);
void (*set_text_bg_default)(void);
bool (*scroll_disable)(void);
void (*scroll_enable)(void);
void (*term_move_character)(size_t new_x, size_t new_y, size_t old_x, size_t old_y);
void (*term_scroll)(void);
void (*term_revscroll)(void);
void (*term_swap_palette)(void);
void (*term_save_state)(void);
void (*term_restore_state)(void);
void (*term_double_buffer_flush)(void);
uint64_t (*term_context_size)(void);
void (*term_context_save)(uint64_t ptr);
void (*term_context_restore)(uint64_t ptr);
void (*term_full_refresh)(void);
// --- fallback ---
#if defined (BIOS)
static void fallback_raw_putchar(uint8_t c) {
struct rm_regs r = {0};
r.eax = 0x0e00 | c;
rm_int(0x10, &r, &r);
}
static void fallback_clear(bool move) {
(void)move;
struct rm_regs r = {0};
rm_int(0x11, &r, &r);
switch ((r.eax >> 4) & 3) {
case 0:
r.eax = 3;
break;
case 1:
r.eax = 1;
break;
case 2:
r.eax = 3;
break;
case 3:
r.eax = 7;
break;
}
rm_int(0x10, &r, &r);
}
static void fallback_set_cursor_pos(size_t x, size_t y) {
struct rm_regs r = {0};
r.eax = 0x0200;
r.ebx = 0;
r.edx = (y << 8) + x;
rm_int(0x10, &r, &r);
}
static void fallback_get_cursor_pos(size_t *x, size_t *y) {
struct rm_regs r = {0};
r.eax = 0x0300;
r.ebx = 0;
rm_int(0x10, &r, &r);
*x = r.edx & 0xff;
*y = r.edx >> 8;
}
#elif defined (UEFI)
static int cursor_x = 0, cursor_y = 0;
static void fallback_raw_putchar(uint8_t c) {
CHAR16 string[2];
string[0] = c;
string[1] = 0;
gST->ConOut->OutputString(gST->ConOut, string);
switch (c) {
case 0x08:
if (cursor_x > 0)
cursor_x--;
break;
case 0x0A:
cursor_x = 0;
break;
case 0x0D:
if (cursor_y < 24)
cursor_y++;
break;
default:
if (++cursor_x > 80) {
cursor_x = 0;
if (cursor_y < 24)
cursor_y++;
}
}
}
static void fallback_clear(bool move) {
(void)move;
gST->ConOut->ClearScreen(gST->ConOut);
cursor_x = cursor_y = 0;
}
static void fallback_set_cursor_pos(size_t x, size_t y) {
if (x >= 80 || y >= 25)
return;
gST->ConOut->SetCursorPosition(gST->ConOut, x, y);
cursor_x = x;
cursor_y = y;
}
static void fallback_get_cursor_pos(size_t *x, size_t *y) {
*x = cursor_x;
*y = cursor_y;
}
#endif
void term_fallback(void) {
#if defined (UEFI)
if (!efi_boot_services_exited) {
gST->ConOut->Reset(gST->ConOut, false);
gST->ConOut->SetMode(gST->ConOut, 0);
cursor_x = cursor_y = 0;
#elif defined (BIOS)
fallback_clear(true);
#endif
term_notready();
raw_putchar = fallback_raw_putchar;
clear = fallback_clear;
set_cursor_pos = fallback_set_cursor_pos;
get_cursor_pos = fallback_get_cursor_pos;
term_backend = FALLBACK;
#if defined (UEFI)
}
#endif
}
// --- notready ---
static void notready_raw_putchar(uint8_t c) {
(void)c;
}
static void notready_clear(bool move) {
(void)move;
}
static void notready_void(void) {}
static void notready_set_cursor_pos(size_t x, size_t y) {
(void)x; (void)y;
}
static void notready_get_cursor_pos(size_t *x, size_t *y) {
*x = 0;
*y = 0;
}
static void notready_size_t(size_t n) {
(void)n;
}
static bool notready_disable(void) {
return false;
}
static void notready_move_character(size_t a, size_t b, size_t c, size_t d) {
(void)a; (void)b; (void)c; (void)d;
}
static uint64_t notready_context_size(void) {
return 0;
}
static void notready_uint32_t(uint32_t n) {
(void)n;
}
static void notready_uint64_t(uint64_t n) {
(void)n;
}
void term_notready(void) {
term_backend = NOT_READY;
raw_putchar = notready_raw_putchar;
clear = notready_clear;
enable_cursor = notready_void;
disable_cursor = notready_disable;
set_cursor_pos = notready_set_cursor_pos;
get_cursor_pos = notready_get_cursor_pos;
set_text_fg = notready_size_t;
set_text_bg = notready_size_t;
set_text_fg_bright = notready_size_t;
set_text_bg_bright = notready_size_t;
set_text_fg_rgb = notready_uint32_t;
set_text_bg_rgb = notready_uint32_t;
set_text_fg_default = notready_void;
set_text_bg_default = notready_void;
scroll_disable = notready_disable;
scroll_enable = notready_void;
term_move_character = notready_move_character;
term_scroll = notready_void;
term_revscroll = notready_void;
term_swap_palette = notready_void;
term_save_state = notready_void;
term_restore_state = notready_void;
term_double_buffer_flush = notready_void;
term_context_size = notready_context_size;
term_context_save = notready_uint64_t;
term_context_restore = notready_uint64_t;
term_full_refresh = notready_void;
term_cols = 80;
term_rows = 24;
}

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

@ -8,11 +8,14 @@
#include <mm/pmm.h>
#include <lib/print.h>
#include <pxe/tftp.h>
#include <tinf.h>
#include <compress/gzip.h>
#include <menu.h>
#include <lib/readline.h>
#include <crypt/blake2b.h>
// A URI takes the form of: resource://root/path
// A URI takes the form of: resource://root/path#hash
// The following function splits up a URI into its componenets
bool uri_resolve(char *uri, char **resource, char **root, char **path) {
bool uri_resolve(char *uri, char **resource, char **root, char **path, char **hash) {
size_t length = strlen(uri) + 1;
char *buf = ext_mem_alloc(length);
memcpy(buf, uri, length);
@ -51,6 +54,26 @@ bool uri_resolve(char *uri, char **resource, char **root, char **path) {
return false;
*path = uri;
// Get hash
for (int i = (int)strlen(uri) - 1; i >= 0; i--) {
if (uri[i] != '#') {
continue;
}
uri[i++] = 0;
if (hash != NULL) {
*hash = uri + i;
}
if (strlen(uri + i) != 128) {
panic(true, "Blake2b hash must be 128 characters long");
return false;
}
break;
}
return true;
}
@ -141,7 +164,6 @@ static struct file_handle *uri_fslabel_dispatch(char *fslabel, char *path) {
return fopen(volume, path);
}
#if defined (BIOS)
static struct file_handle *uri_tftp_dispatch(char *root, char *path) {
uint32_t ip;
if (!strcmp(root, "")) {
@ -153,19 +175,16 @@ static struct file_handle *uri_tftp_dispatch(char *root, char *path) {
}
struct file_handle *ret;
if ((ret = tftp_open(ip, 69, path)) == NULL) {
if ((ret = tftp_open(boot_volume, root, path)) == NULL) {
return NULL;
}
return ret;
}
#endif
static struct file_handle *uri_boot_dispatch(char *s_part, char *path) {
#if defined (BIOS)
if (boot_volume->pxe)
return uri_tftp_dispatch(s_part, path);
#endif
int partition;
@ -190,11 +209,13 @@ static struct file_handle *uri_boot_dispatch(char *s_part, char *path) {
struct file_handle *uri_open(char *uri) {
struct file_handle *ret;
char *resource, *root, *path;
uri_resolve(uri, &resource, &root, &path);
char *resource = NULL, *root = NULL, *path = NULL, *hash = NULL;
if (!uri_resolve(uri, &resource, &root, &path, &hash)) {
return NULL;
}
if (resource == NULL) {
panic(true, "No resource specified for URI `%s`.", uri);
panic(true, "No resource specified for URI `%#`.", uri);
}
bool compressed = false;
@ -217,25 +238,52 @@ struct file_handle *uri_open(char *uri) {
ret = uri_guid_dispatch(root, path);
} else if (!strcmp(resource, "fslabel")) {
ret = uri_fslabel_dispatch(root, path);
#if defined (BIOS)
} else if (!strcmp(resource, "tftp")) {
ret = uri_tftp_dispatch(root, path);
#endif
} else {
panic(true, "Resource `%s` not valid.", resource);
}
if (hash != NULL && ret != NULL) {
uint8_t out_buf[BLAKE2B_OUT_BYTES];
void *file_buf = freadall(ret, MEMMAP_BOOTLOADER_RECLAIMABLE);
blake2b(out_buf, file_buf, ret->size);
uint8_t hash_buf[BLAKE2B_OUT_BYTES];
for (size_t i = 0; i < sizeof(hash_buf); i++) {
hash_buf[i] = digit_to_int(hash[i * 2]) << 4 | digit_to_int(hash[i * 2 + 1]);
}
if (memcmp(hash_buf, out_buf, sizeof(out_buf)) != 0) {
if (hash_mismatch_panic) {
panic(true, "Blake2b hash for URI `%#` does not match!", uri);
} else {
print("WARNING: Blake2b hash for URI `%#` does not match!\n"
" Press Y to continue, press any other key to return to menu...", uri);
char ch = getchar();
if (ch != 'Y' && ch != 'y') {
menu(false);
}
print("\n");
}
}
}
if (compressed && ret != NULL) {
struct file_handle *compressed_fd = ext_mem_alloc(sizeof(struct file_handle));
fread(ret, &compressed_fd->size, ret->size - 4, sizeof(uint32_t));
compressed_fd->fd = ext_mem_alloc(compressed_fd->size);
void *src = freadall(ret, MEMMAP_BOOTLOADER_RECLAIMABLE);
if (tinf_gzip_uncompress(compressed_fd->fd, src, ret->size)) {
panic(true, "tinf error");
if ((compressed_fd->fd = gzip_uncompress(src, ret->size, &compressed_fd->size)) == NULL) {
panic(true, "GZip error");
}
compressed_fd->vol = ret->vol;
fclose(ret);
compressed_fd->path = ext_mem_alloc(ret->path_len);
memcpy(compressed_fd->path, ret->path, ret->path_len);
compressed_fd->path_len = ret->path_len;
compressed_fd->is_memfile = true;
uint64_t src_size = ret->size;
fclose(ret);
pmm_free(src, src_size);
ret = compressed_fd;
}

View File

@ -4,7 +4,7 @@
#include <stdbool.h>
#include <fs/file.h>
bool uri_resolve(char *uri, char **resource, char **root, char **path);
bool uri_resolve(char *uri, char **resource, char **root, char **path, char **hash);
struct file_handle *uri_open(char *uri);
#endif

View File

@ -5,14 +5,16 @@ 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)) ;
}
SECTIONS
{
. = 0x8000;
. = 0xf000;
.text.stage2 : {
*(.entry)
@ -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 = .;
@ -40,12 +38,29 @@ SECTIONS
full_map = .;
getchar = .;
menu = .;
term_write = .;
term_vbe = .;
flanterm_write = .;
term_backend = .;
term_fallback = .;
term_notready = .;
terms = .;
terms_i = .;
stage3_addr = .;
#else
#ifdef LINKER_NOS2MAP
stage2_map = .;
#else
*(.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
@ -54,33 +69,38 @@ 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
.note.gnu.build-id : {
*(.note.gnu.build-id)
limine_sys_size = . - 0x8000;
limine_sys_size = . - 0xf000;
} :data_s3
.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;
. = ALIGN(0x1000);
__text_end = ABSOLUTE(.);
__text_size = ABSOLUTE(__text_end - __text_start);
.rodata : {
__reloc_start = ABSOLUTE(.);
*(.dummy_reloc)
.data.sbat : {
*(.data.sbat)
. = ALIGN(0x1000);
} :data
__reloc_end = ABSOLUTE(.);
__reloc_size = ABSOLUTE(__reloc_end - __reloc_start);
PROVIDE(__sbat_sizev = 1);
__sbat_start = __text_end;
__sbat_size = SIZEOF(.data.sbat);
__sbat_end = __sbat_start + __sbat_size;
.data.reloc : {
*(.data.reloc)
. = ALIGN(0x1000);
} :data
__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;
. = ALIGN(0x1000);
__text_end = ABSOLUTE(.);
__text_size = ABSOLUTE(__text_end - __text_start);
.rodata : {
__reloc_start = ABSOLUTE(.);
*(.dummy_reloc)
.data.sbat : {
*(.data.sbat)
. = ALIGN(0x1000);
} :data
__reloc_end = ABSOLUTE(.);
__reloc_size = ABSOLUTE(__reloc_end - __reloc_start);
PROVIDE(__sbat_sizev = 1);
__sbat_start = __text_end;
__sbat_size = SIZEOF(.data.sbat);
__sbat_end = __sbat_start + __sbat_size;
.data.reloc : {
*(.data.reloc)
. = ALIGN(0x1000);
} :data
__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

@ -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;
. = ALIGN(0x1000);
__text_end = ABSOLUTE(.);
__text_size = ABSOLUTE(__text_end - __text_start);
.rodata : {
__reloc_start = ABSOLUTE(.);
*(.dummy_reloc)
.data.sbat : {
*(.data.sbat)
. = ALIGN(0x1000);
} :data
__reloc_end = ABSOLUTE(.);
__reloc_size = ABSOLUTE(__reloc_end - __reloc_start);
PROVIDE(__sbat_sizev = 1);
__sbat_start = __text_end;
__sbat_size = SIZEOF(.data.sbat);
__sbat_end = __sbat_start + __sbat_size;
.data.reloc : {
*(.data.reloc)
. = ALIGN(0x1000);
} :data
__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

@ -14,6 +14,7 @@
#include <lib/uri.h>
#include <mm/pmm.h>
#include <drivers/vbe.h>
#include <drivers/vga_textmode.h>
#include <console.h>
#include <protos/linux.h>
#include <protos/chainload.h>
@ -99,6 +100,19 @@ static const char *VALID_KEYS[] = {
"PARTITION",
"IMAGE_PATH",
"TERM_CONFIG_OVERRIDE",
"TERM_PALETTE",
"TERM_PALETTE_BRIGHT",
"TERM_BACKGROUND",
"TERM_FOREGROUND",
"TERM_WALLPAPER",
"TERM_MARGIN",
"TERM_MARGIN_GRADIENT",
"TERM_WALLPAPER_STYLE",
"TERM_BACKDROP",
"TERM_FONT_SIZE",
"TERM_FONT",
"TERM_FONT_SPACING",
"TERM_FONT_SCALE",
NULL
};
@ -154,17 +168,17 @@ static void putchar_tokencol(int type, char c) {
static bool editor_no_term_reset = false;
char *config_entry_editor(const char *title, const char *orig_entry) {
term_autoflush = false;
FOR_TERM(TERM->autoflush = false);
enable_cursor();
FOR_TERM(TERM->cursor_enabled = true);
print("\e[2J\e[H");
size_t cursor_offset = 0;
size_t entry_size = strlen(orig_entry);
size_t _window_size = term_rows - 8;
size_t _window_size = terms[0]->rows - 8;
size_t window_offset = 0;
size_t line_size = term_cols - 2;
size_t line_size = terms[0]->cols - 2;
bool display_overflow_error = false;
@ -200,44 +214,44 @@ refresh:
invalid_syntax = false;
print("\e[2J\e[H");
disable_cursor();
FOR_TERM(TERM->cursor_enabled = false);
{
size_t x, y;
print("\n");
get_cursor_pos(&x, &y);
set_cursor_pos_helper(term_cols / 2 - DIV_ROUNDUP(strlen(menu_branding), 2), y);
terms[0]->get_cursor_pos(terms[0], &x, &y);
set_cursor_pos_helper(terms[0]->cols / 2 - DIV_ROUNDUP(strlen(menu_branding), 2), y);
print("\e[3%sm%s\e[37m", menu_branding_colour, menu_branding);
print("\n\n");
}
print(" \e[32mESC\e[0m Discard and Exit \e[32mF10\e[0m Boot\n\n");
print(serial ? "/" : "\xda");
for (size_t i = 0; i < term_cols - 2; i++) {
print(serial ? "/" : "");
for (size_t i = 0; i < terms[0]->cols - 2; i++) {
switch (i) {
case 1: case 2: case 3:
if (window_offset > 0) {
print(serial ? "^" : "\x18");
print(serial ? "^" : "");
break;
}
// FALLTHRU
default: {
size_t title_length = strlen(title);
if (i == (term_cols / 2) - DIV_ROUNDUP(title_length, 2) - 1) {
if (i == (terms[0]->cols / 2) - DIV_ROUNDUP(title_length, 2) - 1) {
print("%s", title);
i += title_length - 1;
} else {
print(serial ? "-" : "\xc4");
print(serial ? "-" : "");
}
}
}
}
size_t tmpx, tmpy;
get_cursor_pos(&tmpx, &tmpy);
print(serial ? "\\" : "\xbf");
terms[0]->get_cursor_pos(terms[0], &tmpx, &tmpy);
print(serial ? "\\" : "");
set_cursor_pos_helper(0, tmpy + 1);
print(serial ? "|" : "\xb3");
print(serial ? "|" : "");
size_t cursor_x, cursor_y;
size_t current_line = 0, line_offset = 0, window_size = _window_size;
@ -250,23 +264,23 @@ refresh:
&& current_line < window_offset + window_size
&& current_line >= window_offset) {
size_t x, y;
get_cursor_pos(&x, &y);
terms[0]->get_cursor_pos(terms[0], &x, &y);
if (i == cursor_offset) {
cursor_x = x;
cursor_y = y;
printed_cursor = true;
}
set_cursor_pos_helper(term_cols - 1, y);
set_cursor_pos_helper(terms[0]->cols - 1, y);
if (current_line == window_offset + window_size - 1) {
get_cursor_pos(&tmpx, &tmpy);
print(serial ? "|" : "\xb3");
terms[0]->get_cursor_pos(terms[0], &tmpx, &tmpy);
print(serial ? "|" : "");
set_cursor_pos_helper(0, tmpy + 1);
print(serial ? "\\" : "\xc0");
print(serial ? "\\" : "");
} else {
get_cursor_pos(&tmpx, &tmpy);
print(serial ? "|" : "\xb3");
terms[0]->get_cursor_pos(terms[0], &tmpx, &tmpy);
print(serial ? "|" : "");
set_cursor_pos_helper(0, tmpy + 1);
print(serial ? "|" : "\xb3");
print(serial ? "|" : "");
}
line_offset = 0;
token_type = validate_line(buffer + i + 1);
@ -281,7 +295,7 @@ refresh:
if (current_line < window_offset + window_size
&& current_line >= window_offset) {
if (i == cursor_offset) {
get_cursor_pos(&cursor_x, &cursor_y);
terms[0]->get_cursor_pos(terms[0], &cursor_x, &cursor_y);
printed_cursor = true;
}
if (syntax_highlighting_enabled) {
@ -291,15 +305,15 @@ refresh:
}
printed_early = true;
size_t x, y;
get_cursor_pos(&x, &y);
if (y == term_rows - 3) {
print(serial ? ">" : "\x1a");
terms[0]->get_cursor_pos(terms[0], &x, &y);
if (y == terms[0]->rows - 3) {
print(serial ? ">" : "");
set_cursor_pos_helper(0, y + 1);
print(serial ? "\\" : "\xc0");
print(serial ? "\\" : "");
} else {
print(serial ? ">" : "\x1a");
print(serial ? ">" : "");
set_cursor_pos_helper(0, y + 1);
print(serial ? "<" : "\x1b\x1b");
print(serial ? "<" : "");
}
}
window_size--;
@ -309,7 +323,7 @@ refresh:
&& current_line < window_offset + window_size
&& current_line >= window_offset
&& !printed_cursor) {
get_cursor_pos(&cursor_x, &cursor_y);
terms[0]->get_cursor_pos(terms[0], &cursor_x, &cursor_y);
printed_cursor = true;
}
@ -356,62 +370,62 @@ refresh:
// syntax error alert
if (validation_enabled) {
size_t x, y;
get_cursor_pos(&x, &y);
set_cursor_pos_helper(0, term_rows-1);
scroll_disable();
terms[0]->get_cursor_pos(terms[0], &x, &y);
set_cursor_pos_helper(0, terms[0]->rows - 1);
FOR_TERM(TERM->scroll_enabled = false);
if (invalid_syntax) {
print("\e[31mConfiguration is INVALID.\e[0m");
} else {
print("\e[32mConfiguration is valid.\e[0m");
}
scroll_enable();
FOR_TERM(TERM->scroll_enabled = true);
set_cursor_pos_helper(x, y);
}
if (current_line - window_offset < window_size) {
size_t x, y;
for (size_t i = 0; i < (window_size - (current_line - window_offset)) - 1; i++) {
get_cursor_pos(&x, &y);
set_cursor_pos_helper(term_cols - 1, y);
print(serial ? "|" : "\xb3");
terms[0]->get_cursor_pos(terms[0], &x, &y);
set_cursor_pos_helper(terms[0]->cols - 1, y);
print(serial ? "|" : "");
set_cursor_pos_helper(0, y + 1);
print(serial ? "|" : "\xb3");
print(serial ? "|" : "");
}
get_cursor_pos(&x, &y);
set_cursor_pos_helper(term_cols - 1, y);
print(serial ? "|" : "\xb3");
terms[0]->get_cursor_pos(terms[0], &x, &y);
set_cursor_pos_helper(terms[0]->cols - 1, y);
print(serial ? "|" : "");
set_cursor_pos_helper(0, y + 1);
print(serial ? "\\" : "\xc0");
print(serial ? "\\" : "");
}
for (size_t i = 0; i < term_cols - 2; i++) {
for (size_t i = 0; i < terms[0]->cols - 2; i++) {
switch (i) {
case 1: case 2: case 3:
if (current_line - window_offset >= window_size) {
print(serial ? "v" : "\x19");
print(serial ? "v" : "");
break;
}
// FALLTHRU
default:
print(serial ? "-" : "\xc4");
print(serial ? "-" : "");
}
}
get_cursor_pos(&tmpx, &tmpy);
print(serial ? "/" : "\xd9");
terms[0]->get_cursor_pos(terms[0], &tmpx, &tmpy);
print(serial ? "/" : "");
set_cursor_pos_helper(0, tmpy + 1);
if (display_overflow_error) {
scroll_disable();
FOR_TERM(TERM->scroll_enabled = false);
print("\e[31mText buffer not big enough, delete something instead.");
scroll_enable();
FOR_TERM(TERM->scroll_enabled = true);
display_overflow_error = false;
}
// Hack to redraw the cursor
set_cursor_pos_helper(cursor_x, cursor_y);
enable_cursor();
FOR_TERM(TERM->cursor_enabled = true);
term_double_buffer_flush();
FOR_TERM(TERM->double_buffer_flush(TERM));
int c = getchar();
size_t buffer_len = strlen(buffer);
@ -479,19 +493,39 @@ refresh:
goto refresh;
}
static size_t print_tree(const char *shift, size_t level, size_t base_index, size_t selected_entry,
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) {
goto skip_line;
}
if (!no_print && base_index + max_entries >= offset + window) {
goto skip_line;
}
if (!no_print) print("%s", shift);
if (level) {
for (size_t i = level - 1; i > 0; i--) {
@ -499,46 +533,59 @@ static size_t print_tree(const char *shift, size_t level, size_t base_index, siz
for (size_t j = 0; j < i; j++)
actual_parent = actual_parent->parent;
if (actual_parent->next != NULL) {
if (!no_print) print(serial ? " |" : " \xb3");
if (!no_print) print(serial ? " |" : " ");
} else {
if (!no_print) print(" ");
}
cur_len += 2;
}
if (current_entry->next == NULL) {
if (!no_print) print(serial ? " `" : " \xc0");
if (!no_print) print(serial ? " `" : " ");
} else {
if (!no_print) print(serial ? " |" : " \xc3");
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 ? "-> " : "\xc4> ");
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(shift, level + 1, base_index + max_entries + 1,
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;
}
static struct memmap_entry *rewound_memmap = NULL;
static size_t rewound_memmap_entries = 0;
static uint8_t *rewound_data;
static no_unwind uint8_t *rewound_data;
#if defined (BIOS)
static uint8_t *rewound_s2_data;
static no_unwind uint8_t *rewound_s2_data;
static no_unwind uint8_t *rewound_bss;
#endif
extern symbol data_begin;
@ -546,18 +593,53 @@ 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
noreturn void _menu(bool timeout_enabled) {
static void menu_init_term(void) {
// If there is GRAPHICS config key and the value is "yes", enable graphics
#if defined (BIOS)
char *graphics = config_get_value(NULL, 0, "GRAPHICS");
#elif defined (UEFI)
char *graphics = "yes";
#endif
if (graphics == NULL || strcmp(graphics, "no") != 0) {
size_t req_width = 0, req_height = 0, req_bpp = 0;
char *menu_resolution = config_get_value(NULL, 0, "INTERFACE_RESOLUTION");
if (menu_resolution != NULL)
parse_resolution(&req_width, &req_height, &req_bpp, menu_resolution);
if (!quiet && !gterm_init(NULL, NULL, NULL, req_width, req_height)) {
#if defined (BIOS)
vga_textmode_init(true);
#elif defined (UEFI)
term_fallback();
#endif
}
} else {
#if defined (BIOS)
if (!quiet) {
vga_textmode_init(true);
}
#endif
}
}
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;
@ -565,23 +647,36 @@ noreturn void _menu(bool timeout_enabled) {
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
}
term_fallback();
if (bad_config == false) {
#if defined (UEFI)
if (init_config_disk(boot_volume)) {
#endif
volume_iterate_parts(boot_volume,
if (!init_config_disk(_PART)) {
boot_volume = _PART;
break;
}
);
#if defined (UEFI)
}
#endif
}
char *quiet_str = config_get_value(NULL, 0, "QUIET");
@ -593,13 +688,14 @@ noreturn void _menu(bool timeout_enabled) {
char *serial_str = config_get_value(NULL, 0, "SERIAL");
serial = serial_str != NULL && strcmp(serial_str, "yes") == 0;
char *hash_mismatch_panic_str = config_get_value(NULL, 0, "HASH_MISMATCH_PANIC");
hash_mismatch_panic = hash_mismatch_panic_str == NULL || strcmp(hash_mismatch_panic_str, "yes") == 0;
char *randomise_mem_str = config_get_value(NULL, 0, "RANDOMISE_MEMORY");
if (randomise_mem_str == NULL)
randomise_mem_str = config_get_value(NULL, 0, "RANDOMIZE_MEMORY");
bool randomise_mem = randomise_mem_str != NULL && strcmp(randomise_mem_str, "yes") == 0;
if (randomise_mem) {
term_vbe(NULL, 0, 0);
early_term = true;
pmm_randomise_memory();
}
@ -608,6 +704,11 @@ noreturn void _menu(bool timeout_enabled) {
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;
@ -638,15 +739,16 @@ noreturn void _menu(bool timeout_enabled) {
timeout = strtoui(timeout_config, NULL, 10);
}
if (!timeout_enabled) {
if (!first_run) {
skip_timeout = true;
}
if (!skip_timeout && !timeout) {
// Use print tree to load up selected_menu_entry and determine if the
// default entry is valid.
print_tree(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");
skip_timeout = true;
} else {
@ -654,96 +756,84 @@ noreturn void _menu(bool timeout_enabled) {
}
}
// If there is GRAPHICS config key and the value is "yes", enable graphics
#if defined (BIOS)
char *graphics = config_get_value(NULL, 0, "GRAPHICS");
#elif defined (UEFI)
char *graphics = "yes";
#endif
menu_init_term();
reterm:
if (graphics == NULL || strcmp(graphics, "no") != 0) {
size_t req_width = 0, req_height = 0, req_bpp = 0;
char *menu_resolution = config_get_value(NULL, 0, "INTERFACE_RESOLUTION");
if (menu_resolution != NULL)
parse_resolution(&req_width, &req_height, &req_bpp, menu_resolution);
term_vbe(NULL, req_width, req_height);
} else {
#if defined (BIOS)
term_textmode();
#endif
}
size_t tree_offset = 0;
refresh:
term_autoflush = false;
if (selected_entry >= tree_offset + terms[0]->rows - 10) {
tree_offset = selected_entry - (terms[0]->rows - 11);
}
if (selected_entry < tree_offset) {
tree_offset = selected_entry;
}
disable_cursor();
FOR_TERM(TERM->autoflush = false);
FOR_TERM(TERM->cursor_enabled = false);
print("\e[2J\e[H");
{
size_t x, y;
print("\n");
get_cursor_pos(&x, &y);
set_cursor_pos_helper(term_cols / 2 - DIV_ROUNDUP(strlen(menu_branding), 2), y);
terms[0]->get_cursor_pos(terms[0], &x, &y);
set_cursor_pos_helper(terms[0]->cols / 2 - DIV_ROUNDUP(strlen(menu_branding), 2), y);
print("\e[3%sm%s\e[37m", menu_branding_colour, menu_branding);
print("\n\n\n\n");
}
while (menu_tree == NULL) {
if (quiet) {
quiet = false;
menu_init_term();
FOR_TERM(TERM->autoflush = false);
FOR_TERM(TERM->cursor_enabled = false);
}
print("Config file %s.\n\n", config_ready ? "contains no valid entries" : "not found");
print("For information on the format of Limine config entries, consult CONFIG.md in\n");
print("the root of the Limine source repository.\n\n");
print("Press a key to enter the Limine console...");
term_double_buffer_flush();
FOR_TERM(TERM->double_buffer_flush(TERM));
getchar();
reset_term();
console();
}
{ // Draw box around boot menu
size_t x, y;
get_cursor_pos(&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 ? "/" : "\xda");
for (size_t i = 0; i < term_cols - 2; i++) {
print(serial ? "-" : "\xc4");
}
print(serial ? "\\" : "\xbf");
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 < term_rows - 2; i++) {
set_cursor_pos_helper(0, i);
print(serial ? "|" : "\xb3");
set_cursor_pos_helper(term_cols - 1, i);
print(serial ? "|" : "\xb3");
}
set_cursor_pos_helper(0, term_rows - 2);
set_cursor_pos_helper(0, terms[0]->rows / 2 - DIV_ROUNDUP(max_tree_height, 2));
print(serial ? "\\" : "\xc0");
for (size_t i = 0; i < term_cols - 2; i++) {
print(serial ? "-" : "\xc4");
}
print(serial ? "/" : "\xd9");
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(serial ? "| " : "\xb3 ", 0, 0, selected_entry, menu_tree,
&selected_menu_entry);
pmm_free(tree_prefix, tree_prefix_len);
{
size_t x, y;
get_cursor_pos(&x, &y);
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");
} else {
print(" \e[32mARROWS\e[0m Select \e[32mENTER\e[0m %s",
selected_menu_entry->expanded ? "Collapse" : "Expand");
terms[0]->get_cursor_pos(terms[0], &x, &y);
if (tree_offset + (terms[0]->rows - 10) < max_entries) {
set_cursor_pos_helper(2, terms[0]->rows - 2);
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");
} else {
print(" \e[32mARROWS\e[0m Select \e[32mENTER\e[0m %s",
selected_menu_entry->expanded ? "Collapse" : "Expand");
}
set_cursor_pos_helper(terms[0]->cols - 13, 3);
print("\e[32mC\e[0m Console");
}
set_cursor_pos_helper(term_cols - 13, 3);
print("\e[32mC\e[0m Console");
set_cursor_pos_helper(x, y);
}
@ -755,34 +845,34 @@ refresh:
if (skip_timeout == false) {
print("\n\n");
for (size_t i = timeout; i; i--) {
set_cursor_pos_helper(0, term_rows - 1);
scroll_disable();
set_cursor_pos_helper(0, terms[0]->rows - 1);
FOR_TERM(TERM->scroll_enabled = false);
print("\e[2K\e[32mBooting automatically in \e[92m%u\e[32m, press any key to stop the countdown...\e[0m", i);
scroll_enable();
term_double_buffer_flush();
FOR_TERM(TERM->scroll_enabled = true);
FOR_TERM(TERM->double_buffer_flush(TERM));
if ((c = pit_sleep_and_quit_on_keypress(1))) {
skip_timeout = true;
if (quiet) {
quiet = false;
goto reterm;
} else {
print("\e[2K");
term_double_buffer_flush();
menu_init_term();
goto timeout_aborted;
}
print("\e[2K");
FOR_TERM(TERM->double_buffer_flush(TERM));
goto timeout_aborted;
}
}
goto autoboot;
}
set_cursor_pos_helper(0, term_rows - 1);
set_cursor_pos_helper(0, terms[0]->rows - 1);
if (selected_menu_entry->comment != NULL) {
scroll_disable();
FOR_TERM(TERM->scroll_enabled = false);
print("\e[36m%s\e[0m", selected_menu_entry->comment);
scroll_enable();
FOR_TERM(TERM->scroll_enabled = true);
}
term_double_buffer_flush();
FOR_TERM(TERM->double_buffer_flush(TERM));
for (;;) {
c = getchar();
@ -793,8 +883,8 @@ timeout_aborted:
int ent = (c - '0') - 1;
if (ent < (int)max_entries) {
selected_entry = ent;
print_tree(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);
goto autoboot;
}
goto refresh;
@ -823,15 +913,18 @@ timeout_aborted:
selected_menu_entry->expanded = !selected_menu_entry->expanded;
goto refresh;
}
if (term_backend == NOT_READY) {
term_vbe(NULL, 0, 0);
if (!quiet) {
if (term_backend == FALLBACK) {
if (!gterm_init(NULL, NULL, NULL, 0, 0)) {
#if defined (BIOS)
if (term_backend == NOT_READY) {
term_textmode();
}
vga_textmode_init(true);
#elif defined (UEFI)
term_fallback();
#endif
} else {
reset_term();
}
} else {
reset_term();
}
}
boot(selected_menu_entry->body);
case 'e':
@ -873,6 +966,7 @@ noreturn void boot(char *config) {
}
if (!strcmp(proto, "stivale1") || !strcmp(proto, "stivale") || !strcmp(proto, "stivale2")) {
quiet = false;
print("The stivale and stivale2 protocols are no longer supported as of Limine 4.x\n");
print("Please notify kernel maintainers to move to the Limine boot protocol or\n");
print("roll back to Limine 3.x.\n\n");
@ -882,25 +976,28 @@ noreturn void boot(char *config) {
#if defined (__x86_64__) || defined (__i386__)
linux_load(config, cmdline);
#else
quiet = false;
print("TODO: Linux is not available on aarch64.\n\n");
#endif
} else if (!strcmp(proto, "multiboot1") || !strcmp(proto, "multiboot")) {
#if defined (__x86_64__) || defined (__i386__)
multiboot1_load(config, cmdline);
#else
quiet = false;
print("Multiboot 1 is not available on aarch64.\n\n");
#endif
} else if (!strcmp(proto, "multiboot2")) {
#if defined (__x86_64__) || defined (__i386__)
multiboot2_load(config, cmdline);
#else
quiet = false;
print("Multiboot 2 is not available on aarch64.\n\n");
#endif
} else if (!strcmp(proto, "chainload_next")) {
chainload_next(config);
chainload_next(config, cmdline);
} else if (!strcmp(proto, "chainload")) {
chainload(config);
chainload(config, cmdline);
}
panic(true, "Incorrect protocol specified for kernel.");
panic(true, "Unsupported protocol specified for kernel.");
}

View File

@ -4,7 +4,7 @@
#include <stdbool.h>
#include <stdnoreturn.h>
noreturn void menu(bool timeout_enabled);
noreturn void menu(bool first_run);
noreturn void boot(char *config);

View File

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

View File

@ -1,3 +1,5 @@
section .text
global menu
extern _menu
menu:
@ -24,3 +26,4 @@ menu:
push 0
jmp _menu
section .note.GNU-stack noalloc noexec nowrite 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;
@ -37,6 +39,9 @@ extern size_t memmap_entries;
#if defined (UEFI)
extern struct memmap_entry *memmap;
extern size_t memmap_entries;
extern struct memmap_entry *untouched_memmap;
extern size_t untouched_memmap_entries;
#endif
extern bool allocations_disallowed;
@ -53,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

@ -32,7 +32,7 @@ void *conv_mem_alloc(size_t count) {
if (base + count > 0x100000)
panic(false, "Conventional memory allocation failed");
if (memmap_alloc_range(base, count, MEMMAP_BOOTLOADER_RECLAIMABLE, true, false, false, false)) {
if (memmap_alloc_range(base, count, MEMMAP_BOOTLOADER_RECLAIMABLE, MEMMAP_USABLE, false, false, false)) {
void *ret = (void *)(uintptr_t)base;
// Zero out allocated space
memset(ret, 0, count);
@ -60,8 +60,8 @@ static size_t memmap_max_entries;
struct memmap_entry *memmap;
size_t memmap_entries = 0;
static struct memmap_entry *untouched_memmap;
static size_t untouched_memmap_entries = 0;
struct memmap_entry *untouched_memmap;
size_t untouched_memmap_entries = 0;
#endif
static const char *memmap_type(uint32_t type) {
@ -91,11 +91,11 @@ static const char *memmap_type(uint32_t type) {
void print_memmap(struct memmap_entry *mm, size_t size) {
for (size_t i = 0; i < size; i++) {
printv("[%X -> %X] : %X <%s (%x)>\n",
mm[i].base,
mm[i].base + mm[i].length,
mm[i].length,
memmap_type(mm[i].type), mm[i].type);
print("[%X -> %X] : %X <%s (%x)>\n",
mm[i].base,
mm[i].base + mm[i].length,
mm[i].length,
memmap_type(mm[i].type), mm[i].type);
}
}
@ -116,6 +116,8 @@ static bool align_entry(uint64_t *base, uint64_t *length) {
return true;
}
static bool sanitiser_keep_first_page = false;
static void sanitise_entries(struct memmap_entry *m, size_t *_count, bool align_entries) {
size_t count = *_count;
@ -167,7 +169,7 @@ static void sanitise_entries(struct memmap_entry *m, size_t *_count, bool align_
if (m[i].type != MEMMAP_USABLE)
continue;
if (m[i].base < 0x1000) {
if (!sanitiser_keep_first_page && m[i].base < 0x1000) {
if (m[i].base + m[i].length <= 0x1000) {
goto del_mm1;
}
@ -227,6 +229,10 @@ static void pmm_reclaim_uefi_mem(struct memmap_entry *m, size_t *_count);
struct memmap_entry *get_memmap(size_t *entries) {
#if defined (UEFI)
if (efi_boot_services_exited == false) {
panic(true, "get_memmap called whilst in boot services");
}
pmm_reclaim_uefi_mem(memmap, &memmap_entries);
#endif
@ -271,7 +277,7 @@ void init_memmap(void) {
// Allocate bootloader itself
memmap_alloc_range(4096,
ALIGN_UP((uintptr_t)bss_end, 4096) - 4096, MEMMAP_BOOTLOADER_RECLAIMABLE, true, true, false, false);
ALIGN_UP((uintptr_t)bss_end, 4096) - 4096, MEMMAP_BOOTLOADER_RECLAIMABLE, 0, true, false, false);
sanitise_entries(memmap, &memmap_entries, false);
@ -280,8 +286,10 @@ void init_memmap(void) {
#endif
#if defined (UEFI)
extern symbol __image_base;
extern symbol __image_end;
static struct memmap_entry *recl;
extern symbol __slide;
extern symbol __image_size;
void init_memmap(void) {
EFI_STATUS status;
@ -348,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) {
@ -366,6 +375,7 @@ void init_memmap(void) {
our_type = MEMMAP_EFI_RECLAIMABLE;
}
}
#endif
memmap[memmap_entries].base = base;
memmap[memmap_entries].length = length;
@ -374,6 +384,8 @@ void init_memmap(void) {
memmap_entries++;
}
bool old_skfp = sanitiser_keep_first_page;
sanitiser_keep_first_page = true;
sanitise_entries(memmap, &memmap_entries, false);
allocations_disallowed = false;
@ -383,33 +395,43 @@ void init_memmap(void) {
ext_mem_alloc_type(0x100000, MEMMAP_EFI_RECLAIMABLE);
}
memcpy(untouched_memmap, memmap, memmap_entries * sizeof(struct memmap_entry));
untouched_memmap_entries = memmap_entries;
// Now own all the usable entries
for (size_t i = 0; i < memmap_entries; i++) {
if (memmap[i].type != MEMMAP_USABLE)
for (size_t i = 0; i < untouched_memmap_entries; i++) {
if (untouched_memmap[i].type != MEMMAP_USABLE)
continue;
EFI_PHYSICAL_ADDRESS base = memmap[i].base;
EFI_PHYSICAL_ADDRESS base = untouched_memmap[i].base;
status = gBS->AllocatePages(AllocateAddress, EfiLoaderData,
memmap[i].length / 4096, &base);
untouched_memmap[i].length / 4096, &base);
if (status) {
print("pmm: WARNING: AllocatePages failure (%d)\n", status);
memmap_alloc_range(memmap[i].base, memmap[i].length, MEMMAP_RESERVED, true, true, false, false);
for (size_t j = 0; j < untouched_memmap[i].length; j += 4096) {
base = untouched_memmap[i].base + j;
status = gBS->AllocatePages(AllocateAddress, EfiLoaderData, 1, &base);
if (status) {
memmap_alloc_range(base, 4096, MEMMAP_EFI_RECLAIMABLE, MEMMAP_USABLE, true, false, false);
}
}
}
}
memcpy(untouched_memmap, memmap, memmap_entries * sizeof(struct memmap_entry));
untouched_memmap_entries = memmap_entries;
size_t bootloader_size = ALIGN_UP((uintptr_t)__image_end - (uintptr_t)__image_base, 4096);
sanitiser_keep_first_page = old_skfp;
// Allocate bootloader itself
memmap_alloc_range((uintptr_t)__image_base, bootloader_size,
MEMMAP_BOOTLOADER_RECLAIMABLE, false, true, false, true);
memmap_alloc_range((uintptr_t)__slide, (uintptr_t)__image_size,
MEMMAP_BOOTLOADER_RECLAIMABLE, 0, true, false, true);
sanitise_entries(memmap, &memmap_entries, false);
recl = ext_mem_alloc(1024 * sizeof(struct memmap_entry));
return;
fail:
@ -423,15 +445,7 @@ static void pmm_reclaim_uefi_mem(struct memmap_entry *m, size_t *_count) {
for (size_t i = 0; i < count; i++) {
if (m[i].type == MEMMAP_EFI_RECLAIMABLE) {
recl_i++;
}
}
struct memmap_entry *recl = ext_mem_alloc(recl_i * sizeof(struct memmap_entry));
for (size_t i = 0, j = 0; i < count; i++) {
if (m[i].type == MEMMAP_EFI_RECLAIMABLE) {
recl[j++] = m[i];
recl[recl_i++] = m[i];
}
}
@ -524,7 +538,15 @@ struct memmap_entry *get_raw_memmap(size_t *entry_count) {
#if defined (UEFI)
struct memmap_entry *get_raw_memmap(size_t *entry_count) {
if (efi_boot_services_exited == false) {
panic(true, "get_raw_memmap called whilst in boot services");
}
bool old_skfp = sanitiser_keep_first_page;
sanitiser_keep_first_page = true;
pmm_reclaim_uefi_mem(untouched_memmap, &untouched_memmap_entries);
sanitiser_keep_first_page = old_skfp;
*entry_count = untouched_memmap_entries;
return untouched_memmap;
}
@ -534,7 +556,7 @@ void pmm_free(void *ptr, size_t count) {
count = ALIGN_UP(count, 4096);
if (allocations_disallowed)
panic(false, "Memory allocations disallowed");
memmap_alloc_range((uintptr_t)ptr, count, MEMMAP_USABLE, false, false, false, true);
memmap_alloc_range((uintptr_t)ptr, count, MEMMAP_USABLE, 0, false, false, true);
}
void *ext_mem_alloc(size_t count) {
@ -545,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)
@ -559,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);
@ -574,7 +610,7 @@ void *ext_mem_alloc_type_aligned(size_t count, uint32_t type, size_t alignment)
// We now reserve the range we need.
int64_t aligned_length = entry_top - alloc_base;
memmap_alloc_range((uint64_t)alloc_base, (uint64_t)aligned_length, type, true, true, false, false);
memmap_alloc_range((uint64_t)alloc_base, (uint64_t)aligned_length, type, MEMMAP_USABLE, true, false, false);
void *ret = (void *)(size_t)alloc_base;

View File

@ -10,6 +10,16 @@
typedef uint64_t pt_entry_t;
// Maps level indexes to the page size for that level.
_Static_assert(VMM_MAX_LEVEL <= 5, "6-level paging not supported");
static uint64_t page_sizes[5] = {
0x1000,
0x200000,
0x40000000,
0x8000000000,
0x1000000000000,
};
static pt_entry_t *get_next_level(pagemap_t pagemap, pt_entry_t *current_level,
uint64_t virt, enum page_size desired_sz,
size_t level_idx, size_t entry);
@ -28,9 +38,12 @@ static pt_entry_t *get_next_level(pagemap_t pagemap, pt_entry_t *current_level,
#define PT_IS_LARGE(x) (((x) & (PT_FLAG_VALID | PT_FLAG_LARGE)) == (PT_FLAG_VALID | PT_FLAG_LARGE))
#define PT_TO_VMM_FLAGS(x) ((x) & (PT_FLAG_WRITE | PT_FLAG_NX))
pagemap_t new_pagemap(int lv) {
#define pte_new(addr, flags) ((pt_entry_t)(addr) | (flags))
#define pte_addr(pte) ((pte) & PT_PADDR_MASK)
pagemap_t new_pagemap(int paging_mode) {
pagemap_t pagemap;
pagemap.levels = lv;
pagemap.levels = paging_mode == PAGING_MODE_X86_64_5LVL ? 5 : 4;
pagemap.top_level = ext_mem_alloc(PT_SIZE);
return pagemap;
}
@ -106,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);
}
@ -146,6 +165,9 @@ void vmm_assert_4k_pages(void) {
#define PT_IS_LARGE(x) (((x) & (PT_FLAG_VALID | PT_FLAG_TABLE)) == PT_FLAG_VALID)
#define PT_TO_VMM_FLAGS(x) (pt_to_vmm_flags_internal(x))
#define pte_new(addr, flags) ((pt_entry_t)(addr) | (flags))
#define pte_addr(pte) ((pte) & PT_PADDR_MASK)
static uint64_t pt_to_vmm_flags_internal(pt_entry_t entry) {
uint64_t flags = 0;
@ -159,9 +181,9 @@ static uint64_t pt_to_vmm_flags_internal(pt_entry_t entry) {
return flags;
}
pagemap_t new_pagemap(int lv) {
pagemap_t new_pagemap(int paging_mode) {
pagemap_t pagemap;
pagemap.levels = lv;
pagemap.levels = paging_mode == PAGING_MODE_AARCH64_5LVL ? 5 : 4;
pagemap.top_level[0] = ext_mem_alloc(PT_SIZE);
pagemap.top_level[1] = ext_mem_alloc(PT_SIZE);
return pagemap;
@ -231,47 +253,25 @@ static pt_entry_t *get_next_level(pagemap_t pagemap, pt_entry_t *current_level,
pt_entry_t *ret;
if (PT_IS_TABLE(current_level[entry])) {
ret = (pt_entry_t *)(size_t)(current_level[entry] & PT_PADDR_MASK);
ret = (pt_entry_t *)(size_t)pte_addr(current_level[entry]);
} else {
if (PT_IS_LARGE(current_level[entry])) {
// We are replacing an existing large page with a smaller page.
// Split the previous mapping into mappings of the newly requested size
// before performing the requested map operation.
uint64_t old_page_size, new_page_size;
switch (level_idx) {
case 2:
old_page_size = 0x40000000;
break;
case 1:
old_page_size = 0x200000;
break;
if ((level_idx >= VMM_MAX_LEVEL) || (level_idx == 0))
panic(false, "Unexpected level in get_next_level");
if (desired_sz >= VMM_MAX_LEVEL)
panic(false, "Unexpected page size in get_next_level");
default:
panic(false, "Unexpected level in get_next_level");
}
switch (desired_sz) {
case Size1GiB:
new_page_size = 0x40000000;
break;
case Size2MiB:
new_page_size = 0x200000;
break;
case Size4KiB:
new_page_size = 0x1000;
break;
default:
panic(false, "Unexpected page size in get_next_level");
}
uint64_t old_page_size = page_sizes[level_idx];
uint64_t new_page_size = page_sizes[desired_sz];
// Save all the information from the old entry at this level
uint64_t old_flags = PT_TO_VMM_FLAGS(current_level[entry]);
uint64_t old_phys = current_level[entry] & PT_PADDR_MASK;
uint64_t old_phys = pte_addr(current_level[entry]);
uint64_t old_virt = virt & ~(old_page_size - 1);
if (old_phys & (old_page_size - 1))
@ -279,7 +279,7 @@ static pt_entry_t *get_next_level(pagemap_t pagemap, pt_entry_t *current_level,
// Allocate a table for the next level
ret = ext_mem_alloc(PT_SIZE);
current_level[entry] = (pt_entry_t)(size_t)ret | PT_TABLE_FLAGS;
current_level[entry] = pte_new((size_t)ret, PT_TABLE_FLAGS);
// Recreate the old mapping with smaller pages
for (uint64_t i = 0; i < old_page_size; i += new_page_size) {
@ -288,11 +288,9 @@ static pt_entry_t *get_next_level(pagemap_t pagemap, pt_entry_t *current_level,
} else {
// Allocate a table for the next level
ret = ext_mem_alloc(PT_SIZE);
current_level[entry] = (pt_entry_t)(size_t)ret | PT_TABLE_FLAGS;
current_level[entry] = pte_new((size_t)ret, PT_TABLE_FLAGS);
}
}
return ret;
}

View File

@ -8,7 +8,22 @@
#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
#define PAGING_MODE_X86_64_4LVL 0
#define PAGING_MODE_X86_64_5LVL 1
#define paging_mode_va_bits(mode) ((mode) ? 57 : 48)
static inline uint64_t paging_mode_higher_half(int paging_mode) {
if (paging_mode == PAGING_MODE_X86_64_5LVL) {
return 0xff00000000000000;
} else {
return 0xffff800000000000;
}
}
typedef struct {
int levels;
@ -32,6 +47,21 @@ void map_page(pagemap_t pagemap, uint64_t virt_addr, uint64_t phys_addr, uint64_
#define VMM_FLAG_NOEXEC ((uint64_t)1 << 1)
#define VMM_FLAG_FB ((uint64_t)1 << 2)
#define VMM_MAX_LEVEL 3
#define PAGING_MODE_AARCH64_4LVL 0
#define PAGING_MODE_AARCH64_5LVL 1
#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 0xffc0000000000000;
} else {
return 0xffff000000000000;
}
}
typedef struct {
int levels;
void *top_level[2];

View File

@ -21,7 +21,7 @@
#if defined (BIOS)
__attribute__((noinline, section(".realmode")))
noreturn static void spinup(uint8_t drive) {
noreturn static void spinup(uint8_t drive, void *buf) {
struct idtr real_mode_idt;
real_mode_idt.limit = 0x3ff;
real_mode_idt.ptr = 0;
@ -30,6 +30,14 @@ noreturn static void spinup(uint8_t drive) {
"cli\n\t"
"cld\n\t"
// Safe stack location
"mov $0x7c00, %%esp\n\t"
// move buffer to final location
"mov $0x7c00, %%edi\n\t"
"mov $512, %%ecx\n\t"
"rep movsb\n\t"
"lidt (%%eax)\n\t"
"pushl $0x08\n\t"
@ -65,14 +73,16 @@ noreturn static void spinup(uint8_t drive) {
".code32\n\t"
:
: "a" (&real_mode_idt), "d" (drive)
: "a" (&real_mode_idt), "d" (drive), "S"(buf)
: "memory"
);
__builtin_unreachable();
}
noreturn void chainload(char *config) {
noreturn void chainload(char *config, char *cmdline) {
(void)cmdline;
uint64_t val;
int part; {
@ -173,23 +183,24 @@ load:
}
void bios_chainload_volume(struct volume *p) {
size_t rows, cols;
init_vga_textmode(&rows, &cols, false);
vga_textmode_init(false);
volume_read(p, (void *)0x7c00, 0, 512);
void *buf = ext_mem_alloc(512);
volatile uint16_t *boot_sig = (volatile uint16_t *)0x7dfe;
volume_read(p, buf, 0, 512);
uint16_t *boot_sig = (uint16_t *)(buf + 0x1fe);
if (*boot_sig != 0xaa55) {
return;
}
spinup(p->drive);
spinup(p->drive, buf);
}
#elif defined (UEFI)
noreturn void chainload(char *config) {
noreturn void chainload(char *config, char *cmdline) {
char *image_path = config_get_value(config, 0, "IMAGE_PATH");
if (image_path == NULL)
panic(true, "chainload: IMAGE_PATH not specified");
@ -198,26 +209,24 @@ noreturn void chainload(char *config) {
if ((image = uri_open(image_path)) == NULL)
panic(true, "chainload: Failed to open image with path `%s`. Is the path correct?", image_path);
efi_chainload_file(config, image);
efi_chainload_file(config, cmdline, image);
}
noreturn void efi_chainload_file(char *config, struct file_handle *image) {
noreturn void efi_chainload_file(char *config, char *cmdline, struct file_handle *image) {
EFI_STATUS status;
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_deinit();
term_notready();
size_t req_width = 0, req_height = 0, req_bpp = 0;
@ -225,9 +234,19 @@ noreturn void efi_chainload_file(char *config, struct file_handle *image) {
if (resolution != NULL)
parse_resolution(&req_width, &req_height, &req_bpp, resolution);
struct fb_info fbinfo;
if (!fb_init(&fbinfo, req_width, req_height, req_bpp))
panic(true, "chainload: Unable to set video mode");
struct fb_info *fbinfo;
size_t fb_count;
fb_init(&fbinfo, &fb_count, req_width, req_height, req_bpp);
size_t cmdline_len = strlen(cmdline);
CHAR16 *new_cmdline;
status = gBS->AllocatePool(EfiLoaderData, (cmdline_len + 1) * sizeof(CHAR16), (void **)&new_cmdline);
if (status) {
panic(true, "chainload: Allocation failure");
}
for (size_t i = 0; i < cmdline_len + 1; i++) {
new_cmdline[i] = cmdline[i];
}
pmm_release_uefi_mem();
@ -271,6 +290,9 @@ noreturn void efi_chainload_file(char *config, struct file_handle *image) {
new_handle_loaded_image->DeviceHandle = efi_part_handle;
}
new_handle_loaded_image->LoadOptionsSize = cmdline_len * sizeof(CHAR16);
new_handle_loaded_image->LoadOptions = new_cmdline;
UINTN exit_data_size = 0;
CHAR16 *exit_data = NULL;
EFI_STATUS exit_status = gBS->StartImage(new_handle, &exit_data_size, &exit_data);

View File

@ -3,11 +3,11 @@
#include <stdnoreturn.h>
noreturn void chainload(char *config);
noreturn void chainload(char *config, char *cmdline);
#if defined (UEFI)
#include <fs/file.h>
noreturn void efi_chainload_file(char *config, struct file_handle *image);
noreturn void efi_chainload_file(char *config, char *cmdline, struct file_handle *image);
#endif
#if defined (BIOS)

View File

@ -8,14 +8,15 @@
#include <lib/part.h>
#if defined (BIOS)
static void try(char *config, struct volume *v) {
static void try(char *config, char *cmdline, struct volume *v) {
(void)config;
(void)cmdline;
bios_chainload_volume(v);
}
#endif
#if defined (UEFI)
static void try(char *config, struct volume *v) {
static void try(char *config, char *cmdline, struct volume *v) {
for (int i = 0; i <= v->max_partition + 1; i++) {
struct file_handle *image;
struct volume *p = volume_get_by_coord(v->is_optical, v->index, i);
@ -28,12 +29,12 @@ static void try(char *config, struct volume *v) {
}
case_insensitive_fopen = old_cif;
efi_chainload_file(config, image);
efi_chainload_file(config, cmdline, image);
}
}
#endif
noreturn void chainload_next(char *config) {
noreturn void chainload_next(char *config, char *cmdline) {
bool wrap = false;
for (int i = boot_volume->is_optical ? 0 : (wrap = true, boot_volume->index + 1);
boot_volume->is_optical ? true : i != boot_volume->index; i++) {
@ -47,7 +48,7 @@ noreturn void chainload_next(char *config) {
}
}
try(config, v);
try(config, cmdline, v);
}
wrap = false;
@ -63,7 +64,7 @@ noreturn void chainload_next(char *config) {
}
}
try(config, v);
try(config, cmdline, v);
}
panic(true, "chainload_next: No other bootable device");

View File

@ -3,6 +3,6 @@
#include <stdnoreturn.h>
noreturn void chainload_next(char *config);
noreturn void chainload_next(char *config, char *cmdline);
#endif

View File

@ -18,6 +18,7 @@
#include <sys/gdt.h>
#include <lib/fb.h>
#include <lib/term.h>
#include <flanterm/backends/fb.h>
#include <sys/pic.h>
#include <sys/lapic.h>
#include <sys/idt.h>
@ -32,36 +33,32 @@
#include <limine.h>
#define MAX_REQUESTS 128
#define MAX_MEMMAP 256
static pagemap_t build_pagemap(bool level5pg, bool nx, struct elf_range *ranges, size_t ranges_count,
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,
uint64_t direct_map_offset) {
pagemap_t pagemap = new_pagemap(level5pg ? 5 : 4);
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");
}
for (size_t i = 0; i < ranges_count; i++) {
uint64_t virt = ranges[i].base;
uint64_t phys;
if (virt & ((uint64_t)1 << 63)) {
phys = physical_base + (virt - virtual_base);
} else {
panic(false, "limine: Virtual address of a PHDR in lower half");
}
} else {
for (size_t i = 0; i < ranges_count; i++) {
uint64_t virt = ranges[i].base;
uint64_t phys;
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");
}
uint64_t pf =
(ranges[i].permissions & ELF_PF_X ? 0 : (nx ? VMM_FLAG_NOEXEC : 0)) |
(ranges[i].permissions & ELF_PF_W ? VMM_FLAG_WRITE : 0);
uint64_t pf =
(ranges[i].permissions & ELF_PF_X ? 0 : (nx ? VMM_FLAG_NOEXEC : 0)) |
(ranges[i].permissions & ELF_PF_W ? VMM_FLAG_WRITE : 0);
for (uint64_t j = 0; j < ranges[i].length; j += 0x1000) {
map_page(pagemap, virt + j, phys + j, pf, Size4KiB);
}
for (uint64_t j = 0; j < ranges[i].length; j += 0x1000) {
map_page(pagemap, virt + j, phys + j, pf, Size4KiB);
}
}
@ -107,11 +104,13 @@ static pagemap_t build_pagemap(bool level5pg, bool nx, struct elf_range *ranges,
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);
@ -124,16 +123,16 @@ static pagemap_t build_pagemap(bool level5pg, bool nx, struct elf_range *ranges,
}
}
// 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;
@ -144,7 +143,6 @@ static pagemap_t build_pagemap(bool level5pg, bool nx, struct elf_range *ranges,
map_page(pagemap, direct_map_offset + page, page, VMM_FLAG_WRITE | VMM_FLAG_FB, Size4KiB);
}
}
#endif
return pagemap;
}
@ -190,10 +188,29 @@ static uint64_t physical_base, virtual_base, slide, direct_map_offset;
static size_t requests_count;
static void **requests;
static void set_paging_mode(int paging_mode, bool kaslr) {
direct_map_offset = paging_mode_higher_half(paging_mode);
if (kaslr) {
uint64_t mask = ((uint64_t)1 << (paging_mode_va_bits(paging_mode) - 4)) - 1;
direct_map_offset += (rand64() & ~((uint64_t)0x40000000 - 1)) & mask;
}
}
static uint64_t reported_addr(void *addr) {
return (uint64_t)(uintptr_t)addr + direct_map_offset;
}
#define get_phys_addr(addr) ({ \
__auto_type get_phys_addr__addr = (addr); \
uintptr_t get_phys_addr__r; \
if (get_phys_addr__addr & ((uint64_t)1 << 63)) { \
get_phys_addr__r = physical_base + (get_phys_addr__addr - virtual_base); \
} else { \
get_phys_addr__r = get_phys_addr__addr; \
} \
get_phys_addr__r; \
})
static struct limine_file get_file(struct file_handle *file, char *cmdline) {
struct limine_file ret = {0};
@ -227,9 +244,12 @@ static struct limine_file get_file(struct file_handle *file, char *cmdline) {
}
}
ret.path = reported_addr(file->path);
char *path = ext_mem_alloc(file->path_len);
memcpy(path, file->path, file->path_len);
ret.address = reported_addr(freadall(file, MEMMAP_KERNEL_AND_MODULES));
ret.path = reported_addr(path);
ret.address = reported_addr(freadall_mode(file, MEMMAP_KERNEL_AND_MODULES, true));
ret.size = file->size;
ret.cmdline = reported_addr(cmdline);
@ -267,9 +287,18 @@ uint64_t limine_term_write_ptr = 0;
void limine_term_callback(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t);
#endif
static uint64_t term_arg;
static void (*actual_callback)(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t);
static void callback_shim(struct flanterm_context *ctx, uint64_t a, uint64_t b, uint64_t c, uint64_t d) {
(void)ctx;
actual_callback(term_arg, a, b, c, d);
}
// TODO pair with specific terminal
static void term_write_shim(uint64_t context, uint64_t buf, uint64_t count) {
(void)context;
term_write(buf, count);
_term_write(terms[0], buf, count);
}
noreturn void limine_load(char *config, char *cmdline) {
@ -281,11 +310,27 @@ noreturn void limine_load(char *config, char *cmdline) {
if (kernel_path == NULL)
panic(true, "limine: KERNEL_PATH not specified");
print("limine: Loading kernel `%s`...\n", kernel_path);
print("limine: Loading kernel `%#`...\n", kernel_path);
struct file_handle *kernel_file;
if ((kernel_file = uri_open(kernel_path)) == NULL)
panic(true, "limine: Failed to open kernel with path `%s`. Is the path correct?", kernel_path);
panic(true, "limine: Failed to open kernel with path `%#`. Is the path correct?", kernel_path);
char *k_path_copy = ext_mem_alloc(strlen(kernel_path) + 1);
strcpy(k_path_copy, kernel_path);
char *k_resource = NULL, *k_root = NULL, *k_path = NULL, *k_hash = NULL;
uri_resolve(k_path_copy, &k_resource, &k_root, &k_path, &k_hash);
char *k_path_ = ext_mem_alloc(strlen(k_path) + 2);
k_path_[0] = '/';
strcpy(k_path_ + 1, k_path);
k_path = k_path_;
for (size_t i = strlen(k_path) - 1; ; i--) {
if (k_path[i] == '/' || i == 1) {
k_path[i] = 0;
break;
}
k_path[i] = 0;
}
uint8_t *kernel = freadall(kernel_file, MEMMAP_BOOTLOADER_RECLAIMABLE);
@ -305,13 +350,14 @@ noreturn void limine_load(char *config, char *cmdline) {
struct elf_range *ranges;
uint64_t ranges_count;
uint64_t image_size;
uint64_t image_size_before_bss;
bool is_reloc;
if (!elf64_load(kernel, &entry_point, &slide,
MEMMAP_KERNEL_AND_MODULES, kaslr,
&ranges, &ranges_count,
&physical_base, &virtual_base, &image_size,
&physical_base, &virtual_base, NULL,
&image_size_before_bss,
&is_reloc)) {
panic(true, "limine: ELF64 load failure");
}
@ -332,7 +378,7 @@ noreturn void limine_load(char *config, char *cmdline) {
requests = ext_mem_alloc(MAX_REQUESTS * sizeof(void *));
requests_count = 0;
uint64_t common_magic[2] = { LIMINE_COMMON_MAGIC };
for (size_t i = 0; i < ALIGN_DOWN(image_size, 8); i += 8) {
for (size_t i = 0; i < ALIGN_DOWN(image_size_before_bss, 8); i += 8) {
uint64_t *p = (void *)(uintptr_t)physical_base + i;
if (p[0] != common_magic[0]) {
@ -368,41 +414,95 @@ noreturn void limine_load(char *config, char *cmdline) {
printv("limine: ELF entry point: %X\n", entry_point);
printv("limine: Requests count: %u\n", requests_count);
// 5 level paging feature & HHDM slide
bool want_5lv;
FEAT_START
// Check if 5-level paging is available
bool level5pg = false;
// TODO(qookie): aarch64 also has optional 5 level paging when using 4K pages
// Paging Mode
int paging_mode, max_paging_mode;
#if defined (__x86_64__) || defined (__i386__)
paging_mode = max_paging_mode = PAGING_MODE_X86_64_4LVL;
if (cpuid(0x00000007, 0, &eax, &ebx, &ecx, &edx) && (ecx & (1 << 16))) {
printv("limine: CPU has 5-level paging support\n");
level5pg = true;
max_paging_mode = PAGING_MODE_X86_64_5LVL;
}
#elif defined (__aarch64__)
paging_mode = max_paging_mode = PAGING_MODE_AARCH64_4LVL;
// TODO(qookie): aarch64 also has optional 5 level paging when using 4K pages
#else
#error Unknown architecture
#endif
struct limine_5_level_paging_request *lv5pg_request = get_request(LIMINE_5_LEVEL_PAGING_REQUEST);
want_5lv = lv5pg_request != NULL && level5pg;
#define paging_mode_limine_to_vmm(x) (x)
#define paging_mode_vmm_to_limine(x) (x)
direct_map_offset = want_5lv ? 0xff00000000000000 : 0xffff800000000000;
bool have_paging_mode_request = false;
bool paging_mode_set = false;
FEAT_START
struct limine_paging_mode_request *pm_request = get_request(LIMINE_PAGING_MODE_REQUEST);
if (pm_request == NULL)
break;
have_paging_mode_request = true;
if (kaslr) {
direct_map_offset += (rand64() & ~((uint64_t)0x40000000 - 1)) & 0xfffffffffff;
if (pm_request->mode > LIMINE_PAGING_MODE_MAX) {
print("warning: ignoring invalid mode in paging mode request\n");
break;
}
if (want_5lv) {
void *lv5pg_response = ext_mem_alloc(sizeof(struct limine_5_level_paging_response));
lv5pg_request->response = reported_addr(lv5pg_response);
}
paging_mode = paging_mode_limine_to_vmm(pm_request->mode);
if (paging_mode > max_paging_mode)
paging_mode = max_paging_mode;
set_paging_mode(paging_mode, kaslr);
paging_mode_set = true;
struct limine_paging_mode_response *pm_response =
ext_mem_alloc(sizeof(struct limine_paging_mode_response));
pm_response->mode = paging_mode_vmm_to_limine(paging_mode);
pm_request->response = reported_addr(pm_response);
FEAT_END
// 5 level paging feature & HHDM slide
FEAT_START
struct limine_5_level_paging_request *lv5pg_request = get_request(LIMINE_5_LEVEL_PAGING_REQUEST);
if (lv5pg_request == NULL)
break;
if (have_paging_mode_request) {
print("paging: ignoring 5-level paging request in favor of paging mode request\n");
break;
}
#if defined (__x86_64__) || defined (__i386__)
if (max_paging_mode < PAGING_MODE_X86_64_5LVL)
break;
paging_mode = PAGING_MODE_X86_64_5LVL;
#elif defined (__aarch64__)
if (max_paging_mode < PAGING_MODE_AARCH64_5LVL)
break;
paging_mode = PAGING_MODE_AARCH64_5LVL;
#else
#error Unknown architecture
#endif
set_paging_mode(paging_mode, kaslr);
paging_mode_set = true;
void *lv5pg_response = ext_mem_alloc(sizeof(struct limine_5_level_paging_response));
lv5pg_request->response = reported_addr(lv5pg_response);
FEAT_END
if (!paging_mode_set) {
set_paging_mode(paging_mode, kaslr);
}
#if defined (__aarch64__)
uint64_t aa64mmfr0;
asm volatile ("mrs %0, id_aa64mmfr0_el1" : "=r" (aa64mmfr0));
uint64_t pa = aa64mmfr0 & 0xF;
uint64_t tsz = 64 - (want_5lv ? 57 : 48);
uint64_t tsz = 64 - paging_mode_va_bits(paging_mode);
#endif
struct limine_file *kf = ext_mem_alloc(sizeof(struct limine_file));
@ -511,10 +611,13 @@ FEAT_START
smbios_response->entry_64 = reported_addr(smbios_entry_64);
}
smbios_request->response = reported_addr(smbios_response);
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)
// EFI system table feature
FEAT_START
@ -540,9 +643,6 @@ FEAT_START
}
#if defined (UEFI)
struct limine_dtb_response *dtb_response =
ext_mem_alloc(sizeof(struct limine_dtb_response));
// TODO: Looking for the DTB should be moved out of here and into lib/, because:
// 1. We will need it for core bring-up for the SMP request.
// 2. We will need to patch it for the Linux boot protocol to set the initramfs
@ -555,11 +655,15 @@ FEAT_START
for (size_t i = 0; i < gST->NumberOfTableEntries; i++) {
EFI_CONFIGURATION_TABLE *cur_table = &gST->ConfigurationTable[i];
if (memcmp(&cur_table->VendorGuid, &dtb_guid, sizeof(EFI_GUID)) == 0)
dtb_response->dtb_ptr = (uint64_t)(uintptr_t)cur_table->VendorTable;
if (memcmp(&cur_table->VendorGuid, &dtb_guid, sizeof(EFI_GUID)) == 0) {
struct limine_dtb_response *dtb_response =
ext_mem_alloc(sizeof(struct limine_dtb_response));
dtb_response->dtb_ptr = reported_addr((void *)cur_table->VendorTable);
dtb_request->response = reported_addr(dtb_response);
break;
}
}
dtb_request->response = reported_addr(dtb_response);
#endif
FEAT_END
@ -611,6 +715,10 @@ FEAT_START
break;
}
if (module_request->revision >= 1) {
module_count += module_request->internal_module_count;
}
if (module_count == 0) {
break;
}
@ -618,38 +726,80 @@ FEAT_START
struct limine_module_response *module_response =
ext_mem_alloc(sizeof(struct limine_module_response));
module_response->revision = 1;
struct limine_file *modules = ext_mem_alloc(module_count * sizeof(struct limine_file));
size_t final_module_count = 0;
for (size_t i = 0; i < module_count; i++) {
struct conf_tuple conf_tuple =
config_get_tuple(config, i,
"MODULE_PATH", "MODULE_CMDLINE");
char *module_path;
char *module_cmdline;
bool module_required = true;
bool module_path_allocated = false;
char *module_path = conf_tuple.value1;
char *module_cmdline = conf_tuple.value2;
if (module_request->revision >= 1 && i < module_request->internal_module_count) {
uint64_t *internal_modules = (void *)get_phys_addr(module_request->internal_modules);
struct limine_internal_module *internal_module = (void *)get_phys_addr(internal_modules[i]);
module_path = (char *)get_phys_addr(internal_module->path);
module_cmdline = (char *)get_phys_addr(internal_module->cmdline);
char *module_path_abs = ext_mem_alloc(1024);
char *module_path_abs_p = module_path_abs;
strcpy(module_path_abs_p, k_resource);
module_path_abs_p += strlen(k_resource);
strcpy(module_path_abs_p, "://");
module_path_abs_p += 3;
strcpy(module_path_abs_p, k_root);
module_path_abs_p += strlen(k_root);
get_absolute_path(module_path_abs_p, module_path, k_path);
module_path = module_path_abs;
module_path_allocated = true;
module_required = internal_module->flags & LIMINE_INTERNAL_MODULE_REQUIRED;
} else {
struct conf_tuple conf_tuple =
config_get_tuple(config, i - (module_request->revision >= 1 ? module_request->internal_module_count : 0),
"MODULE_PATH", "MODULE_CMDLINE");
module_path = conf_tuple.value1;
module_cmdline = conf_tuple.value2;
}
if (module_cmdline == NULL) {
module_cmdline = "";
}
print("limine: Loading module `%s`...\n", module_path);
print("limine: Loading module `%#`...\n", module_path);
struct file_handle *f;
if ((f = uri_open(module_path)) == NULL)
panic(true, "limine: Failed to open module with path `%s`. Is the path correct?", module_path);
if ((f = uri_open(module_path)) == NULL) {
if (module_required) {
panic(true, "limine: Failed to open module with path `%#`. Is the path correct?", module_path);
}
print("limine: Warning: Non-required internal module `%#` not found\n", module_path);
if (module_path_allocated) {
pmm_free(module_path, 1024);
}
continue;
}
if (module_path_allocated) {
pmm_free(module_path, 1024);
}
struct limine_file *l = &modules[i];
struct limine_file *l = &modules[final_module_count++];
*l = get_file(f, module_cmdline);
fclose(f);
}
uint64_t *modules_list = ext_mem_alloc(module_count * sizeof(uint64_t));
for (size_t i = 0; i < module_count; i++) {
uint64_t *modules_list = ext_mem_alloc(final_module_count * sizeof(uint64_t));
for (size_t i = 0; i < final_module_count; i++) {
modules_list[i] = reported_addr(&modules[i]);
}
module_response->module_count = module_count;
module_response->module_count = final_module_count;
module_response->modules = reported_addr(modules_list);
module_request->response = reported_addr(module_response);
@ -662,9 +812,11 @@ FEAT_END
parse_resolution(&req_width, &req_height, &req_bpp, resolution);
}
struct fb_info fb;
uint64_t *term_fb_ptr = NULL;
uint64_t term_fb_addr;
struct fb_info *fbs;
size_t fbs_count;
// Terminal feature
FEAT_START
@ -676,6 +828,8 @@ FEAT_START
struct limine_terminal_response *terminal_response =
ext_mem_alloc(sizeof(struct limine_terminal_response));
terminal_response->revision = 1;
struct limine_terminal *terminal = ext_mem_alloc(sizeof(struct limine_terminal));
quiet = false;
@ -683,23 +837,30 @@ FEAT_START
char *term_conf_override_s = config_get_value(config, 0, "TERM_CONFIG_OVERRIDE");
if (term_conf_override_s != NULL && strcmp(term_conf_override_s, "yes") == 0) {
term_vbe(config, req_width, req_height);
if (!gterm_init(&fbs, &fbs_count, config, req_width, req_height)) {
goto term_fail;
}
} else {
term_vbe(NULL, req_width, req_height);
if (!gterm_init(&fbs, &fbs_count, NULL, req_width, req_height)) {
goto term_fail;
}
}
if (current_video_mode < 0) {
panic(true, "limine: Failed to initialise terminal");
if (0) {
term_fail:
pmm_free(terminal, sizeof(struct limine_terminal));
pmm_free(terminal_response, sizeof(struct limine_terminal_response));
break; // next feature
}
fb = fbinfo;
if (terminal_request->callback != 0) {
terms[0]->callback = callback_shim;
#if defined (__i386__)
term_callback = limine_term_callback;
actual_callback = (void *)limine_term_callback;
limine_term_callback_ptr = terminal_request->callback;
#elif defined (__x86_64__) || defined (__aarch64__)
term_callback = (void *)terminal_request->callback;
actual_callback = (void *)terminal_request->callback;
#else
#error Unknown architecture
#endif
@ -721,9 +882,10 @@ FEAT_START
#endif
term_fb_ptr = &terminal->framebuffer;
term_fb_addr = reported_addr((void *)(((struct flanterm_fb_context *)terms[0])->framebuffer));
terminal->columns = term_cols;
terminal->rows = term_rows;
terminal->columns = terms[0]->cols;
terminal->rows = terms[0]->rows;
uint64_t *term_list = ext_mem_alloc(1 * sizeof(uint64_t));
term_list[0] = reported_addr(terminal);
@ -736,62 +898,83 @@ FEAT_START
goto skip_fb_init;
FEAT_END
term_deinit();
term_notready();
if (!fb_init(&fb, req_width, req_height, req_bpp)) {
panic(true, "limine: Could not acquire framebuffer");
fb_init(&fbs, &fbs_count, req_width, req_height, req_bpp);
if (fbs_count == 0) {
goto no_fb;
}
skip_fb_init:
memmap_alloc_range(fb.framebuffer_addr,
(uint64_t)fb.framebuffer_pitch * fb.framebuffer_height,
MEMMAP_FRAMEBUFFER, false, false, false, true);
for (size_t i = 0; i < fbs_count; i++) {
memmap_alloc_range(fbs[i].framebuffer_addr,
(uint64_t)fbs[i].framebuffer_pitch * fbs[i].framebuffer_height,
MEMMAP_FRAMEBUFFER, 0, false, false, true);
}
// Framebuffer feature
FEAT_START
// For now we only support 1 framebuffer
struct limine_framebuffer *fbp = ext_mem_alloc(sizeof(struct limine_framebuffer));
if (term_fb_ptr != NULL) {
*term_fb_ptr = reported_addr(fbp);
}
struct limine_framebuffer_request *framebuffer_request = get_request(LIMINE_FRAMEBUFFER_REQUEST);
if (framebuffer_request == NULL) {
if (framebuffer_request == NULL && term_fb_ptr == NULL) {
break; // next feature
}
struct limine_framebuffer *fbp = ext_mem_alloc(fbs_count * sizeof(struct limine_framebuffer));
struct limine_framebuffer_response *framebuffer_response =
ext_mem_alloc(sizeof(struct limine_framebuffer_response));
struct edid_info_struct *edid_info = get_edid_info();
if (edid_info != NULL) {
fbp->edid_size = sizeof(struct edid_info_struct);
fbp->edid = reported_addr(edid_info);
framebuffer_response->revision = 1;
uint64_t *fb_list = ext_mem_alloc(fbs_count * sizeof(uint64_t));
for (size_t i = 0; i < fbs_count; i++) {
uint64_t *modes_list = ext_mem_alloc(fbs[i].mode_count * sizeof(uint64_t));
for (size_t j = 0; j < fbs[i].mode_count; j++) {
fbs[i].mode_list[j].memory_model = LIMINE_FRAMEBUFFER_RGB;
modes_list[j] = reported_addr(&fbs[i].mode_list[j]);
}
fbp[i].modes = reported_addr(modes_list);
fbp[i].mode_count = fbs[i].mode_count;
if (fbs[i].edid != NULL) {
fbp[i].edid_size = sizeof(struct edid_info_struct);
fbp[i].edid = reported_addr(fbs[i].edid);
}
fbp[i].memory_model = LIMINE_FRAMEBUFFER_RGB;
fbp[i].address = reported_addr((void *)(uintptr_t)fbs[i].framebuffer_addr);
fbp[i].width = fbs[i].framebuffer_width;
fbp[i].height = fbs[i].framebuffer_height;
fbp[i].bpp = fbs[i].framebuffer_bpp;
fbp[i].pitch = fbs[i].framebuffer_pitch;
fbp[i].red_mask_size = fbs[i].red_mask_size;
fbp[i].red_mask_shift = fbs[i].red_mask_shift;
fbp[i].green_mask_size = fbs[i].green_mask_size;
fbp[i].green_mask_shift = fbs[i].green_mask_shift;
fbp[i].blue_mask_size = fbs[i].blue_mask_size;
fbp[i].blue_mask_shift = fbs[i].blue_mask_shift;
fb_list[i] = reported_addr(&fbp[i]);
}
fbp->memory_model = LIMINE_FRAMEBUFFER_RGB;
fbp->address = reported_addr((void *)(uintptr_t)fb.framebuffer_addr);
fbp->width = fb.framebuffer_width;
fbp->height = fb.framebuffer_height;
fbp->bpp = fb.framebuffer_bpp;
fbp->pitch = fb.framebuffer_pitch;
fbp->red_mask_size = fb.red_mask_size;
fbp->red_mask_shift = fb.red_mask_shift;
fbp->green_mask_size = fb.green_mask_size;
fbp->green_mask_shift = fb.green_mask_shift;
fbp->blue_mask_size = fb.blue_mask_size;
fbp->blue_mask_shift = fb.blue_mask_shift;
uint64_t *fb_list = ext_mem_alloc(1 * sizeof(uint64_t));
fb_list[0] = reported_addr(fbp);
framebuffer_response->framebuffer_count = 1;
framebuffer_response->framebuffer_count = fbs_count;
framebuffer_response->framebuffers = reported_addr(fb_list);
framebuffer_request->response = reported_addr(framebuffer_response);
if (framebuffer_request != NULL) {
framebuffer_request->response = reported_addr(framebuffer_response);
}
if (term_fb_ptr != NULL) {
for (size_t i = 0; i < fbs_count; i++) {
if (fbp[i].address == term_fb_addr) {
*term_fb_ptr = reported_addr(&fbp[i]);
break;
}
}
}
FEAT_END
no_fb:
// Boot time feature
FEAT_START
struct limine_boot_time_request *boot_time_request = get_request(LIMINE_BOOT_TIME_REQUEST);
@ -820,18 +1003,21 @@ FEAT_END
#endif
#if defined (__aarch64__)
uint64_t fb_attr = 0x00;
if (fb.framebuffer_addr) {
// Find the most restrictive caching mode from all framebuffers to use
uint64_t fb_attr = (uint64_t)-1;
for (size_t i = 0; i < fbs_count; i++) {
int el = current_el();
uint64_t res;
// Figure out the caching mode used for this particular framebuffer
if (el == 1) {
asm volatile (
"at s1e1w, %1\n\t"
"isb\n\t"
"mrs %0, par_el1"
: "=r"(res)
: "r"(fb.framebuffer_addr)
: "r"(fbs[i].framebuffer_addr)
: "memory");
} else if (el == 2) {
asm volatile (
@ -839,7 +1025,7 @@ FEAT_END
"isb\n\t"
"mrs %0, par_el1"
: "=r"(res)
: "r"(fb.framebuffer_addr)
: "r"(fbs[i].framebuffer_addr)
: "memory");
} else {
panic(false, "Unexpected EL in limine_load");
@ -848,8 +1034,26 @@ FEAT_END
if (res & 1)
panic(false, "Address translation for framebuffer failed");
fb_attr = res >> 56;
uint64_t new_attr = res >> 56;
// Use whatever we find first
if (fb_attr == (uint64_t)-1)
fb_attr = new_attr;
// Prefer Device memory over Normal memory
else if ((fb_attr & 0b11110000) && !(new_attr & 0b11110000))
fb_attr = new_attr;
// Prefer tighter Device memory (lower values)
else if (!(fb_attr & 0b11110000) && !(new_attr & 0b11110000) && fb_attr > new_attr)
fb_attr = new_attr;
// Use Normal non-cacheable otherwise (avoid trying to figure out how to downgrade inner vs outer).
else if ((fb_attr & 0b11110000) && (new_attr & 0b11110000))
fb_attr = 0b01000100; // Inner&outer Non-cacheable
// Otherwise do nothing (fb_attr is already more restrictive than new_attr).
}
// If no framebuffers are found, just zero out the MAIR entry
if (fb_attr == (uint64_t)-1)
fb_attr = 0;
#endif
void *stack = ext_mem_alloc(stack_size) + stack_size;
@ -863,7 +1067,7 @@ FEAT_END
#endif
pagemap_t pagemap = {0};
pagemap = build_pagemap(want_5lv, nx_available, ranges, ranges_count,
pagemap = build_pagemap(paging_mode, nx_available, ranges, ranges_count,
physical_base, virtual_base, direct_map_offset);
#if defined (UEFI)
@ -877,21 +1081,18 @@ FEAT_START
break; // next feature
}
struct limine_smp_info *smp_array;
struct smp_information *smp_info;
struct limine_smp_info *smp_info;
size_t cpu_count;
#if defined (__x86_64__) || defined (__i386__)
uint32_t bsp_lapic_id;
smp_info = init_smp(0, (void **)&smp_array,
&cpu_count, &bsp_lapic_id,
true, want_5lv,
smp_info = init_smp(&cpu_count, &bsp_lapic_id,
paging_mode,
pagemap, smp_request->flags & LIMINE_SMP_X2APIC, nx_available,
direct_map_offset, true);
#elif defined (__aarch64__)
uint64_t bsp_mpidr;
smp_info = init_smp(0, (void **)&smp_array,
&cpu_count, &bsp_mpidr,
smp_info = init_smp(&cpu_count, &bsp_mpidr,
pagemap, LIMINE_MAIR(fb_attr), LIMINE_TCR(tsz, pa), LIMINE_SCTLR);
#else
#error Unknown architecture
@ -903,7 +1104,7 @@ FEAT_START
for (size_t i = 0; i < cpu_count; i++) {
void *cpu_stack = ext_mem_alloc(stack_size) + stack_size;
smp_info[i].stack_addr = reported_addr(cpu_stack + stack_size);
smp_info[i].reserved = reported_addr(cpu_stack);
}
struct limine_smp_response *smp_response =
@ -920,7 +1121,7 @@ FEAT_START
uint64_t *smp_list = ext_mem_alloc(cpu_count * sizeof(uint64_t));
for (size_t i = 0; i < cpu_count; i++) {
smp_list[i] = reported_addr(&smp_array[i]);
smp_list[i] = reported_addr(&smp_info[i]);
}
smp_response->cpu_count = cpu_count;
@ -938,8 +1139,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;
@ -949,7 +1150,7 @@ FEAT_START
break; // next feature
}
if (mmap_entries > MAX_MEMMAP) {
if (mmap_entries > MEMMAP_MAX) {
panic(false, "limine: Too many memmap entries");
}
@ -997,9 +1198,7 @@ FEAT_START
FEAT_END
// Clear terminal for kernels that will use the Limine terminal
term_write((uint64_t)(uintptr_t)("\e[2J\e[H"), 7);
term_runtime = true;
FOR_TERM(flanterm_write(TERM, "\e[2J\e[H", 7));
#if defined (__x86_64__) || defined (__i386__)
#if defined (BIOS)
@ -1012,6 +1211,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();
@ -1020,14 +1229,16 @@ FEAT_END
uint64_t reported_stack = reported_addr(stack);
common_spinup(limine_spinup_32, 8,
want_5lv, (uint32_t)(uintptr_t)pagemap.top_level,
paging_mode, (uint32_t)(uintptr_t)pagemap.top_level,
(uint32_t)entry_point, (uint32_t)(entry_point >> 32),
(uint32_t)reported_stack, (uint32_t)(reported_stack >> 32),
(uint32_t)(uintptr_t)local_gdt, nx_available);
#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);
#else

Some files were not shown because too many files have changed in this diff Show More