Compare commits

...

430 Commits

Author SHA1 Message Date
iProgramInCpp
e63d804f6f limine: Fix two other small typos in PROTOCOL.md 2023-10-29 04:37:09 +01:00
mintsuki
cad3c72fce config: Fix bug where macro definitions were not skipped over properly when parsing 2023-10-29 04:27:04 +01:00
ミンツキ
7cd46f3d26
Merge pull request #314 from iProgramMC/fix-typo-in-protocol-1
limine: Fix a small typo error in PROTOCOL.md
2023-10-28 20:03:13 +02:00
iProgramInCpp
f4051f49db
limine: Fix a small typo error in PROTOCOL.md
This corrects an error which mistakenly says "the an Entry Point request (...)", in the section where the machine state at entry into the kernel is described.
2023-10-28 17:48:30 +03:00
mintsuki
a5051f92bf build: Changes to comply more with the GNU build system - adds ChangeLog 2023-10-28 05:16:45 +02:00
mintsuki
ec564407da docs: Update example Limine version in README to 5.20231024.0 2023-10-24 18:50:28 +02:00
mintsuki
a0127f9f40 pmm: Add MEMMAP_MAX macro and use it instead of hardcoding 256 2023-10-24 18:38:18 +02:00
mintsuki
e49865a467 lib/time: EFI: Return time of 0 if GetTime() unsupported 2023-10-24 18:38:18 +02:00
48cf
2bba72634f lib/gterm: Try to initialize all 32-bpp framebuffers 2023-10-24 18:38:18 +02:00
48cf
45b39285f1 pmm: Ignore allow_high_allocs on non x86-64 architectures 2023-10-24 18:38:18 +02:00
mintsuki
a795dc1972 build: Backport misc autoconf/pkgconf improvements 2023-10-24 01:21:24 +02:00
mintsuki
c1860c8d80 limine/ioapic: Change spec to avoid masking IOAPIC RTEs unless Fixed or Lowest Priority 2023-10-24 01:21:24 +02:00
mintsuki
49cfba851c build: Misc minor QOL configure.ac/GNUmakefile.in improvements 2023-10-24 01:21:24 +02:00
mintsuki
b348bb75e7 docs: Update example Limine version in README to 5.20231006.0 2023-10-06 12:25:44 -05:00
mintsuki
c1f5b21177 misc: Remove unnecessary ifdefs added in previous commits 2023-10-06 12:25:44 -05:00
mintsuki
b474b6bad0 misc: Only allocate memory and modules above 4GiB on 64-bit platforms 2023-10-06 12:25:44 -05:00
mintsuki
5323bce117 pmm: Allow allocations above 4GiB and use them in freadall() 2023-10-06 12:25:44 -05:00
mintsuki
1bcbf817ed docs: Update example Limine version in README to 5.20230928.2 2023-09-28 17:49:31 -05:00
mintsuki
f81b9d2dc3 build: Fix makefile target dependencies bug introduced in a0c2f95 2023-09-28 17:49:31 -05:00
mintsuki
d0a1285feb docs: Update example Limine version in README to 5.20230928.1 2023-09-28 16:26:32 -05:00
mintsuki
a0c2f95a1d build: Fix bug introduced in 7885f260 due to a misunderstanding of an objcopy flag 2023-09-28 16:03:13 -05:00
mintsuki
d421ebcb58 docs: Update example Limine version in README to 5.20230928.0 2023-09-28 06:56:28 -05:00
mintsuki
7117b85c86 build: Fix indentation issue in common/GNUmakefile 2023-09-28 06:56:28 -05:00
mintsuki
3a81c3e13d build: ldscripts: .reloc -> .dummy_reloc 2023-09-28 06:56:28 -05:00
mintsuki
a0997a598b build: Fix race conditions introduced in 22d45a5428 2023-09-28 06:56:28 -05:00
mintsuki
212dbd32c1 misc: Add .note.GNU-stack where it was still missing 2023-09-28 06:56:28 -05:00
mintsuki
a55f68b3bd smp: riscv64: Replace .insn directive with .4byte 2023-09-28 06:56:28 -05:00
mintsuki
a83dafe6f4 misc: Add section .note.GNU-stack to assembly files 2023-09-28 06:56:28 -05:00
mintsuki
afdc556301 time: Change signature of get_jdn() to use int types 2023-09-28 06:56:28 -05:00
mintsuki
bfc518cc07 docs: Update example Limine version in README to 5.20230924.0 2023-09-24 02:03:59 -05:00
mintsuki
81c39fc080 elf: Panic if there are PHDRs with different perms sharing same page 2023-09-24 01:56:50 -05:00
mintsuki
87a88bf565 smp: Remove dead 32-bit trampoline code 2023-09-23 17:37:38 -05:00
mintsuki
3fde8f0158 docs: PROTOCOL.md: Fix up layout of mappings table 2023-09-22 16:54:15 -05:00
mintsuki
50f4383f93 limine: Make explicit some implied padding in some structures 2023-09-22 16:40:07 -05:00
mintsuki
c7df84e237 test: riscv64: Fix issue with OVMF not working on latest QEMU 2023-09-22 16:39:59 -05:00
mintsuki
f1236373fe menu: Fix padding issue introduced in e1d25f8 2023-09-22 16:39:51 -05:00
mintsuki
a36de776a7 docs: Update example Limine version in README to 5.20230917.0 2023-09-16 17:14:13 -05:00
mintsuki
a0fb5a04d3 docs: PROTOCOL.md: Backport caching section from trunk 2023-09-16 16:31:16 -05:00
mintsuki
042a6e9554 misc: Backports from trunk 2023-09-16 15:12:14 -05:00
mintsuki
c5c43cb0fd misc: aarch64: Remove unused enter_in_current_el() function 2023-09-16 14:28:33 -05:00
mintsuki
5f7bcc0b1d riscv: Fix cherry-picking issue introduced in e3d65aa628 2023-09-16 11:35:43 -05:00
mintsuki
45958f7162 misc: Consistently call x86-64 such, instead of x86_64 2023-09-16 11:31:35 -05:00
mintsuki
e9b5511084 docs: PROTOCOL.md: Minor fixes 2023-09-16 11:31:19 -05:00
xvanc
f4bfe1289a riscv: skip rv{32,64} prefix when parsing extensions from isa strings 2023-09-16 11:28:15 -05:00
xvanc
cdac49ebfb acpi: remove duplicate definition in sys/lapic.c 2023-09-16 11:28:15 -05:00
xvanc
90b82dc43f riscv/vmm: use Svpbmt extension when available 2023-09-16 11:28:15 -05:00
xvanc
e3d65aa628 riscv: refactor smp init 2023-09-16 11:28:15 -05:00
xvanc
f33732a2e5 riscv: implement feature dectection 2023-09-16 11:21:17 -05:00
xvanc
09c430f286 lib/libc: add misc utilities 2023-09-16 11:21:17 -05:00
xvanc
2200161e7d acpi: move acpi structure defs to lib/acpi.h 2023-09-16 11:21:17 -05:00
mintsuki
f8bfe41e71 test: Use -dumpmachine to find architecture instead of expecting -target 2023-09-11 17:16:19 -05:00
mintsuki
0f7ee05635 misc/bios: Update and improve linker script and related files 2023-09-11 17:16:19 -05:00
mintsuki
b54c3fc9cc protos/chainload: Fix bug that could result in bogus oom errors. Fixes #302 2023-09-11 17:16:19 -05:00
mintsuki
756dd235ea decompressor: Mark .entry section with proper flags in entry.asm 2023-09-11 17:16:19 -05:00
mintsuki
09c87feaee decompressor: Add rodata PHDR and section to ld script 2023-09-11 17:16:19 -05:00
Kacper Słomiński
916aa370b2 protos: chainload: Allocate memory for the null terminator in cmdline 2023-09-11 17:16:19 -05:00
mintsuki
0ebf0245df misc: Misc EFI linker script improvements and drop .sbat 2023-09-11 17:16:19 -05:00
mintsuki
8f789fc0ae docs: Update example Limine version in README to 5.20230909.0 2023-09-09 16:08:08 -05:00
mintsuki
b5cffbb6e8 misc: Improve UEFI linker scripts 2023-09-09 15:57:38 -05:00
mintsuki
9ff62c2a62 docs: README.md: Fix minor grammar mistake 2023-09-09 10:08:44 -05:00
mintsuki
68f82c3d30 stage1/gdt: Mark accessed flag in descriptors 2023-09-09 10:08:44 -05:00
mintsuki
2642249edd docs: Remove references to shim as we don't directly support it 2023-09-09 10:08:44 -05:00
mintsuki
e6a67c80a6 x86/gdt: Mark accessed flag in descriptors 2023-09-09 10:08:44 -05:00
mintsuki
541dbd265c docs: Update example Limine version in README to 5.20230830.0 2023-08-29 22:34:47 -05:00
mintsuki
e207c03f69 build: Drop -mabi=sysv for x86 for clang 16 2023-08-29 22:34:27 -05:00
mintsuki
57e4ae6e25 config: Disable editor by default if config b2sum present. Fixes #296 2023-08-29 22:34:20 -05:00
mintsuki
a30cad3556 menu: Change menu arrow to use unicode big arrow 2023-08-29 22:34:15 -05:00
mintsuki
ac0d9465f5 gterm: Update font's big left and right arrows 2023-08-29 22:34:11 -05:00
mintsuki
f0b899b5bc docs: Update example Limine version in README to 5.20230819.0 2023-08-19 08:43:54 -05:00
mintsuki
4abedffb43 disk: BIOS: Skip drive if sector size is 0. Fixes #294 2023-08-19 08:20:45 -05:00
Kacper Słomiński
50dab6c2f1 smp: aarch64: Don't needlessly invalidate the data cache
Also get rid of the function to do clean + invalidate as not to be
tempted by it.
2023-08-18 13:38:14 -05:00
Kacper Słomiński
ba5d63b82a elf: aarch64: Don't needlessly invalidate the data cache
Cleaning the data cache to PoC without invalidating it is enough when
invalidating the instruction cache to PoU.
2023-08-18 13:37:55 -05:00
mintsuki
573d0095bf elf: elf64_load_section(): Return false early if sh_num == 0 2023-08-18 13:37:39 -05:00
mintsuki
27a32e416c disk: Add additional volume_index_i overflow guards 2023-08-18 13:37:16 -05:00
mintsuki
9a074530a9 exceptions: Change naming of exceptions in panic message 2023-08-18 13:36:58 -05:00
mintsuki
a248b557bb docs: Update example Limine version in README to 5.20230811.0 2023-08-11 10:31:14 -05:00
mintsuki
d66df6b38a limine: Do not return SMBIOS response if not present 2023-08-10 19:26:54 -05:00
mintsuki
1e9a42e7ce test: General makefile updates 2023-08-08 14:09:31 -05:00
mintsuki
b8fff872de test: Use Flanterm 2023-08-08 14:09:19 -05:00
mekb
820d4751d3 menu: Add option to hide help text 2023-08-08 14:09:11 -05:00
xvanc
82ea6d6a57 test/riscv: disable linker relaxation, specify ISA string and ABI
Although linker relaxation is disabled, the compiler still emits small
data sections which must be explicitly included in the linker script.
2023-08-04 07:22:12 -05:00
xvanc
030242d69a vmm/riscv: fix bug in vmm_max_paging_mode() 2023-08-03 20:12:51 -05:00
mintsuki
b64335f62a docs: Update example Limine version in README to 5.20230801.0 2023-08-01 05:32:12 -05:00
mintsuki
50b8ab2c26 rv64: Misc relaxation related fixes 2023-08-01 05:32:05 -05:00
mintsuki
2d0752f60c docs: Update example Limine version in README to 5.20230729.0 2023-07-29 12:00:19 -05:00
mintsuki
ff86be6be6 misc: Update test wallpaper and screenshot 2023-07-29 11:55:37 -05:00
mintsuki
2f1dac0600 gterm: Change resolutions at which autoscaling is triggered 2023-07-29 11:55:37 -05:00
mintsuki
0ecb2ab895 menu: Center menu vertically 2023-07-29 11:55:37 -05:00
mintsuki
474fc105a5 gop: Readd preset mode storage 2023-07-29 11:55:37 -05:00
mintsuki
418f8d7280 menu: Do not draw box around boot menu 2023-07-29 02:17:12 -05:00
mintsuki
722bde2cbc menu: Adjust centering by 2 characters to the left 2023-07-28 04:26:48 -05:00
mintsuki
5bdb1bbf55 menu: Fix a couple of boot menu alignment issues 2023-07-28 04:26:48 -05:00
mintsuki
8f167bc2e5 menu: Initialise max_len if null regardless of shift 2023-07-28 04:26:48 -05:00
mintsuki
d73cd37834 menu: Fix maybe uninitialised issue with cur_len var 2023-07-28 04:26:48 -05:00
mintsuki
478b6f3806 menu: Fix NULL deref bug with shift variable 2023-07-28 04:26:48 -05:00
mintsuki
4b452e69a4 console: Add slide command 2023-07-28 04:26:48 -05:00
mintsuki
98f30bfdd6 menu: Center boot menu 2023-07-28 04:26:48 -05:00
mintsuki
ba2597605b Revert "build: Make limine-uefi-cd.bin 16MiB in size (use FAT16)"
This reverts commit 2da0a08072.
2023-07-28 04:26:48 -05:00
mintsuki
9921af54d0 gterm: Autoscale font on higher resolutions 2023-07-28 04:26:48 -05:00
Kacper Słomiński
a2e502328d limine: Adjust higher half offsets for AArch64 2023-07-26 17:05:43 -05:00
Kacper Słomiński
dc68fcaff7 limine: Use a higher-half pointer for the stack on AArch64 2023-07-26 17:05:33 -05:00
mintsuki
f365a46617 misc: Minor updates to linker scripts 2023-07-26 17:05:20 -05:00
mintsuki
871a8053c2 build: Get rid of OBJCOPY2ELF_FLAGS since only IA-32/BIOS used it 2023-07-26 17:05:06 -05:00
mintsuki
49ecb6b577 build: Get rid of RISCV_CFLAGS variable as it is now unnecessary 2023-07-26 17:04:54 -05:00
mintsuki
997e2c756a ci: Remove openssh dependency no longer required for release 2023-07-26 17:04:46 -05:00
mintsuki
bc1896c5bb riscv64: Do not use global pointer register 2023-07-26 17:04:30 -05:00
mintsuki
e261a96fa4 docs/protocol: Fix typo and mandate ra and gp registers to be 0 for rv64 2023-07-26 17:04:21 -05:00
mintsuki
1f82dd89c7 host/limine: Fix typo 2023-07-26 17:03:52 -05:00
mintsuki
93942a3334 docs: Update example Limine version in README to 5.20230709.0 2023-07-09 03:55:27 +02:00
mintsuki
b72d033510 elf: elf64_load(): Remove accidentally left in debug code 2023-07-09 03:40:06 +02:00
mintsuki
11f50a6aaa part: Require keypresses between entry displays in list_volumes() 2023-07-09 03:37:55 +02:00
mintsuki
79e50a82af misc: Use assembly for memory functions on x86 2023-07-09 03:09:45 +02:00
mintsuki
17e26c8c95 elf: Fix potential uninitialised usage of bss_size 2023-07-09 03:09:45 +02:00
mintsuki
9333f1ca8b limine/elf: Optimise not to scan .bss for requests 2023-07-08 23:44:50 +02:00
mintsuki
99d671ecf8 build: Drop -Wno-deprecated-declarations flag 2023-06-20 16:24:27 +02:00
mintsuki
7882d89b4e limine: Drop 5-level paging request support 2023-06-20 16:10:08 +02:00
mintsuki
1ad6d6013e limine: Drop terminal request support 2023-06-20 15:58:52 +02:00
mintsuki
2ac43a320f asm: Add missing section directives 2023-06-20 13:24:49 +02:00
mintsuki
2d6a1e4535 console: Add firmware type command 2023-06-20 11:10:33 +02:00
mintsuki
d08ea721a5 limine.c: Add copyright and license information to version command 2023-06-20 10:19:01 +02:00
mintsuki
6e41938206 gensyms: Filter out non-function symbols 2023-06-20 08:54:53 +02:00
mintsuki
67fd1a8d9f docs: Update example Limine version in README to 4.20230615.0 2023-06-15 13:20:43 +02:00
mintsuki
66268f7d7f pmm: Use fixed value of 1024 for recl entries count 2023-06-15 13:06:52 +02:00
mintsuki
cb14f44eb3 pmm: Fix change-memmap-in-use bug 2023-06-15 12:54:36 +02:00
mintsuki
910a0d84a0 vmm: Fix page_sizes values and move declaration to top 2023-06-15 08:21:48 +02:00
mintsuki
2da0a08072 build: Make limine-uefi-cd.bin 16MiB in size (use FAT16) 2023-06-15 03:14:04 +02:00
mintsuki
670b635ae8 config: Add and document ARCH built-in macro 2023-06-15 02:23:48 +02:00
mintsuki
bc8188e275 misc: limine.sys -> limine-bios.sys 2023-06-15 02:02:32 +02:00
mintsuki
38ccb76c40 misc: limine-hdd.bin -> limine-bios-hdd.bin 2023-06-15 01:47:16 +02:00
mintsuki
7b1284808a build: Fix permissions of output files in makefile instead of release recipe 2023-06-15 01:33:17 +02:00
mintsuki
34a2e85c34 misc: Add missing EFI executables install commands to host Makefile 2023-06-15 01:12:56 +02:00
mintsuki
ece02695e8 misc: limine-cd.bin -> limine-bios-cd.bin 2023-06-15 01:07:44 +02:00
mintsuki
45fd1ac08f test: Misc updates to the linker script 2023-06-15 00:52:59 +02:00
mintsuki
264decd0ef misc: limine-cd-efi.bin -> limine-uefi-cd.bin 2023-06-14 03:14:41 +02:00
mintsuki
d0b9bbdca6 misc: limine-pxe.bin -> limine-bios-pxe.bin 2023-06-14 03:04:01 +02:00
mintsuki
1c5fde5dc9 misc: Add BOOTRISCV64.EFI to permissions fix list 2023-06-14 00:25:42 +02:00
mintsuki
a069e220c0 docs: BOOT{IA32,X64,AA64}.EFI -> BOOT*.EFI 2023-06-14 00:14:20 +02:00
mintsuki
b764792c97 docs: Mention creating the ESP tree in ISOHYBRID partition 2023-06-13 12:35:15 +02:00
mintsuki
a9e6e00994 docs: Add donations link 2023-06-12 17:46:39 +02:00
mintsuki
2b154138fe misc: Updates for new limine-efi 2023-06-12 05:57:47 +02:00
mintsuki
cde874fe80 misc: Updates for new flanterm 2023-06-10 19:23:50 +02:00
mintsuki
a627c732d5 docs: Update example Limine version in README to 4.20230606.0 2023-06-06 02:02:23 +02:00
mintsuki
b78309b45a misc: Remove tinf from tree, pull at bootstrap time 2023-06-06 01:16:58 +02:00
mintsuki
666c5dfcd1 riscv64: Update location of __global_pointer$ 2023-06-06 00:17:07 +02:00
mintsuki
13042bd25e build/riscv64: libgcc-riscv64 -> libgcc-riscv64-softfloat 2023-06-06 00:02:07 +02:00
mintsuki
f6946a7f0c test: Use retrage.github.io EDK2 nightly builds for all ports 2023-06-05 23:14:44 +02:00
mintsuki
74a6b8e125 protos/linux: Do not zero EFI memmap size on IA-32 EFI 2023-06-05 23:05:20 +02:00
mintsuki
705719a229 docs/readme: Adjust stb_image.h link to point to dev branch 2023-06-05 00:07:03 +02:00
mintsuki
e205d51ca4 docs: Add Limine pronounciation link to README.md 2023-06-04 23:39:14 +02:00
ミンツキ
fa7b2409e7
Merge pull request #276 from xvanc/trunk
limine: scale the maximum KASLR offset based on the address space size
2023-06-04 21:05:48 +02:00
xvanc
1f01ddfc6d
limine: scale the maximum KASLR offset based on the address space size 2023-06-04 13:50:26 -05:00
xvanc
9274ee656e
Initial riscv64 port (#274)
* initial riscv64 port

* enable Paging Mode feature for all architectures

* riscv: add missing protocol docs

* riscv: fix tests

* docs: clarify `LIMINE_PAGING_MODE_DEFAULT` macro

* build: fix whitespace in common/GNUmakefile

* riscv: default to Sv48 paging when supported

* vmm: make `VMM_MAX_LEVEL` 1-indexed

* limine: do not call `reported_addr()` before finaling paging mode

smp/riscv: do not overwrite the argument passed to APs

* limine/riscv: update default paging mode in limine.h

* test/riscv: pad OVMF.fd when downloading it
2023-06-04 01:36:06 +02:00
mintsuki
e91196d452 test: Fix copying mistake (typo) 2023-06-03 01:51:17 +02:00
ミンツキ
bee1d50c1a
Merge pull request #275 from blanham/netboot_fix_when_no_block_io
Fix netboot in configs where BLOCK_IO_PROTOCOL does not exist
2023-06-01 10:40:36 +02:00
Bryce Lanham
fe083d3701 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-01 03:33:13 -05:00
mintsuki
dce1c31ad5 docs: Update example Limine version in README to 4.20230530.0 2023-05-30 22:44:12 +02:00
mintsuki
f26b651e5f disk/efi: Do not use DISK_IO protocol and fix buffer reuse bug 2023-05-30 21:36:09 +02:00
mintsuki
679fdd4351 misc: Use C instead of asm for mem*() family of functions 2023-05-30 12:23:31 +02:00
mintsuki
4190710dc6 docs: Update example Limine version in README to 4.20230529.0 2023-05-29 13:06:02 +02:00
mintsuki
9079f3007d ci: Fix permissions of certain files in binary branch 2023-05-29 12:51:21 +02:00
mintsuki
eac03c8c89 build/uefi: Remove now-useless -DGNU_EFI_USE_MS_ABI flag 2023-05-28 23:53:34 +02:00
mintsuki
0125dcd67a build/uefi: Pass -fshort-wchar to CC 2023-05-27 16:55:49 +02:00
mintsuki
844386487d docs: Update example Limine version in README 2023-05-14 09:28:24 +02:00
mintsuki
71b175b7b9 stb_image: Track dev branch 2023-05-14 06:08:55 +02:00
mintsuki
153412f53e host: Perform compile-time endian check if supported 2023-05-14 05:13:09 +02:00
mintsuki
7989064599 elf: Improve detection of relocatable ELFs 2023-05-13 00:05:50 +02:00
mintsuki
836d1c2038 docs: Update example Limine version in README 2023-05-03 22:51:13 +02:00
mintsuki
2c11fb337c stb_image: Update to commit with zlib EOF bug fixed 2023-05-03 19:53:27 +02:00
mintsuki
73462a5116 Revert "compress/gz: Add hack to allow macOS compressed GZs to load with stbi"
This reverts commit 1dd75a18ac.
2023-05-03 19:53:27 +02:00
mintsuki
f618eb26af Revert "misc: Revert back to using tinf for all GZ decompression"
This reverts commit 3438b8d235.
2023-05-03 19:53:27 +02:00
mintsuki
e9186e1859 Revert "uri: Backport pre-tinf-removal variable assignments"
This reverts commit 514522125b.
2023-05-03 19:53:27 +02:00
mintsuki
35808c593e build: Remove some empty lines in dist make target 2023-05-03 15:54:14 +02:00
ミンツキ
717c60cd6a
Merge pull request #271 from blanham/multiboot1_fix_elf32_section_loading
multiboot1: also fix elf32 section loading
2023-05-03 03:54:46 +02:00
Bryce Lanham
e0c3e6bdce 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-02 20:48:13 -05:00
ミンツキ
df34599feb
Merge pull request #270 from blanham/multiboot2_fix_elf32_section_loading
multiboot2: fix 32 bit elf section loading
2023-05-03 03:39:12 +02:00
Bryce Lanham
fdcb9a9243 multiboot2: fix 32 bit elf section loading
Existing code was using 64 bit elf section header unconditionally. This
commit fixes that :)
2023-05-02 20:15:43 -05:00
mintsuki
1a4888858b hgen: Add extra sed command for handling Solaris's od 2023-05-02 08:49:46 +02:00
mintsuki
8dd7973e23 pxe: Add and use constant PXE ACK packet size and fix BIOS PXE ACK struct 2023-04-28 04:59:08 +02:00
mintsuki
36846549e0 menu: Do not initialise textmode terminal if QUIET=yes. Addresses #269 2023-04-26 23:49:22 +02:00
mintsuki
172060e249 bootstrap: Add BOOTSTRAP_NO_SHALLOW_CLONES support 2023-04-25 02:42:34 +02:00
ミンツキ
d7da6d63b5
Merge pull request #267 from blanham/add_multiboot2_network_tag
Implement Multiboot2 network tag
2023-04-24 16:39:30 +02:00
Bryce Lanham
2362f1a785 Implement Multiboot2 network tag
Added caching of the dhcp response in the pxe code, and then adding the
tag containing it.
2023-04-24 06:44:56 -05:00
ミンツキ
2a26d90394
Merge pull request #265 from blanham/fix_pxe_proxy_boot
Fix PXE BIOS boot when using a proxy DHCP server
2023-04-22 10:37:23 +02:00
Bryce Lanham
64a0c6073b Fix PXE BIOS boot when using a proxy DHCP server 2023-04-22 01:22:36 -05:00
mintsuki
73b126e067 build: Sanitise autoconf substitutions with gmake variables 2023-04-21 18:57:08 +02:00
mintsuki
c41e3969a6 build: Pass proper warning flags to nasm 2023-04-18 12:41:01 +02:00
mintsuki
b991fb93f8 docs: Document TEXTMODE config for multiboot 1 and 2 2023-04-13 21:02:09 +02:00
mintsuki
e57050d9c7 multiboot1: Support TEXTMODE config as with Linux/mb2 protocols 2023-04-13 19:21:49 +02:00
mintsuki
93ae0e9afc textmode: Actually disable term hooking on non-managed initialisation 2023-04-13 18:49:26 +02:00
ミンツキ
3613997108
Merge pull request #263 from klange/mb2-textmode
multiboot2: Support TEXTMODE config as with linux
2023-04-12 16:24:14 +02:00
ミンツキ
eae24e64e5
Merge pull request #262 from klange/mb2-ignore-optional
multiboot2: ignore unsupported tags if they are marked optional
2023-04-12 13:18:34 +02:00
K. Lange
2da6225f9e multiboot2: ignore unsupported tags if they are marked optional 2023-04-12 19:53:24 +09:00
K. Lange
a3f84fc4a3 multiboot2: Support TEXTMODE config as with linux 2023-04-12 19:50:01 +09:00
mintsuki
240d9688b0 multiboot2: Fix lack of argument to panic format string 2023-04-12 09:56:28 +02:00
mintsuki
7ad444936e host: Condense various host utilities into a single executable 2023-04-11 22:04:05 +02:00
mintsuki
eba0183b6e build: Reorganise warning flags 2023-04-11 17:15:41 +02:00
mintsuki
ebd1953e51 build: Use uppercase PIE/PIC compilation flags 2023-04-11 15:57:02 +02:00
mintsuki
514522125b uri: Backport pre-tinf-removal variable assignments 2023-04-08 03:10:53 +02:00
mintsuki
3438b8d235 misc: Revert back to using tinf for all GZ decompression 2023-04-08 02:17:02 +02:00
mintsuki
e0f8d94de7 limine: Fix spurious deprecation warnings coming from limine.h 2023-03-30 08:26:14 +02:00
mintsuki
67d2631826 limine: Add note about deprecation of terminal to PROTOCOL.md 2023-03-30 04:13:45 +02:00
mintsuki
b66184cfbd limine: Clarify ambiguity with response revision and internal modules 2023-03-30 03:51:59 +02:00
mintsuki
012605adf9 limine: Fix issue with internal modules and kernels in root dir 2023-03-30 02:43:52 +02:00
mintsuki
d0df21abb9 limine: Mark terminal as deprecated 2023-03-30 02:12:24 +02:00
mintsuki
01eeeb6e1d term: Drop in_bootloader for new Flanterm 2023-03-30 01:23:55 +02:00
mintsuki
779571339e misc: Updates for Flanterm rebrand 2023-03-29 22:43:06 +02:00
mintsuki
936240a3c6 limine-deploy: Check ferror() before using perror() on fread/fwrite fails 2023-03-29 20:29:03 +02:00
mintsuki
a2dd3449a8 limine: Fix framebuffer pointer in terminal struct being invalid without a framebuffer request 2023-03-29 11:04:53 +02:00
mintsuki
42027470c7 limine: Fix bug where internal modules are parsed with revision < 1 2023-03-25 00:59:26 +01:00
mintsuki
45ff0e2e93 limine: Document internal modules 2023-03-24 18:44:25 +01:00
mintsuki
d0ee1e7d65 limine: Support relative-to-kernel paths for internal modules 2023-03-24 18:24:27 +01:00
mintsuki
698ca1a665 limine: Honour LIMINE_INTERNAL_MODULE_REQUIRED flag 2023-03-24 10:18:18 +01:00
mintsuki
830251e68e limine: Load internal modules before config modules 2023-03-24 09:07:40 +01:00
mintsuki
d4334699e3 limine: Implement internal modules concept 2023-03-24 01:02:31 +01:00
mintsuki
5a53f91e01 build: Split test portion of root makefile to own file 2023-03-23 16:03:58 +01:00
mintsuki
0196abf2ec build: Minor build system updates 2023-03-23 02:35:08 +01:00
mintsuki
2ea3f7e9d8 build: Minor build system updates 2023-03-23 01:02:58 +01:00
mintsuki
3bf159d81c compress: Rename modified tinfgzip wrapper to gzip 2023-03-16 22:49:24 +01:00
mintsuki
9663318102 build: Remove useless unset commands from common GNUmakefile 2023-03-16 17:01:41 +01:00
mintsuki
c202cce72c build: Use DEFAULT_VAR for all overridable default makefile vars 2023-03-16 16:09:02 +01:00
mintsuki
813c1e6c95 Revert "build: bootstrap: Do not manually install install-sh"
This reverts commit 5f5c98866e.
2023-03-16 04:38:59 +01:00
mintsuki
fadb9a7c13 build: Misc updates for new freestanding-toolchain 2023-03-16 03:38:53 +01:00
mintsuki
7d6125d413 build: Fix up some makefile variable names 2023-03-16 02:49:45 +01:00
mintsuki
f71f506b0a build: configure: Change some variable names to be more friendly 2023-03-16 02:28:50 +01:00
mintsuki
08647f7d5c decompressor: Move tinf directory to decompressor directory 2023-03-16 01:23:11 +01:00
mintsuki
c7a7539d23 build: configure: Exit on freestanding-toolchain error 2023-03-14 22:35:11 +01:00
mintsuki
5f5c98866e build: bootstrap: Do not manually install install-sh 2023-03-14 20:07:05 +01:00
mintsuki
7dc04b42cc build: Add and use PROG_ABSPATH autoconf macro 2023-03-14 19:51:22 +01:00
mintsuki
9009404a11 build: Updates for newer freestanding-toolchain 2023-03-14 17:20:46 +01:00
mintsuki
674f490f7b misc: bootstrap: Fix freestanding-toolchain presence check 2023-03-14 12:08:14 +01:00
mintsuki
b072a08f72 misc: Do not remove freestanding-toolchain from release tarball 2023-03-13 20:51:44 +01:00
mintsuki
8d61d0ab3a misc: Use freestanding-toolchain instead of cross-detect 2023-03-13 20:40:32 +01:00
mintsuki
d1e4b9946c docs: LICENSE.md -> LICENSE 2023-03-10 14:01:49 +01:00
mintsuki
828e3790a4 chainload: LoadOptionsSize should be in bytes. Fixes #254 2023-03-08 15:40:11 +01:00
mintsuki
ca69475609 protocol: Specify that kernel must be physically contiguous 2023-03-08 07:34:06 +01:00
mintsuki
246276a538 chainload: BIOS: do not rely on 0x7c00 being free 2023-03-07 13:07:28 +01:00
mintsuki
980c122475 vga_textmode: Minor cursor-related bug fixes 2023-03-07 13:07:28 +01:00
mintsuki
4ef529b4eb misc: Load BIOS port at 0xf000 instead of 0x8000 2023-03-07 02:21:09 +01:00
mintsuki
5bc6fbca3b misc: Change example wallpaper 2023-03-06 22:22:58 +01:00
mintsuki
fc4e283ad5 stb_image: Fix free/realloc wrappers to handle being passed NULL 2023-03-05 19:01:31 +01:00
mintsuki
0f4beb1bfd gterm: Fix NULL dereference bug when no wallpaper used 2023-03-05 09:49:28 +01:00
mintsuki
9d6c64954c gh: Remove issue templates 2023-03-05 09:21:11 +01:00
mintsuki
1dd75a18ac compress/gz: Add hack to allow macOS compressed GZs to load with stbi 2023-03-05 09:08:37 +01:00
mintsuki
8bb12244be image: Use stbi_image_free() instead of freeing buffer ourselves 2023-03-05 08:47:38 +01:00
mintsuki
753bb820ae stb_image: More proper implementation of malloc/free/realloc macros 2023-03-05 08:29:27 +01:00
mintsuki
5f84ade177 docs: Minor README.md formatting fix 2023-03-05 08:01:41 +01:00
mintsuki
959c44658e image: Use stb_image for image loading 2023-03-05 07:57:54 +01:00
mintsuki
11ef3bced2 build: Honour CROSS_CPPFLAGS 2023-02-25 01:38:26 +01:00
mintsuki
a786c26a26 build: Install markdown docs on install; distclean fix 2023-02-21 03:32:27 +01:00
mintsuki
8ee9dc1ebd build: Only install limine-deploy.1 man page if built 2023-02-21 01:35:57 +01:00
mintsuki
d17e220e61 docs: Add man pages for host executables 2023-02-21 00:15:04 +01:00
mintsuki
9bcad9d258 build: Very minor QOL fixes 2023-02-20 22:24:21 +01:00
mintsuki
b4649f8808 docs: Update PHILOSOPHY.md to note reason for ext* driver inclusion 2023-02-20 05:10:33 +01:00
mintsuki
1e65ada438 Revert "fs: Drop ext* support"
This reverts commit caaf4f94a5.
2023-02-20 05:10:33 +01:00
mintsuki
c924d7b7e5 build: Misc quality-of-life fixes 2023-02-19 10:07:21 +01:00
mintsuki
ce7a552723 misc: Let freestanding-headers handle limits.h 2023-02-18 09:41:30 +01:00
mintsuki
c7f344784c menu: Fix issue introduced in 48053fd2 where TIMEOUT=0 would not show interface 2023-02-16 07:18:04 +01:00
mintsuki
48053fd206 misc: Fix bug on trunk where returns to menu from panic would crash 2023-02-16 03:54:10 +01:00
mintsuki
e909489635 vga_textmode: Unbreak on trunk 2023-02-16 03:21:06 +01:00
mintsuki
a3f814b5f7 uri/tinfgzip: Minor fixes and layering improvement 2023-02-16 02:05:11 +01:00
mintsuki
3ae87be595 uri: Fix minor use-after-free bug 2023-02-15 21:09:46 +01:00
mintsuki
9b07351208 uri: Prevent memory leak when opening compressed files 2023-02-15 21:05:55 +01:00
mintsuki
82aec4b1b2 docs: Update PHILOSOPHY.md noting that ext2/3/4 has been dropped 2023-02-15 12:28:16 +01:00
mintsuki
143d3d85de stb/image: Comment out problematic functions 2023-02-15 11:53:07 +01:00
mintsuki
1099993b14 stb: Ignore some warnings coming from stb_image.h 2023-02-15 11:31:28 +01:00
mintsuki
71b3ae548b compress: Replace tinf's inflate implementation with stb_image's zlib 2023-02-15 11:21:53 +01:00
mintsuki
caaf4f94a5 fs: Drop ext* support 2023-02-15 11:21:53 +01:00
mintsuki
bcac8b6256 build: Use separate STRIP program in host Makefile 2023-02-12 23:13:26 +01:00
mintsuki
d744fc8c63 build: Further fixes related to cd8188d8 2023-02-12 23:13:26 +01:00
mintsuki
ec34c86d58 build: Update for latest cross-detect 2023-02-12 22:20:38 +01:00
mintsuki
8b7dc549f7 build: Misc configure.ac improvements, install-strip fix ups 2023-02-12 20:14:51 +01:00
mintsuki
7e46840b86 build: Update for latest cross-detect 2023-02-12 07:39:17 +01:00
mintsuki
87bea2fe0d host/enroll-config: Bring up to standard with deploy 2023-02-08 22:52:54 +01:00
mintsuki
8d427d7699 host/enroll-config: Fix buffer overflow 2023-02-08 21:59:02 +01:00
mintsuki
cd8188d832 build: Fix race condition in root GNUmakefile.in 2023-02-07 05:09:52 +01:00
mintsuki
fb4b02a451 docs: README.md: Document secure boot and config hash enrolling 2023-02-07 00:49:40 +01:00
mintsuki
8c7655eacd docs: Misc README.md fixes and updates 2023-02-07 00:42:13 +01:00
mintsuki
c30afde043 config: Do not allow recovering from checksum mismatch panic 2023-02-07 00:28:51 +01:00
mintsuki
843be07536 config: No longer allow continuing boot on checksum mismatches 2023-02-07 00:23:10 +01:00
mintsuki
8c7a98310a misc: Add support for enrolling config blake2b hash in executable 2023-02-06 23:58:19 +01:00
mintsuki
191ad51eaa docs: Add PHILOSOPHY.md 2023-02-06 20:24:57 +01:00
mintsuki
5c1b96b393 protocol: Update copyright date in limine.h 2023-02-06 19:28:51 +01:00
mintsuki
a7721872dd term: Expose support for out-of-band output control 2023-01-20 20:14:38 +01:00
mintsuki
28dd8a1062 file: Fix several bugs to do with handling of path field 2023-01-20 17:27:41 +01:00
mintsuki
2091aa9c21 Revert "Revert "Revert "ci: Build and check using Alpine instead of Arch"""
This reverts commit 8caf7b5b75.
2023-01-20 16:25:15 +01:00
mint
41d4b3af54
Merge pull request #246 from Qwinci/trunk
limine: Add UEFI PXE support
2023-01-17 22:56:35 +01:00
Qwinci
3dd0a6fb41
limine: Add UEFI PXE support
based on @qookei's original patch with small changes.
2023-01-17 18:47:36 +02:00
mintsuki
ac1c5d1b95 efi/chainload: Support passing of command lines. Addresses #244 2023-01-14 12:49:22 +01:00
mintsuki
a085af55ec misc: Update copyright for 2023 2023-01-11 06:36:13 +01:00
mintsuki
8caf7b5b75 Revert "Revert "ci: Build and check using Alpine instead of Arch""
This reverts commit ce4046d559.
2022-12-30 09:04:45 +01:00
mintsuki
a0d8c7b2ab ci: Remove website upload portion of workflow 2022-12-30 08:53:36 +01:00
mintsuki
2ee939725e term: Compatibility with new terminal code 2022-12-30 07:58:46 +01:00
mintsuki
1aba6b3aeb lib/gterm: Remove now-useless full_refresh() call 2022-12-16 03:53:42 +01:00
mintsuki
10bbba0066 docs: Document TERM_BACKGROUND_BRIGHT and TERM_FOREGROUND_BRIGHT 2022-12-16 03:33:29 +01:00
mintsuki
b3c08f8122 term: Compatibility with latest terminal changes 2022-12-14 16:35:03 +01:00
mintsuki
fc6b69f0ac host/limine-deploy: Add quiet option. Closes #243 2022-12-13 13:18:18 +01:00
mintsuki
382d88913d docs/protocol: Fix syntax highlighting of struct limine_video_mode 2022-12-08 12:25:43 +01:00
mint
040a15817f
Merge pull request #240 from TornaxO7/add_docs_to_stack
adding bytes description to stack_size
2022-12-08 12:10:42 +01:00
TornaxO7
98bfcc6dbd
adding bytes description to stack_size 2022-12-06 14:22:24 +01:00
mint
6df8a35698
Merge pull request #239 from Lockna/errata-protocol
docs/protocol: Fix wording for reserved/reclaimable
2022-12-01 01:18:01 +01:00
Raphael O
3fc36e9ac1
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-11-30 21:19:58 +01:00
mintsuki
25c6c18c8b Revert "fs: Drop ext* support"
This reverts commit ba5aca6fd8.
2022-11-30 01:48:00 +01:00
mintsuki
0748cf5bf2 Revert "fs: Fix unused variable warning introduced in ba5aca6f"
This reverts commit a48036141f.
2022-11-30 01:48:00 +01:00
mintsuki
a48036141f fs: Fix unused variable warning introduced in ba5aca6f 2022-11-29 17:05:01 +01:00
mintsuki
ba5aca6fd8 fs: Drop ext* support 2022-11-29 16:55:43 +01:00
mint
32d7aa1815
Merge pull request #238 from qookei/fix-aa64-fbs
limine: Fix caching mode detection for multiple framebuffers on AArch64
2022-11-25 03:21:51 +01:00
Kacper Słomiński
04d22b1e52 limine: Fix caching mode detection for multiple framebuffers on AArch64 2022-11-23 01:03:06 +01:00
mintsuki
ffaaabf14a readline: Fix issue arising from terminal's wraparound handling fix 2022-11-19 08:04:17 +01:00
mintsuki
c2854bde82 gop: Fix small issue causing IA-32 UEFI port not to build 2022-11-19 06:35:41 +01:00
mintsuki
f9399fd5a3 disk: Fix issue where _p struct was not zeroed out in create_disk_index() 2022-11-19 06:35:41 +01:00
mint
15127263ca
Merge pull request #236 from beakeyz/memleakfix_disk_create_index
Fixed little memory leak in the UEFI build
2022-11-19 00:37:55 +01:00
mintsuki
d39baeaa80 video: Initial support for multiple framebuffers 2022-11-18 23:59:31 +01:00
beakeyz
28187433f9 Fixed little memory leak in the UEFI build that would make the bootloader crash on systems with larger disks 2022-11-18 22:28:28 +00:00
mintsuki
9b68f081cf docs: Add packaging status to README.md 2022-11-15 11:25:51 +01:00
mintsuki
bf4c0f7d7a gop: Remove ConOut logic 2022-11-15 11:25:51 +01:00
mint
99f8c7b187
Merge pull request #234 from raccog/trunk
readline: Fix command line scrolling and cursor wrap-around
2022-11-14 07:45:27 +01:00
mintsuki
e924aa5f26 gop: Use ConOut to obtain GOP whenever possible 2022-11-14 07:35:06 +01:00
mintsuki
970292460d limine.h: Use C90 style comments for license header 2022-11-14 07:35:06 +01:00
mintsuki
60c115658c Revert "gop: Allow user to select which GOP to use in config. Addresses #233"
This reverts commit d82dc64b93.
2022-11-14 07:35:06 +01:00
mintsuki
20572082c1 Revert "gop: Fix implicit declaration warning introduced in d82dc64b"
This reverts commit c477414c5c.
2022-11-14 07:35:06 +01:00
Ryan Cohen
07d8dd2c68
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-13 13:49:00 -05:00
mintsuki
c477414c5c gop: Fix implicit declaration warning introduced in d82dc64b 2022-11-12 00:34:20 +01:00
mintsuki
d82dc64b93 gop: Allow user to select which GOP to use in config. Addresses #233 2022-11-11 23:40:56 +01:00
mintsuki
22c041ff08 limine.h: Add license header 2022-11-05 15:44:08 +01:00
mintsuki
1258f01bc2 Revert "smp/x86: Free up trampoline memory after use"
This reverts commit ae771dd8a1.
2022-11-02 15:28:07 +01:00
mintsuki
144c481ed5 docs/protocol: Clarify file address alignment 2022-10-30 13:58:01 +01:00
mintsuki
7e403e0059 multiboot2: Support load_addr == -1 2022-10-30 11:19:02 +01:00
mintsuki
ae771dd8a1 smp/x86: Free up trampoline memory after use 2022-10-29 16:17:57 +02:00
mintsuki
49f4ccd312 pmm: Work around potential memmap data race in EFI init_memmap() 2022-10-17 06:28:53 +02:00
mintsuki
09faf82bc4 pmm: Fix AllocatePages() call to take pages count; remove useless alignment check 2022-10-17 04:41:11 +02:00
mintsuki
d8193abc98 pmm: Avoid throwing away big memory ranges that fail to AllocatePages() indiscriminately 2022-10-17 04:34:27 +02:00
mintsuki
ce4046d559 Revert "ci: Build and check using Alpine instead of Arch"
This reverts commit 502f77b30f.
2022-10-16 01:31:36 +02:00
mintsuki
7e1d4a9870 linux: Revert 793d0293 2022-10-14 14:28:17 +02:00
mintsuki
3c541576f3 disk: Fix wrong parameter passed to ReadBlocks() 2022-10-14 06:59:35 +02:00
mintsuki
c7e62083fd docs: Document blake2b checksums related things 2022-10-14 06:07:53 +02:00
mintsuki
f0d6aa8033 docs: Fix formatting issue in PROTOCOL.md 2022-10-14 06:07:53 +02:00
mintsuki
c14bb6059f gop: Do not zero default_res out erroneously 2022-10-14 05:34:54 +02:00
mintsuki
e0aec79cb6 limine: Add support for framebuffer modes listing 2022-10-14 05:19:13 +02:00
mintsuki
01ee09373c file: Reimplement a1bcf3c0 without use-after-free bug 2022-10-14 05:15:17 +02:00
mintsuki
502f77b30f ci: Build and check using Alpine instead of Arch 2022-10-14 00:02:55 +02:00
mintsuki
42b1db1063 misc: Update references to hardcoded directories 2022-10-14 00:02:55 +02:00
mintsuki
b30d2dc978 disk: UEFI: Add BLOCK_IO fallback for volume_from_efi_handle() 2022-10-14 00:02:55 +02:00
mintsuki
da5896b764 disk: On UEFI, improve optical vs non-optical detection 2022-10-14 00:02:55 +02:00
mintsuki
6022f5bf23 elf: Add overlapping PHDR detection 2022-10-10 04:35:28 +02:00
mintsuki
96fe1aa2e0 disk: Only use BLOCK_IO as fallback to DISK_IO when determining optical 2022-10-09 10:58:07 +02:00
mintsuki
d265cad7b6 disk: On BIOS, change how optical is determined 2022-10-09 10:58:07 +02:00
mintsuki
ce33e9dff3 limine: Fix bug which triggered on no-NX where wrong register was used for rd/wrmsr 2022-10-09 07:31:26 +02:00
mintsuki
fa40b927cd docs: Update README.md 2022-10-07 09:14:30 +02:00
mintsuki
d10d2baded menu: Add arrows to indicate overflow for many menu entries 2022-10-07 08:49:13 +02:00
mintsuki
af80341c8c misc: Dynamically allocate EFI memmap copy 2022-10-07 07:49:47 +02:00
mintsuki
53d20619ec menu: Properly handly high number of entries 2022-10-07 07:35:08 +02:00
mintsuki
2557aa8f46 misc: Increase EFI_COPY_MAX_ENTRIES to 2048 2022-10-07 06:23:49 +02:00
mintsuki
4ba1b2fd9d limine/smp: Fix stack offset accidentally added twice 2022-10-06 18:39:55 +02:00
mintsuki
3d95c8960c misc: Add limine subdir to stage3 and config search paths. Closes #225 2022-10-06 06:29:11 +02:00
mint
23f2c7dbac
Merge pull request #228 from czapek1337/some-fixes
Some minor fixes
2022-10-06 06:05:37 +02:00
czapek1337
02c26a8738
efi: Fallback to volume scan instead of panicking 2022-10-06 05:58:39 +02:00
mintsuki
b1319408dd menu: Add missing valid keys 2022-10-06 05:41:21 +02:00
mintsuki
7f09259c57 term: Misc improvements for SERIAL=yes on EFI 2022-10-06 05:41:21 +02:00
mintsuki
610a98d8b2 term: Unbreak textmode + serial combo 2022-10-06 05:41:21 +02:00
mintsuki
6e1c792e41 gterm: Prevent memory leak gterm_init() failure 2022-10-06 05:41:21 +02:00
mintsuki
fb994e61c6 limine: Fix NULL term dereference bug if gterm_init fails 2022-10-06 05:41:21 +02:00
czapek1337
44a3f3f2f7
disk: Use BLOCK_IO instead of DISK_IO 2022-10-06 05:38:06 +02:00
czapek1337
68e936e7f4
readline: Fallback to SystemTable->ConIn 2022-10-06 05:37:22 +02:00
mintsuki
ac34ec411f term: Better ensure term is not accessed when NULL 2022-10-05 15:01:01 +02:00
mintsuki
ec9d384bf2 limine: Do not panic if failing to set up terminal or framebuffer 2022-10-05 14:32:54 +02:00
mintsuki
cc8ff90865 menu: Use fallback terminal instead of panicking on gterm_init() fail 2022-10-05 14:32:54 +02:00
mintsuki
6cbb9c4577 limine: Fix bug where NULL term was accessed. Fixes #227 2022-10-05 14:32:54 +02:00
mintsuki
ffa6d4e0c7 limine: Reimplement proper callback functionality 2022-10-04 21:53:19 +02:00
mintsuki
d187c576d8 term: Make term_notready() static 2022-10-04 21:00:39 +02:00
mintsuki
ff8c5f318c term: Gate BIOS specific code behind ifdefs 2022-10-04 20:47:19 +02:00
mintsuki
f977548e84 term: Reimplement context control 2022-10-04 20:39:50 +02:00
mintsuki
48a7c12e5b term: Misc fixes and improvements 2022-10-04 19:10:38 +02:00
mintsuki
d3c8a66918 term: Misc fixes and improvements 2022-10-04 08:21:59 +02:00
mintsuki
b34954bb43 term: Misc fixes and improvements 2022-10-04 07:24:42 +02:00
mintsuki
45312e66ae term: Add builtin font 2022-10-04 06:04:31 +02:00
mintsuki
f6ba5991b5 term: Misc minor bug fixes 2022-10-04 05:39:48 +02:00
mintsuki
0f1d86e7e4 term: Tidy up VGA textmode wrapper code 2022-10-04 02:34:11 +02:00
mintsuki
8849d08eeb term: Tidy up gterm wrapper code 2022-10-04 01:37:19 +02:00
mintsuki
4d855fc17e term: Move to use external, portable terminal 2022-10-04 00:58:00 +02:00
mintsuki
e466501f92 pmm: Misc bug fixes in pmm 2022-09-28 01:16:39 +02:00
mintsuki
96c184fdf6 term: Misc bug fixes in fallback backends 2022-09-28 01:16:39 +02:00
mintsuki
7f046f67b9 build: Use variables to determine installable files instead of ignoring errors 2022-09-28 01:16:39 +02:00
mintsuki
e5d786158f docs: Update README.md in preparation for version naming scheme change 2022-09-27 06:48:05 +02:00
mintsuki
0d7b1e1148 term: Do not reset mode on UEFI fallback init 2022-09-27 06:36:04 +02:00
mintsuki
00e9f2ce46 multiboot: Fix warnings when building BIOS port 2022-09-27 05:55:00 +02:00
mintsuki
a2ba71eb1d multiboot: Allow for headless boots 2022-09-27 05:46:39 +02:00
mintsuki
c849bfc10b 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 04:59:29 +02:00
mintsuki
bd7c3602bb pmm: Keep first page on sanitiser call in get_raw_memmap() 2022-09-26 02:42:32 +02:00
mintsuki
97c928a354 pmm: Backport some other stuff reverted in 4a4409e1 2022-09-25 23:10:58 +02:00
mintsuki
64c897a82d pmm: Backport fa6f6077 and 74a3a1c6 2022-09-25 20:37:17 +02:00
mintsuki
714d8ac2ce Revert "file: Convert file to a memfile as soon as possible"
This reverts commit a1bcf3c09b.
2022-09-24 04:10:45 +02:00
mintsuki
4a4409e1b2 pmm: Undo most of what was done between 85603ec8 and 74a3a1c6 2022-09-24 03:57:55 +02:00
mintsuki
0cb98610f0 panic: Fix build on non-BIOS targets 2022-09-23 20:59:02 +02:00
mintsuki
e062b4ed7d term: Move more of it to stage 3 2022-09-23 20:53:14 +02:00
mintsuki
e67a75fe09 Revert "linux/efi: Perform efi_memmap_size=0 workaround for 32 on 64 as well"
This reverts commit b9f41799b4.
2022-09-23 01:00:44 +02:00
mintsuki
34a53292f7 build: Update install commands to be more quiet on non-fatal fail 2022-09-23 00:44:06 +02:00
mintsuki
b9f41799b4 linux/efi: Perform efi_memmap_size=0 workaround for 32 on 64 as well 2022-09-22 18:10:08 +02:00
mintsuki
390372533f build: Update build option dependencies and names 2022-09-22 15:58:59 +02:00
mintsuki
b229d0cdf3 config: On UEFI, scan the volume containing the EFI executable first. Addresses #219 2022-09-22 15:12:11 +02:00
mintsuki
0a28a0959b build: Honor LIBS variable 2022-09-20 23:10:19 +02:00
mintsuki
dab2a35b3e build: Honor CPPFLAGS variable 2022-09-20 21:28:12 +02:00
mintsuki
d5ff44676b menu: Fix regression when pressing a key during quiet timeout wait. Addresses in part #220 2022-09-20 15:25:24 +02:00
mintsuki
b1bfa2d2d8 build: Fix issue introduced in 87e09dba 2022-09-20 10:02:33 +02:00
mintsuki
a6189abdc1 misc: Fix bugs introduced in 3181293a 2022-09-20 09:54:35 +02:00
mintsuki
e89d834457 disk/efi: Improve firmware error handling 2022-09-19 20:48:42 +02:00
mintsuki
87e09dba61 build: Plug back limine_stage2only.elf into the BIOS build system 2022-09-19 02:31:23 +02:00
mintsuki
59bbd1f657 menu: Avoid reinitialising fallback terminal on first runs 2022-09-18 11:52:31 +02:00
mintsuki
26f6ac3bb2 smp: Fix indentation 2022-09-18 11:30:21 +02:00
mintsuki
dc5ed66e67 efi: Limit amount of tries to get boot volume from handle 2022-09-18 10:39:39 +02:00
mintsuki
f86a421209 misc: Fix up some no_unwind globals 2022-09-17 15:09:08 +02:00
mintsuki
0ae552a25c misc: Misc stage 2 related improvements 2022-09-17 13:53:57 +02:00
mintsuki
7f14f2f0d0 misc: Improve printing effectively on panics and errors 2022-09-17 10:40:14 +02:00
mintsuki
e76c8d47a9 multiboot2: Fix broken EFI memmap length calculation 2022-09-15 22:31:50 +02:00
mintsuki
50b524838a efi: Ensure panics are (hopefully) always visible 2022-09-15 13:31:42 +02:00
mintsuki
886523359c efi/disk: Use blake2b to calculate unique sector hash 2022-09-15 12:53:47 +02:00
mintsuki
430e841903 build: Do not request readelf from cross-detect when not needed 2022-09-15 06:56:32 +02:00
mintsuki
708868c889 build: Change name of --enable-uefi-x86_64 option to --enable-uefi-x86-64 2022-09-15 06:38:04 +02:00
mintsuki
a95d475c89 build: Only check nasm and gzip presence as needed 2022-09-15 06:33:29 +02:00
mintsuki
2b71eaedb6 smp: Fix aarch64 issue introduced in 0f04f686 2022-09-14 15:39:52 +02:00
mintsuki
0f04f6860a smp: Remove hacks needed for stivale 2022-09-14 14:54:55 +02:00
mintsuki
7e6aad3113 build: Fix stage2 map 2022-09-14 02:20:12 +02:00
mintsuki
ae4605936a misc: Minor cleanup after #216 2022-09-14 02:20:12 +02:00
mint
c1e98f26c9
Merge pull request #216 from czapek1337/blake2b
Implement blake2b hash function and checksum validation
2022-09-13 09:30:45 +02:00
czapek1337
9680a1ad51
uri: Add checksum validation 2022-09-13 01:14:55 +02:00
czapek1337
71eb143611
print: Specifier for printing URIs 2022-09-12 14:10:36 +02:00
czapek1337
a1bcf3c09b
file: Convert file to a memfile as soon as possible 2022-09-12 14:10:36 +02:00
czapek1337
8906518cd2
crypt: Implement blake2b hash function 2022-09-12 14:10:36 +02:00
mint
f8d714317b
Merge pull request #217 from Andy-Python-Programmer/trunk
DTB: ensure the `dtb_ptr` is an HHDM address
2022-09-12 09:27:18 +02:00
Andy-Python-Programmer
528be7230f
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 17:25:35 +10:00
mintsuki
82eb809111 elf: Fix issue where KASLR was applied to non reloc executables 2022-09-11 23:07:13 +02:00
167 changed files with 7633 additions and 6086 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

@ -10,7 +10,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 aarch64-linux-gnu-gcc
run: pacman --noconfirm -Syu && pacman --needed --noconfirm -S base-devel git autoconf automake nasm curl mtools llvm clang lld aarch64-linux-gnu-gcc riscv64-linux-gnu-gcc
- name: Checkout code
uses: actions/checkout@v3
@ -19,10 +19,13 @@ 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
- name: Build the bootloader (GNU, riscv64)
run: ./bootstrap && ./configure TOOLCHAIN_FOR_TARGET=riscv64-linux-gnu --enable-werror --enable-uefi-riscv64 && 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,25 +36,22 @@ 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
- name: Clean limine-version
run: rm build/bin/limine-version
- name: Clean limine
run: rm build/bin/limine
- name: Clean limine-deploy
run: rm build/bin/limine-deploy
- name: Build limine for Windows
run: make -C build/bin CC="i686-w64-mingw32-gcc" CFLAGS="-O2 -pipe" CPPFLAGS="-D__USE_MINGW_ANSI_STDIO" limine
- name: Build limine-deploy-win32
run: make -C build/bin CC="i686-w64-mingw32-gcc" CFLAGS="-O2 -pipe" limine-deploy
- name: Strip limine-deploy-win32
run: i686-w64-mingw32-strip build/bin/limine-deploy.exe
- name: Strip limine for Windows
run: i686-w64-mingw32-strip build/bin/limine.exe
- name: Copy LICENSE to bin
run: cp LICENSE.md build/bin/
run: cp COPYING build/bin/LICENSE
- name: Copy install-sh to bin
run: cp build-aux/install-sh build/bin/
@ -62,8 +59,8 @@ jobs:
- name: Copy limine.h to bin
run: cp limine.h build/bin/
- name: Remove limine-hdd.bin
run: rm build/bin/limine-hdd.bin
- name: Remove limine-bios-hdd.bin
run: rm build/bin/limine-bios-hdd.bin
- name: Push binaries to binary branch
run: |
@ -98,11 +95,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,19 +26,23 @@
/.vscode
/test_image
!/common/font.bin
/cross-detect
/freestanding-toolchain
/configure
/configure.ac.save
/INSTALL
/build-aux
/aclocal.m4
/*~
/config.status
/config.log
/autom4te.cache
/man/man1/limine.1
/GNUmakefile
/config.h
/common-bios
/common-uefi-ia32
/common-uefi-x86-64
/common-uefi-aarch64
/common-uefi-riscv64
/decompressor-build
/stage1.stamp

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`, `riscv64`. 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,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:

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_CD_EFI := @BUILD_CD_EFI@
override BUILD_PXE := @BUILD_PXE@
override BUILD_CD := @BUILD_CD@
override BUILD_LIMINE_DEPLOY := @BUILD_LIMINE_DEPLOY@
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_UEFI_RISCV64 := @BUILD_UEFI_RISCV64@
override BUILD_UEFI_CD := @BUILD_UEFI_CD@
override BUILD_BIOS_PXE := @BUILD_BIOS_PXE@
override BUILD_BIOS_CD := @BUILD_BIOS_CD@
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,124 +70,169 @@ 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@
$(MAKE) '$(call SHESCAPE,$(BINDIR))/limine-cd-efi.bin'
all: $(call MKESCAPE,$(BINDIR))/Makefile
$(MAKE) all1
$(call MKESCAPE,$(BINDIR))/limine-hdd.h: $(call MKESCAPE,$(BINDIR))/limine-hdd.bin
.PHONY: all1
all1: $(BUILD_UEFI_X86_64) $(BUILD_UEFI_IA32) $(BUILD_UEFI_AARCH64) $(BUILD_UEFI_RISCV64) $(BUILD_BIOS)
$(MAKE) '$(call SHESCAPE,$(BINDIR))/limine'
$(MAKE) '$(call SHESCAPE,$(BINDIR))/limine-uefi-cd.bin'
$(call MKESCAPE,$(BINDIR))/limine-bios-hdd.h: $(call MKESCAPE,$(BINDIR))/limine-bios-hdd.bin
$(MKDIR_P) '$(call SHESCAPE,$(BINDIR))'
cd '$(call SHESCAPE,$(BINDIR))' && '$(call SHESCAPE,$(SRCDIR))/host/hgen.sh' >limine-hdd.h
cd '$(call SHESCAPE,$(BINDIR))' && '$(call SHESCAPE,$(SRCDIR))/host/hgen.sh' >limine-bios-hdd.h
$(call MKESCAPE,$(BINDIR))/limine-deploy: $(call MKESCAPE,$(BINDIR))/Makefile $(call MKESCAPE,$(SRCDIR))/host/limine-deploy.c $(call MKESCAPE,$(BINDIR))/limine-hdd.h
cp '$(call SHESCAPE,$(SRCDIR))/host/limine-deploy.c' '$(call SHESCAPE,$(BINDIR))/'
$(MAKE) -C '$(call SHESCAPE,$(BINDIR))' limine-deploy
ifeq ($(BUILD_BIOS),limine-bios)
$(call MKESCAPE,$(BINDIR))/limine: $(call MKESCAPE,$(BINDIR))/Makefile $(call MKESCAPE,$(SRCDIR))/host/limine.c $(call MKESCAPE,$(BINDIR))/limine-bios-hdd.h
else
override LIMINE_NO_BIOS := -DLIMINE_NO_BIOS
$(call MKESCAPE,$(BINDIR))/limine-version: $(call MKESCAPE,$(BINDIR))/Makefile $(call MKESCAPE,$(SRCDIR))/host/limine-version.c
$(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: $(call MKESCAPE,$(BINDIR))/Makefile $(call MKESCAPE,$(SRCDIR))/host/limine.c
endif
$(SED) 's/%VERSION%/@PACKAGE_VERSION@/g;s/%COPYRIGHT%/@LIMINE_COPYRIGHT@/g' <'$(call SHESCAPE,$(SRCDIR))/host/limine.c' >'$(call SHESCAPE,$(BINDIR))/limine.c'
CPPFLAGS="$(CPPFLAGS) $(LIMINE_NO_BIOS)" $(MAKE) -C '$(call SHESCAPE,$(BINDIR))' limine
$(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
limine-deploy:
$(MAKE) '$(call SHESCAPE,$(BINDIR))/limine-deploy'
.PHONY: limine-version
limine-version:
$(MAKE) '$(call SHESCAPE,$(BINDIR))/limine-version'
.PHONY: limine
limine:
$(MAKE) '$(call SHESCAPE,$(BINDIR))/limine'
.PHONY: clean
clean: limine-bios-clean limine-uefi-ia32-clean limine-uefi-x86-64-clean limine-uefi-aarch64-clean
clean: limine-bios-clean limine-uefi-ia32-clean limine-uefi-x86-64-clean limine-uefi-aarch64-clean limine-uefi-riscv64-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))/COPYING' '$(call SHESCAPE,$(DESTDIR)$(docdir))/'
$(INSTALL_DATA) '$(call SHESCAPE,$(SRCDIR))/CONFIG.md' '$(call SHESCAPE,$(DESTDIR)$(docdir))/'
$(INSTALL_DATA) '$(call SHESCAPE,$(SRCDIR))/PROTOCOL.md' '$(call SHESCAPE,$(DESTDIR)$(docdir))/'
$(INSTALL_DATA) '$(call SHESCAPE,$(SRCDIR))/PHILOSOPHY.md' '$(call SHESCAPE,$(DESTDIR)$(docdir))/'
$(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.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-bios.sys' '$(call SHESCAPE,$(DESTDIR)$(datarootdir))/limine/'
endif
ifneq ($(BUILD_BIOS_CD),no)
$(INSTALL_DATA) '$(call SHESCAPE,$(BINDIR))/limine-bios-cd.bin' '$(call SHESCAPE,$(DESTDIR)$(datarootdir))/limine/'
endif
ifneq ($(BUILD_UEFI_CD),no)
$(INSTALL_DATA) '$(call SHESCAPE,$(BINDIR))/limine-uefi-cd.bin' '$(call SHESCAPE,$(DESTDIR)$(datarootdir))/limine/'
endif
ifneq ($(BUILD_BIOS_PXE),no)
$(INSTALL_DATA) '$(call SHESCAPE,$(BINDIR))/limine-bios-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_RISCV64),limine-uefi-riscv64)
$(INSTALL_DATA) '$(call SHESCAPE,$(BINDIR))/BOOTRISCV64.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' '$(call SHESCAPE,$(DESTDIR)$(bindir))/'
.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'
.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))/COPYING'
rm -f '$(call SHESCAPE,$(DESTDIR)$(docdir))/CONFIG.md'
rm -f '$(call SHESCAPE,$(DESTDIR)$(docdir))/PROTOCOL.md'
rm -f '$(call SHESCAPE,$(DESTDIR)$(docdir))/PHILOSOPHY.md'
rm -f '$(call SHESCAPE,$(DESTDIR)$(docdir))/README.md'
rm -f '$(call SHESCAPE,$(DESTDIR)$(mandir))/man1/limine.1'
rm -f '$(call SHESCAPE,$(DESTDIR)$(bindir))/limine'
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'
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/hdd' && nasm bootsect.asm -Wall $(WERROR_FLAG) -fbin -DBUILDDIR="'"'$(call NASMESCAPE,$(BUILDDIR))'"'" -o '$(call SHESCAPE,$(BINDIR))/limine-bios-hdd.bin'
ifneq ($(BUILD_BIOS_CD),no)
cd '$(call SHESCAPE,$(SRCDIR))/stage1/cd' && nasm bootsect.asm -Wall $(WERROR_FLAG) -fbin -DBUILDDIR="'"'$(call NASMESCAPE,$(BUILDDIR))'"'" -o '$(call SHESCAPE,$(BINDIR))/limine-bios-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'
ifneq ($(BUILD_BIOS_PXE),no)
cd '$(call SHESCAPE,$(SRCDIR))/stage1/pxe' && nasm bootsect.asm -Wall $(WERROR_FLAG) -fbin -DBUILDDIR="'"'$(call NASMESCAPE,$(BUILDDIR))'"'" -o '$(call SHESCAPE,$(BINDIR))/limine-bios-pxe.bin'
endif
cp '$(call SHESCAPE,$(BUILDDIR))/common-bios/limine.sys' '$(call SHESCAPE,$(BINDIR))/'
cp '$(call SHESCAPE,$(BUILDDIR))/common-bios/limine-bios.sys' '$(call SHESCAPE,$(BINDIR))/'
touch '$(call SHESCAPE,$(BUILDDIR))/stage1.stamp'
.PHONY: limine-bios
limine-bios: common-bios decompressor
$(MAKE) '$(call SHESCAPE,$(BUILDDIR))/stage1.stamp'
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)
ifneq ($(BUILD_CD_EFI),no)
$(call MKESCAPE,$(BINDIR))/limine-uefi-cd.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) $(if $(BUILD_UEFI_RISCV64),$(call MKESCAPE,$(BUILDDIR))/common-uefi-riscv64/BOOTRISCV64.EFI)
ifneq ($(BUILD_UEFI_CD),no)
$(MKDIR_P) '$(call SHESCAPE,$(BINDIR))'
rm -f '$(call SHESCAPE,$(BINDIR))/limine-cd-efi.bin'
dd if=/dev/zero of='$(call SHESCAPE,$(BINDIR))/limine-cd-efi.bin' bs=512 count=2880 2>/dev/null
( mformat -i '$(call SHESCAPE,$(BINDIR))/limine-cd-efi.bin' -f 1440 :: && \
mmd -D s -i '$(call SHESCAPE,$(BINDIR))/limine-cd-efi.bin' ::/EFI && \
mmd -D s -i '$(call SHESCAPE,$(BINDIR))/limine-cd-efi.bin' ::/EFI/BOOT && \
rm -f '$(call SHESCAPE,$(BINDIR))/limine-uefi-cd.bin'
dd if=/dev/zero of='$(call SHESCAPE,$(BINDIR))/limine-uefi-cd.bin' bs=512 count=2880 2>/dev/null
( mformat -i '$(call SHESCAPE,$(BINDIR))/limine-uefi-cd.bin' -f 1440 :: && \
mmd -D s -i '$(call SHESCAPE,$(BINDIR))/limine-uefi-cd.bin' ::/EFI && \
mmd -D s -i '$(call SHESCAPE,$(BINDIR))/limine-uefi-cd.bin' ::/EFI/BOOT && \
( ( [ -f '$(call SHESCAPE,$(BUILDDIR))/common-uefi-aarch64/BOOTAA64.EFI' ] && \
mcopy -D o -i '$(call SHESCAPE,$(BINDIR))/limine-cd-efi.bin' '$(call SHESCAPE,$(BUILDDIR))/common-uefi-aarch64/BOOTAA64.EFI' ::/EFI/BOOT ) || true ) && \
mcopy -D o -i '$(call SHESCAPE,$(BINDIR))/limine-uefi-cd.bin' '$(call SHESCAPE,$(BUILDDIR))/common-uefi-aarch64/BOOTAA64.EFI' ::/EFI/BOOT ) || true ) && \
( ( [ -f '$(call SHESCAPE,$(BUILDDIR))/common-uefi-riscv64/BOOTRISCV64.EFI' ] && \
mcopy -D o -i '$(call SHESCAPE,$(BINDIR))/limine-uefi-cd.bin' '$(call SHESCAPE,$(BUILDDIR))/common-uefi-riscv64/BOOTRISCV64.EFI' ::/EFI/BOOT ) || true ) && \
( ( [ -f '$(call SHESCAPE,$(BUILDDIR))/common-uefi-x86-64/BOOTX64.EFI' ] && \
mcopy -D o -i '$(call SHESCAPE,$(BINDIR))/limine-cd-efi.bin' '$(call SHESCAPE,$(BUILDDIR))/common-uefi-x86-64/BOOTX64.EFI' ::/EFI/BOOT ) || true ) && \
mcopy -D o -i '$(call SHESCAPE,$(BINDIR))/limine-uefi-cd.bin' '$(call SHESCAPE,$(BUILDDIR))/common-uefi-x86-64/BOOTX64.EFI' ::/EFI/BOOT ) || true ) && \
( ( [ -f '$(call SHESCAPE,$(BUILDDIR))/common-uefi-ia32/BOOTIA32.EFI' ] && \
mcopy -D o -i '$(call SHESCAPE,$(BINDIR))/limine-cd-efi.bin' '$(call SHESCAPE,$(BUILDDIR))/common-uefi-ia32/BOOTIA32.EFI' ::/EFI/BOOT ) || true ) \
) || rm -f '$(call SHESCAPE,$(BINDIR))/limine-cd-efi.bin'
mcopy -D o -i '$(call SHESCAPE,$(BINDIR))/limine-uefi-cd.bin' '$(call SHESCAPE,$(BUILDDIR))/common-uefi-ia32/BOOTIA32.EFI' ::/EFI/BOOT ) || true ) \
) || rm -f '$(call SHESCAPE,$(BINDIR))/limine-uefi-cd.bin'
endif
.PHONY: limine-cd-efi
limine-cd-efi:
$(MAKE) '$(call SHESCAPE,$(BINDIR))/limine-cd-efi.bin'
.PHONY: limine-uefi-cd
limine-uefi-cd:
$(MAKE) '$(call SHESCAPE,$(BINDIR))/limine-uefi-cd.bin'
$(call MKESCAPE,$(BINDIR))/BOOTX64.EFI: $(call MKESCAPE,$(BUILDDIR))/common-uefi-x86-64/BOOTX64.EFI
$(MKDIR_P) '$(call SHESCAPE,$(BINDIR))'
@ -200,6 +261,15 @@ limine-uefi-aarch64:
$(MAKE) common-uefi-aarch64
$(MAKE) '$(call SHESCAPE,$(BINDIR))/BOOTAA64.EFI'
$(call MKESCAPE,$(BINDIR))/BOOTRISCV64.EFI: $(call MKESCAPE,$(BUILDDIR))/common-uefi-riscv64/BOOTRISCV64.EFI
$(MKDIR_P) '$(call SHESCAPE,$(BINDIR))'
cp '$(call SHESCAPE,$(BUILDDIR))/common-uefi-riscv64/BOOTRISCV64.EFI' '$(call SHESCAPE,$(BINDIR))/'
.PHONY: limine-uefi-riscv64
limine-uefi-riscv64:
$(MAKE) common-uefi-riscv64
$(MAKE) '$(call SHESCAPE,$(BINDIR))/BOOTRISCV64.EFI'
.PHONY: limine-bios-clean
limine-bios-clean: common-bios-clean decompressor-clean
@ -212,18 +282,22 @@ limine-uefi-ia32-clean: common-uefi-ia32-clean
.PHONY: limine-uefi-aarch64-clean
limine-uefi-aarch64-clean: common-uefi-aarch64-clean
.PHONY: limine-uefi-riscv64-clean
limine-uefi-riscv64-clean: common-uefi-riscv64-clean
.PHONY: dist
dist:
rm -rf '$(call SHESCAPE,$(BUILDDIR))'/"limine-$(LIMINE_VERSION)"
$(MKDIR_P) '$(call SHESCAPE,$(BUILDDIR))'/"limine-$(LIMINE_VERSION)"
cp -r '$(call SHESCAPE,$(SRCDIR))'/.git '$(call SHESCAPE,$(BUILDDIR))'/"limine-$(LIMINE_VERSION)"/
cd '$(call SHESCAPE,$(BUILDDIR))'/"limine-$(LIMINE_VERSION)" && git checkout .
cd '$(call SHESCAPE,$(BUILDDIR))'/"limine-$(LIMINE_VERSION)" && git log --oneline --decorate > ChangeLog
cd '$(call SHESCAPE,$(BUILDDIR))'/"limine-$(LIMINE_VERSION)" && ./bootstrap
rm -rf '$(call SHESCAPE,$(BUILDDIR))'/"limine-$(LIMINE_VERSION)/common/flanterm/.git"
rm -rf '$(call SHESCAPE,$(BUILDDIR))'/"limine-$(LIMINE_VERSION)/freestanding-headers/.git"
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"; \
libgcc_needed="i686 x86_64-no-red-zone aarch64 riscv64-softfloat"; \
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"; \
done; \
@ -231,17 +305,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 +322,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.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 INSTALL 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 +342,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'
@ -279,10 +350,21 @@ common-uefi-aarch64:
common-uefi-aarch64-clean:
rm -rf '$(call SHESCAPE,$(BUILDDIR))/common-uefi-aarch64'
.PHONY: common-uefi-riscv64
common-uefi-riscv64:
$(MAKE) -C '$(call SHESCAPE,$(SRCDIR))/common' all \
TOOLCHAIN_FILE='$(call SHESCAPE,$(BUILDDIR))/toolchain-files/uefi-riscv64-toolchain.mk' \
TARGET=uefi-riscv64 \
BUILDDIR='$(call SHESCAPE,$(BUILDDIR))/common-uefi-riscv64'
.PHONY: common-uefi-riscv64-clean
common-uefi-riscv64-clean:
rm -rf '$(call SHESCAPE,$(BUILDDIR))/common-uefi-riscv64'
.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 +375,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 +386,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

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,18 +112,69 @@ If the kernel is a position independent executable, the bootloader is free to
relocate it as it sees fit, potentially performing KASLR (as specified by the
config).
## Entry machine state
## Caching
### x86_64
### x86-64
The kernel executable, loaded at or above `0xffffffff80000000`, sees all of its
segments mapped using write-back (WB) caching at the page tables level.
All HHDM and identity map memory regions are mapped using write-back (WB) caching at the page
tables level, except framebuffer regions which are mapped using write-combining
(WC) caching at the page tables level.
The PAT's (Page Attribute Table) layout is specified to be as follows:
```
PAT0 -> WB
PAT1 -> WT
PAT2 -> UC-
PAT3 -> UC
PAT4 -> WP
PAT5 -> WC
PAT6 -> unspecified
PAT7 -> unspecified
```
The MTRRs are left as the firmware set them up.
### aarch64
The kernel executable, loaded at or above `0xffffffff80000000`, sees all of its
segments mapped using Normal Write-Back RW-Allocate non-transient caching mode.
All HHDM and identity map memory regions are mapped using the Normal Write-Back RW-Allocate
non-transient caching mode, except for the framebuffer regions, which are
mapped in using an unspecified caching mode, correct for use with the
framebuffer on the platform.
The `MAIR_EL1` register will at least contain entries for the above-mentioned
caching modes, in an unspecified order.
In order to access MMIO regions, the kernel must ensure the correct caching mode
is used on its own.
### riscv64
If the `Svpbmt` extension is available, all framebuffer memory regions are mapped
with `PBMT=NC` to enable write-combining optimizations. The kernel executable,
loaded at or above `0xffffffff80000000`, and all HHDM and identity map memory regions are mapped
with the default `PBMT=PMA`.
If the `Svpbmt` extension is not available, no PMAs can be overridden (effectively,
everything is mapped with `PBMT=PMA`).
## Machine state at entry
### x86-64
`rip` will be the entry point as defined as part of the executable file format,
unless the an Entry Point feature is requested (see below), in which case,
the value of `rip` is going to be taken from there.
unless the Entry Point feature is requested (see below), in which case, the value
of `rip` is going to be taken from there.
At entry all segment registers are loaded as 64 bit code/data segments, limits
and bases are ignored since this is 64-bit mode.
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.
@ -159,30 +212,28 @@ All other general purpose registers are set to 0.
### aarch64
`PC` will be the entry point as defined as part of the executable file format,
unless the an Entry Point feature is requested (see below), in which case,
unless the Entry Point feature is requested (see below), in which case,
the value of `PC` is going to be taken from there.
The contents of the `VBAR_EL1` register are undefined, and the kernel must load it's own.
The contents of the `VBAR_EL1` register are undefined, and the kernel must load
its own.
The `MAIR_EL1` register will contain at least these entries, in an unspecified order:
- Normal, Write-back RW-Allocate non-transient (`0b11111111`),
- Unspecified, correct for use with the framebuffer.
The kernel and the lower-half identity mapping will be mapped with Normal write-back memory,
while the framebuffer is mapped with the correct caching mode. The kernel must ensure that
MMIO it wants to access is mapped with the correct caching mode.
The `MAIR_EL1` register contents are described above, in the caching section.
All interrupts are masked (`PSTATE.{D, A, I, F}` are set to 1).
The kernel is entered in little-endian AArch64 EL1t (EL1 with `PSTATE.SP` set to 0, `PSTATE.E` set to 0, and `PSTATE.nRW` set to 0).
The kernel is entered in little-endian AArch64 EL1t (EL1 with `PSTATE.SP` set to
0, `PSTATE.E` set to 0, and `PSTATE.nRW` set to 0).
Other fields of `PSTATE` are undefined.
At entry: the MMU (`SCTLR_EL1.M`) is enabled, the I-Cache and D-Cache (`SCTLR_EL1.{I, C}`) are enabled,
data alignment checking (`SCTLR_EL1.A`) is disabled. SP alignment checking (`SCTLR_EL1.{SA, SA0}`) is enabled.
Other fields of `SCTLR_EL1` are reset to 0 or to their reserved value.
At entry: the MMU (`SCTLR_EL1.M`) is enabled, the I-Cache and D-Cache
(`SCTLR_EL1.{I, C}`) are enabled, data alignment checking (`SCTLR_EL1.A`) is
disabled. SP alignment checking (`SCTLR_EL1.{SA, SA0}`) is enabled. Other fields
of `SCTLR_EL1` are reset to 0 or to their reserved value.
Higher ELs do not interfere with accesses to vector or floating point instructions or registers.
Higher ELs do not interfere with accesses to vector or floating point
instructions or registers.
Higher ELs do not interfere with accesses to the generic timer and counter.
@ -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 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.

143
README.md
View File

@ -2,19 +2,28 @@
### 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)
* riscv64
### Supported boot protocols
* Linux
@ -23,25 +32,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, aarch64, and riscv64 (UEFI) systems are supported.
## Packaging status
[![Packaging status](https://repology.org/badge/vertical-allrepos/limine.svg)](https://repology.org/project/limine/versions)
## Binary releases
@ -50,19 +62,19 @@ are shipped in the `-binary` branches and tags of this repository
(see [branches](https://github.com/limine-bootloader/limine/branches/all) and
[tags](https://github.com/limine-bootloader/limine/tags)).
For example, to clone the latest binary release of the `v4.x` branch one can do
For example, to clone the latest binary release of the `v5.x` branch one can do
```bash
git clone https://github.com/limine-bootloader/limine.git --branch=v4.x-branch-binary --depth=1
git clone https://github.com/limine-bootloader/limine.git --branch=v5.x-branch-binary --depth=1
```
or, to clone a specific binary point release (for example `v4.0`)
or, to clone a specific binary point release (for example `v5.20231024.0`)
```bash
git clone https://github.com/limine-bootloader/limine.git --branch=v4.0-binary --depth=1
git clone https://github.com/limine-bootloader/limine.git --branch=v5.20231024.0-binary --depth=1
```
In order to rebuild `limine-deploy`, simply run `make` in the binary
In order to rebuild host utilities like `limine`, 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
@ -74,7 +86,7 @@ release directory.
In order to build Limine, the following programs have to be installed:
common UNIX tools (also known as `coreutils`),
`GNU make`, `grep`, `sed`, `find`, `awk`, `gzip`, `nasm`, `mtools`
(optional, necessary to build `limine-cd-efi.bin`).
(optional, necessary to build `limine-uefi-cd.bin`).
Furthermore, `gcc` or `llvm/clang` must also be installed, alongside
the respective binutils.
@ -92,11 +104,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,92 +132,107 @@ 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),
run `limine-deploy` as such:
run `limine bios-install` as such:
```bash
limine-deploy <path to device/image>
limine bios-install <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-bios.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
installation:
* Specifying a dedicated stage 2 partition.
* Letting `limine-deploy` attempt to embed stage 2 within GPT structures.
* Letting `limine bios-install` attempt to embed stage 2 within GPT structures.
In case one wants to specify a stage 2 partition, create a partition on the GPT
device of at least 32KiB in size, and pass the 1-based number of the partition
to `limine-deploy` as a second argument; such as:
to `limine bios-install` as a second argument; such as:
```bash
limine-deploy <path to device/image> <1-based stage 2 partition number>
limine bios-install <path to device/image> <1-based stage 2 partition number>
```
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
In case one wants to let `limine bios-install` embed stage 2 within GPT's structures,
simply omit the partition number, and invoke `limine bios-install` 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-bios.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
`limine-uefi-cd.bin`, `limine-bios-cd.bin`, `limine-bios.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-bios.sys` and `limine.cfg` must either be in the root, `limine`, `boot`, or
`boot/limine` directory; `limine-uefi-cd.bin` and `limine-bios-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:
```
xorriso -as mkisofs -b <relative path of limine-cd.bin> \
xorriso -as mkisofs -b <relative path of limine-bios-cd.bin> \
-no-emul-boot -boot-load-size 4 -boot-info-table \
--efi-boot <relative path of limine-cd-efi.bin> \
--efi-boot <relative path of limine-uefi-cd.bin> \
-efi-boot-part --efi-boot-image --protective-msdos-label \
<root directory> -o image.iso
```
*Note: `xorriso` is required.*
And do not forget to also run `limine-deploy` on the generated image:
And do not forget to also run `limine bios-install` on the generated image:
```
limine-deploy image.iso
limine bios-install image.iso
```
`<relative path of limine-cd.bin>` is the relative path of
`limine-cd.bin` inside the root directory.
For example, if it was copied in `<root directory>/boot/limine-cd.bin`,
it would be `boot/limine-cd.bin`.
`<relative path of limine-bios-cd.bin>` is the relative path of
`limine-bios-cd.bin` inside the root directory.
For example, if it was copied in `<root directory>/boot/limine-bios-cd.bin`,
it would be `boot/limine-bios-cd.bin`.
`<relative path of limine-cd-efi.bin>` is the relative path of
`limine-cd-efi.bin` inside the root directory.
`<relative path of limine-uefi-cd.bin>` is the relative path of
`limine-uefi-cd.bin` inside the root directory.
For example, if it was copied in
`<root directory>/boot/limine-cd-efi.bin`, it would be
`boot/limine-cd-efi.bin`.
`<root directory>/boot/limine-uefi-cd.bin`, it would be
`boot/limine-uefi-cd.bin`.
### BIOS/PXE boot
The `limine-pxe.bin` binary is a valid PXE boot image.
The `limine-bios-pxe.bin` binary is a valid PXE boot image.
In order to boot Limine from PXE it is necessary to setup a DHCP server with
support for PXE booting. This can either be accomplished using a single DHCP
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.
`limine.cfg` and `limine-bios.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-bios.sys` file is not needed on the server.
### Configuration
The `limine.cfg` file contains Limine's configuration.
@ -217,7 +242,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,28 @@ 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
AUTOMAKE_LIBDIR="$(automake --print-libdir)"
cp "${AUTOMAKE_LIBDIR}/INSTALL" ./
mkdir -p build-aux
cp "${automake_libdir}/install-sh" build-aux
cp "${AUTOMAKE_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,20 @@ 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 \
$(WERROR_FLAG) \
-std=gnu11 \
-nostdinc \
-ffreestanding \
@ -43,85 +43,118 @@ 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 += \
ifeq ($(TARGET),uefi-riscv64)
override CFLAGS_FOR_TARGET += \
-fPIE \
-fshort-wchar
ifeq ($(CC_FOR_TARGET_IS_CLANG),yes)
override CFLAGS_FOR_TARGET += -march=rv64imac
else
override CFLAGS_FOR_TARGET += -march=rv64imac_zicsr_zifencei
endif
override CFLAGS_FOR_TARGET += \
-mabi=lp64 \
-mno-relax
override CPPFLAGS_FOR_TARGET := \
-I'$(call SHESCAPE,$(BUILDDIR))/limine-efi/inc' \
-I'$(call SHESCAPE,$(BUILDDIR))/limine-efi/inc/riscv64' \
$(CPPFLAGS_FOR_TARGET) \
-DUEFI \
-D__riscv64
endif
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 +163,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 +172,7 @@ ifeq ($(TARGET),uefi-ia32)
endif
ifeq ($(TARGET),uefi-aarch64)
override CROSS_LDFLAGS += \
override LDFLAGS_FOR_TARGET += \
-m aarch64elf \
-static \
-pie \
@ -147,6 +180,16 @@ ifeq ($(TARGET),uefi-aarch64)
-z text
endif
ifeq ($(TARGET),uefi-riscv64)
override LDFLAGS_FOR_TARGET += \
-m elf64lriscv \
--no-relax \
-static \
-pie \
--no-dynamic-linker \
-z text
endif
override C_FILES := $(shell find . -type f -name '*.c')
ifeq ($(TARGET),bios)
override ASMX86_FILES := $(shell find . -type f -name '*.asm_x86')
@ -176,101 +219,119 @@ ifeq ($(TARGET),uefi-aarch64)
override OBJ := $(addprefix $(call MKESCAPE,$(BUILDDIR))/, $(C_FILES:.c=.o) $(ASM64_FILES:.asm_aarch64=.o) $(ASM64U_FILES:.asm_uefi_aarch64=.o))
endif
ifeq ($(TARGET),uefi-riscv64)
override ASM64_FILES := $(shell find . -type f -name '*.asm_riscv64')
override ASM64U_FILES := $(shell find . -type f -name '*.asm_uefi_riscv64')
override OBJ := $(addprefix $(call MKESCAPE,$(BUILDDIR))/, $(C_FILES:.c=.o) $(ASM64_FILES:.asm_riscv64=.o) $(ASM64U_FILES:.asm_uefi_riscv64=.o))
endif
override HEADER_DEPS := $(addprefix $(call MKESCAPE,$(BUILDDIR))/, $(C_FILES:.c=.d))
.PHONY: all
ifeq ($(TARGET),bios)
all: $(call MKESCAPE,$(BUILDDIR))/limine.sys $(call MKESCAPE,$(BUILDDIR))/stage2.bin.gz
all: $(call MKESCAPE,$(BUILDDIR))/limine-bios.sys $(call MKESCAPE,$(BUILDDIR))/stage2.bin.gz
else ifeq ($(TARGET),uefi-x86-64)
all: $(call MKESCAPE,$(BUILDDIR))/BOOTX64.EFI
else ifeq ($(TARGET),uefi-ia32)
all: $(call MKESCAPE,$(BUILDDIR))/BOOTIA32.EFI
else ifeq ($(TARGET),uefi-aarch64)
all: $(call MKESCAPE,$(BUILDDIR))/BOOTAA64.EFI
else ifeq ($(TARGET),uefi-riscv64)
all: $(call MKESCAPE,$(BUILDDIR))/BOOTRISCV64.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
$(call MKESCAPE,$(BUILDDIR))/stage2.bin: $(call MKESCAPE,$(BUILDDIR))/limine-bios.sys
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-bios.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 +344,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 +390,89 @@ 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-riscv64)
$(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'
$(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))/BOOTRISCV64.EFI: $(call MKESCAPE,$(BUILDDIR))/limine.elf
$(OBJCOPY_FOR_TARGET) -O binary '$(call SHESCAPE,$<)' '$(call SHESCAPE,$@)'
chmod -x '$(call SHESCAPE,$@)'
$(call MKESCAPE,$(BUILDDIR))/limine-efi/gnuefi/crt0-efi-riscv64.S.o: limine-efi
$(call MKESCAPE,$(BUILDDIR))/limine-efi/gnuefi/reloc_riscv64.c.o: limine-efi
.PHONY: limine-efi
limine-efi: $(call MKESCAPE,$(BUILDDIR))/limine-efi
$(MAKE) -C '$(call SHESCAPE,$(BUILDDIR))/limine-efi/gnuefi' \
CC="$(CC_FOR_TARGET)" \
CFLAGS="$(BASE_CFLAGS)" \
CPPFLAGS='-nostdinc -I$(call SHESCAPE,$(SRCDIR))/../freestanding-headers' \
ARCH=riscv64
$(call MKESCAPE,$(BUILDDIR))/linker_nomap.ld: linker_uefi_riscv64.ld.in
$(MKDIR_P) '$(call SHESCAPE,$(BUILDDIR))'
$(CC_FOR_TARGET) -x c -E -P -undef -DLINKER_NOMAP linker_uefi_riscv64.ld.in -o '$(call SHESCAPE,$(BUILDDIR))/linker_nomap.ld'
$(call MKESCAPE,$(BUILDDIR))/limine_nomap.elf: $(call MKESCAPE,$(BUILDDIR))/limine-efi/gnuefi/crt0-efi-riscv64.S.o $(call MKESCAPE,$(BUILDDIR))/limine-efi/gnuefi/reloc_riscv64.c.o $(OBJ) ../libgcc-binaries/libgcc-riscv64-softfloat.a
$(MAKE) '$(call SHESCAPE,$(BUILDDIR))/linker_nomap.ld'
$(LD_FOR_TARGET) \
-T'$(call SHESCAPE,$(BUILDDIR))/linker_nomap.ld' \
'$(call OBJESCAPE,$^)' $(LDFLAGS_FOR_TARGET) -o '$(call SHESCAPE,$@)'
$(call MKESCAPE,$(BUILDDIR))/linker.ld: linker_uefi_riscv64.ld.in
$(MKDIR_P) '$(call SHESCAPE,$(BUILDDIR))'
$(CC_FOR_TARGET) -x c -E -P -undef linker_uefi_riscv64.ld.in -o '$(call SHESCAPE,$(BUILDDIR))/linker.ld'
$(call MKESCAPE,$(BUILDDIR))/limine.elf: $(call MKESCAPE,$(BUILDDIR))/limine-efi/gnuefi/crt0-efi-riscv64.S.o $(call MKESCAPE,$(BUILDDIR))/limine-efi/gnuefi/reloc_riscv64.c.o $(OBJ) ../libgcc-binaries/libgcc-riscv64-softfloat.a $(call MKESCAPE,$(BUILDDIR))/full.map.o
$(MAKE) '$(call SHESCAPE,$(BUILDDIR))/linker.ld'
$(LD_FOR_TARGET) \
-T'$(call SHESCAPE,$(BUILDDIR))/linker.ld' \
'$(call OBJESCAPE,$^)' $(LDFLAGS_FOR_TARGET) -o '$(call SHESCAPE,$@)'
endif
ifeq ($(TARGET),uefi-ia32)
@ -364,66 +480,77 @@ 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-riscv64)
$(call MKESCAPE,$(BUILDDIR))/%.o: %.c $(call MKESCAPE,$(BUILDDIR))/limine-efi
$(MKDIR_P) "$$(dirname '$(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 +558,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 +566,61 @@ 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-riscv64)
$(call MKESCAPE,$(BUILDDIR))/%.o: %.asm_riscv64
$(MKDIR_P) "$$(dirname '$(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_riscv64
$(MKDIR_P) "$$(dirname '$(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

@ -0,0 +1,11 @@
.section .text
.global efi_main
.extern uefi_entry
efi_main:
.option norelax
mv fp, zero
mv ra, zero
j 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 [rsp], rax
jmp uefi_entry
section .note.GNU-stack noalloc noexec nowrite progbits

View File

@ -32,7 +32,7 @@ bool stage3_loaded = false;
static bool stage3_found = false;
extern symbol stage3_addr;
extern symbol limine_sys_size;
extern symbol limine_bios_sys_size;
extern symbol build_id_s2;
extern symbol build_id_s3;
@ -41,8 +41,10 @@ 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) {
if ((stage3 = fopen(part, "/limine-bios.sys")) == NULL
&& (stage3 = fopen(part, "/limine/limine-bios.sys")) == NULL
&& (stage3 = fopen(part, "/boot/limine-bios.sys")) == NULL
&& (stage3 = fopen(part, "/boot/limine/limine-bios.sys")) == NULL) {
case_insensitive_fopen = old_cif;
return false;
}
@ -50,19 +52,19 @@ static bool stage3_init(struct volume *part) {
stage3_found = true;
if (stage3->size != (size_t)limine_sys_size) {
print("limine.sys size incorrect.\n");
if (stage3->size != (size_t)limine_bios_sys_size) {
print("limine-bios.sys size incorrect.\n");
return false;
}
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);
if (memcmp(build_id_s2 + 16, build_id_s3 + 16, 20) != 0) {
print("limine.sys build ID mismatch.\n");
print("limine-bios.sys build ID mismatch.\n");
return false;
}
@ -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-bios.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

@ -22,11 +22,12 @@
#include <drivers/disk.h>
#include <sys/lapic.h>
#include <lib/readline.h>
#include <sys/cpu.h>
void stage3_common(void);
#if defined (UEFI)
extern symbol __image_base;
extern symbol __slide;
noreturn void uefi_entry(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) {
gST = SystemTable;
@ -36,23 +37,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 +63,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 +75,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 +95,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 +109,41 @@ 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
#if defined (__riscv)
#if defined (UEFI)
RISCV_EFI_BOOT_PROTOCOL *rv_proto = get_riscv_boot_protocol();
if (rv_proto == NULL || rv_proto->GetBootHartId(rv_proto, &bsp_hartid) != EFI_SUCCESS) {
panic(false, "failed to get BSP's hartid");
}
#else
#error riscv: only UEFI is supported
#endif
init_riscv();
#endif
term_notready();
menu(true);
}

View File

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

View File

@ -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,29 @@ 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");
#elif defined (__riscv64)
strcpy(arch_macro->value, "riscv64");
#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)) {
@ -218,10 +253,17 @@ int init_config(size_t config_size) {
panic(true, "config: Malformed macro usage");
}
}
if (config_addr[i] != '=') {
if (config_addr[i++] != '=') {
i = orig_i;
goto next;
}
while (config_addr[i] != '\n' && config_addr[i] != 0) {
i++;
if (i >= config_size) {
bad_config = true;
panic(true, "config: Malformed macro usage");
}
}
continue;
}

View File

@ -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,16 +20,22 @@
#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
#define ARCH_X86_32 0x03
#define ARCH_AARCH64 0xb7
#define ARCH_RISCV 0xf3
#define BITS_LE 0x01
#define ELFCLASS64 0x02
#define ET_DYN 0x0003
#define SHT_RELA 0x00000004
#define R_X86_64_RELATIVE 0x00000008
#define R_AARCH64_RELATIVE 0x00000403
#define R_RISCV_RELATIVE 0x00000003
/* Indices into identification array */
#define EI_CLASS 4
@ -76,19 +82,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;
@ -113,6 +106,8 @@ int elf_bits(uint8_t *elf) {
case ARCH_X86_64:
case ARCH_AARCH64:
return 64;
case ARCH_RISCV:
return (hdr->ident[EI_CLASS] == ELFCLASS64) ? 64 : 32;
case ARCH_X86_32:
return 32;
default:
@ -163,6 +158,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;
}
@ -231,6 +231,8 @@ static bool elf64_apply_relocations(uint8_t *elf, struct elf64_hdr *hdr, void *b
case R_X86_64_RELATIVE:
#elif defined (__aarch64__)
case R_AARCH64_RELATIVE:
#elif defined (__riscv64)
case R_RISCV_RELATIVE:
#else
#error Unknown architecture
#endif
@ -278,7 +280,7 @@ bool elf64_load_section(uint8_t *elf, void *buffer, const char *name, size_t lim
#if defined (__x86_64__) || defined (__i386__)
if (hdr->machine != ARCH_X86_64) {
printv("elf: Not an x86_64 ELF file.\n");
printv("elf: Not an x86-64 ELF file.\n");
return false;
}
#elif defined (__aarch64__)
@ -286,10 +288,19 @@ bool elf64_load_section(uint8_t *elf, void *buffer, const char *name, size_t lim
printv("elf: Not an aarch64 ELF file.\n");
return false;
}
#elif defined (__riscv64)
if (hdr->machine != ARCH_RISCV && hdr->ident[EI_CLASS] == ELFCLASS64) {
printv("elf: Not a riscv64 ELF file.\n");
return false;
}
#else
#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 +412,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,12 +426,16 @@ 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) {
panic(true, "elf: Not an aarch64 ELF file.\n");
}
#elif defined (__riscv64)
if (hdr->machine != ARCH_RISCV && hdr->ident[EI_CLASS] == ELFCLASS64) {
panic(true, "elf: Not a riscv64 ELF file.\n");
}
#else
#error Unknown architecture
#endif
@ -457,6 +472,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 +544,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 +555,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 +587,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 +706,7 @@ bool elf64_load_elsewhere(uint8_t *elf, uint64_t *entry_point,
}
if (hdr->machine != ARCH_X86_64) {
printv("elf: Not an x86_64 ELF file.\n");
printv("elf: Not an x86-64 ELF file.\n");
return false;
}

View File

@ -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) {
@ -168,9 +110,47 @@ uint32_t hex2bin(uint8_t *str, uint32_t size) {
#if defined (UEFI)
no_unwind bool efi_boot_services_exited = false;
#if defined (__riscv)
#define EFI_COPY_MAX_ENTRIES 512
RISCV_EFI_BOOT_PROTOCOL *get_riscv_boot_protocol(void) {
EFI_GUID boot_proto_guid = RISCV_EFI_BOOT_PROTOCOL_GUID;
RISCV_EFI_BOOT_PROTOCOL *proto;
// LocateProtocol() is available from EFI version 1.1
if (gBS->Hdr.Revision >= ((1 << 16) | 10)) {
if (gBS->LocateProtocol(&boot_proto_guid, NULL, (void **)&proto) == EFI_SUCCESS) {
return proto;
}
}
UINTN bufsz = 0;
if (gBS->LocateHandle(ByProtocol, &boot_proto_guid, NULL, &bufsz, NULL) != EFI_BUFFER_TOO_SMALL)
return NULL;
EFI_HANDLE *handles_buf = ext_mem_alloc(bufsz);
if (handles_buf == NULL)
return NULL;
if (bufsz < sizeof(EFI_HANDLE))
goto error;
if (gBS->LocateHandle(ByProtocol, &boot_proto_guid, NULL, &bufsz, handles_buf) != EFI_SUCCESS)
goto error;
if (gBS->HandleProtocol(handles_buf[0], &boot_proto_guid, (void **)&proto) != EFI_SUCCESS)
goto error;
pmm_free(handles_buf, bufsz);
return proto;
error:
pmm_free(handles_buf, bufsz);
return NULL;
}
#endif
no_unwind bool efi_boot_services_exited = false;
bool efi_exit_boot_services(void) {
EFI_STATUS status;
@ -193,6 +173,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:
@ -215,10 +203,107 @@ retry:
asm volatile ("cli" ::: "memory");
#elif defined (__aarch64__)
asm volatile ("msr daifset, #15" ::: "memory");
#elif defined (__riscv64)
asm volatile ("csrci sstatus, 0x2" ::: "memory");
#else
#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

@ -10,6 +10,9 @@
#include <lib/libc.h>
#if defined (UEFI)
# include <efi.h>
# if defined (__riscv64)
# include <protocol/riscv/efiboot.h>
# endif
#endif
#if defined (UEFI)
@ -33,14 +36,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);
@ -59,7 +60,7 @@ uint64_t strtoui(const char *s, const char **end, int base);
#if defined (__i386__)
void memcpy32to64(uint64_t, uint64_t, uint64_t);
#elif defined (__x86_64__) || defined (__aarch64__)
#elif defined (__x86_64__) || defined (__aarch64__) || defined(__riscv64)
# define memcpy32to64(X, Y, Z) memcpy((void *)(uintptr_t)(X), (void *)(uintptr_t)(Y), Z)
#else
#error Unknown architecture
@ -94,12 +95,14 @@ 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);
#elif defined (__riscv64)
noreturn void riscv_spinup(uint64_t entry, uint64_t sp, uint64_t satp);
#if defined (UEFI)
RISCV_EFI_BOOT_PROTOCOL *get_riscv_boot_protocol(void);
#endif
#else
#error Unknown architecture
#endif

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);
@ -85,7 +74,7 @@ nested:
for (;;) {
#if defined (__x86_64__) || defined (__i386__)
asm ("hlt");
#elif defined (__aarch64__)
#elif defined (__aarch64__) || defined (__riscv64)
asm ("wfi");
#else
#error Unknown architecture

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

@ -0,0 +1,47 @@
.section .text
.global riscv_spinup
riscv_spinup:
.option norelax
csrci sstatus, 0x2
csrw sie, zero
csrw stvec, zero
mv t0, a0
mv sp, a1
csrw satp, a2
mv a0, zero
mv a1, zero
mv a2, zero
mv a3, zero
mv a4, zero
mv a5, zero
mv a6, zero
mv a7, zero
mv s0, zero
mv s1, zero
mv s2, zero
mv s3, zero
mv s4, zero
mv s5, zero
mv s6, zero
mv s7, zero
mv s8, zero
mv s9, zero
mv s10, zero
mv s11, zero
mv t1, zero
mv t2, zero
mv t3, zero
mv t4, zero
mv t5, zero
mv t6, zero
mv tp, zero
mv gp, zero
mv ra, zero
jr t0
.section .note.GNU-stack,"",%progbits

View File

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

View File

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

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;
@ -54,6 +54,8 @@ void print_stacktrace(size_t *base_ptr) {
"movq %%rbp, %0"
#elif defined (__aarch64__)
"mov %0, x29"
#elif defined (__riscv64)
"mv %0, fp; addi %0, %0, -16"
#endif
: "=r"(base_ptr)
:: "memory"
@ -73,7 +75,11 @@ void print_stacktrace(size_t *base_ptr) {
print(" [%p]\n", ret_addr);
if (!old_bp)
break;
#if defined (__riscv)
base_ptr = (void *)(old_bp - 16);
#else
base_ptr = (void*)old_bp;
#endif
}
print("End of trace. ");
}

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

@ -0,0 +1,81 @@
OUTPUT_FORMAT(elf64-littleriscv)
OUTPUT_ARCH(riscv:rv64)
ENTRY(_start)
PHDRS
{
text PT_LOAD FLAGS((1 << 0) | (1 << 2)) ;
rodata PT_LOAD FLAGS((1 << 2)) ;
data PT_LOAD FLAGS((1 << 1) | (1 << 2)) ;
dynamic PT_DYNAMIC FLAGS((1 << 1) | (1 << 2)) ;
}
SECTIONS
{
. = 0;
__slide = .;
__image_base = ABSOLUTE(.);
__image_size = ABSOLUTE(__image_end - __image_base);
.text : {
*(.pe_header)
. = ALIGN(0x1000);
__text_start = ABSOLUTE(.);
*(.text .text.*)
} :text
. = ALIGN(0x1000);
__text_end = ABSOLUTE(.);
__text_size = ABSOLUTE(__text_end - __text_start);
.rodata : {
__reloc_start = ABSOLUTE(.);
*(.dummy_reloc)
. = ALIGN(0x1000);
__reloc_end = ABSOLUTE(.);
__reloc_size = ABSOLUTE(__reloc_end - __reloc_start);
__data_start = ABSOLUTE(.);
*(.rodata .rodata.*)
#ifdef LINKER_NOMAP
full_map = .;
#else
*(.full_map)
#endif
} :rodata
.data : {
data_begin = .;
*(.data .data.*)
*(.sdata .sdata.*)
*(.sbss .sbss.*)
*(.bss .bss.*)
*(COMMON)
data_end = .;
*(.no_unwind)
} :data
.got : {
*(.got .got.*)
} :data
.dynamic : {
*(.dynamic)
. = ALIGN(0x1000);
} :data :dynamic
__data_end = ABSOLUTE(.);
__data_size = ABSOLUTE(__data_end - __data_start);
__image_end = ABSOLUTE(.);
/DISCARD/ : {
*(.eh_frame)
*(.note .note.*)
}
}

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
print("TODO: Linux is not available on aarch64.\n\n");
quiet = false;
print("TODO: Linux is not available on aarch64 or riscv64.\n\n");
#endif
} else if (!strcmp(proto, "multiboot1") || !strcmp(proto, "multiboot")) {
#if defined (__x86_64__) || defined (__i386__)
multiboot1_load(config, cmdline);
#else
print("Multiboot 1 is not available on aarch64.\n\n");
quiet = false;
print("Multiboot 1 is not available on aarch64 or riscv64.\n\n");
#endif
} else if (!strcmp(proto, "multiboot2")) {
#if defined (__x86_64__) || defined (__i386__)
multiboot2_load(config, cmdline);
#else
print("Multiboot 2 is not available on aarch64.\n\n");
quiet = false;
print("Multiboot 2 is not available on aarch64 or riscv64.\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

@ -0,0 +1,24 @@
.section .data
.p2align 3
stack_at_first_entry:
.8byte 0
.section .text
.global menu
.extern _menu
menu:
.option norelax
lla t0, stack_at_first_entry
ld t1, (t0)
beqz t1, 1f
mv sp, t1
j 2f
1: sd sp, (t0)
2: mv fp, zero
mv ra, zero
j _menu
.section .note.GNU-stack,"",%progbits

View File

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

View File

@ -22,6 +22,8 @@ struct memmap_entry {
#define MEMMAP_FRAMEBUFFER 0x1002
#define MEMMAP_EFI_RECLAIMABLE 0x2000
#define MEMMAP_MAX 512
struct meminfo {
size_t uppermem;
size_t lowermem;
@ -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;
@ -221,6 +243,152 @@ level4:
pml1[pml1_entry] = (pt_entry_t)(phys_addr | real_flags | PT_FLAG_4K_PAGE);
}
#elif defined (__riscv64)
#define PT_FLAG_VALID ((uint64_t)1 << 0)
#define PT_FLAG_READ ((uint64_t)1 << 1)
#define PT_FLAG_WRITE ((uint64_t)1 << 2)
#define PT_FLAG_EXEC ((uint64_t)1 << 3)
#define PT_FLAG_USER ((uint64_t)1 << 4)
#define PT_FLAG_ACCESSED ((uint64_t)1 << 6)
#define PT_FLAG_DIRTY ((uint64_t)1 << 7)
#define PT_FLAG_PBMT_NC ((uint64_t)1 << 62)
#define PT_PADDR_MASK ((uint64_t)0x003ffffffffffc00)
#define PT_FLAG_RWX (PT_FLAG_READ | PT_FLAG_WRITE | PT_FLAG_EXEC)
#define PT_TABLE_FLAGS PT_FLAG_VALID
#define PT_IS_TABLE(x) (((x) & (PT_FLAG_VALID | PT_FLAG_RWX)) == PT_FLAG_VALID)
#define PT_IS_LARGE(x) (((x) & (PT_FLAG_VALID | PT_FLAG_RWX)) > PT_FLAG_VALID)
#define PT_TO_VMM_FLAGS(x) (pt_to_vmm_flags_internal(x))
#define pte_new(addr, flags) (((pt_entry_t)(addr) >> 2) | (flags))
#define pte_addr(pte) (((pte) & PT_PADDR_MASK) << 2)
static uint64_t pt_to_vmm_flags_internal(pt_entry_t entry) {
uint64_t flags = 0;
if (entry & PT_FLAG_WRITE)
flags |= VMM_FLAG_WRITE;
if (!(entry & PT_FLAG_EXEC))
flags |= VMM_FLAG_NOEXEC;
if (entry & PT_FLAG_PBMT_NC)
flags |= VMM_FLAG_FB;
return flags;
}
uint64_t paging_mode_higher_half(int paging_mode) {
switch (paging_mode) {
case PAGING_MODE_RISCV_SV39:
return 0xffffffc000000000;
case PAGING_MODE_RISCV_SV48:
return 0xffff800000000000;
case PAGING_MODE_RISCV_SV57:
return 0xff00000000000000;
default:
panic(false, "paging_mode_higher_half: invalid mode");
}
}
int paging_mode_va_bits(int paging_mode) {
switch (paging_mode) {
case PAGING_MODE_RISCV_SV39:
return 39;
case PAGING_MODE_RISCV_SV48:
return 48;
case PAGING_MODE_RISCV_SV57:
return 57;
default:
panic(false, "paging_mode_va_bits: invalid mode");
}
}
int vmm_max_paging_mode(void)
{
static int max_level;
if (max_level > 0)
goto done;
pt_entry_t *table = ext_mem_alloc(PT_SIZE);
// Test each paging mode starting with Sv57.
// Since writes to `satp` with an invalid MODE have no effect, and pages can be mapped at
// any level, we can identity map the entire lower half (very likely guaranteeing everything
// this code needs will be mapped) and check if enabling the paging mode succeeds.
int lvl = 4;
for (; lvl >= 2; lvl--) {
pt_entry_t entry = PT_FLAG_ACCESSED | PT_FLAG_DIRTY | PT_FLAG_RWX | PT_FLAG_VALID;
for (int i = 0; i < 256; i++) {
table[i] = entry;
entry += page_sizes[lvl] >> 2;
}
uint64_t satp = ((uint64_t)(6 + lvl) << 60) | ((uint64_t)table >> 12);
csr_write("satp", satp);
if (csr_read("satp") == satp) {
max_level = lvl;
break;
}
}
csr_write("satp", 0);
pmm_free(table, PT_SIZE);
if (max_level == 0)
panic(false, "vmm: paging is not supported");
done:
return 6 + max_level;
}
static pt_entry_t pbmt_nc = 0;
pagemap_t new_pagemap(int paging_mode) {
pagemap_t pagemap;
pagemap.paging_mode = paging_mode;
pagemap.max_page_size = paging_mode - 6;
pagemap.top_level = ext_mem_alloc(PT_SIZE);
if (riscv_check_isa_extension("svpbmt", NULL, NULL)) {
printv("riscv: Svpbmt extension is supported.\n");
pbmt_nc = PT_FLAG_PBMT_NC;
}
return pagemap;
}
void map_page(pagemap_t pagemap, uint64_t virt_addr, uint64_t phys_addr, uint64_t flags, enum page_size page_size) {
// Truncate the requested page size to the maximum supported.
if (page_size > pagemap.max_page_size)
page_size = pagemap.max_page_size;
// Convert VMM_FLAG_* into PT_FLAG_*.
// Set the ACCESSED and DIRTY flags to avoid faults.
pt_entry_t ptflags = PT_FLAG_VALID | PT_FLAG_READ | PT_FLAG_ACCESSED | PT_FLAG_DIRTY;
if (flags & VMM_FLAG_WRITE)
ptflags |= PT_FLAG_WRITE;
if (!(flags & VMM_FLAG_NOEXEC))
ptflags |= PT_FLAG_EXEC;
if (flags & VMM_FLAG_FB)
ptflags |= pbmt_nc;
// Start at the highest level.
// The values of `enum page_size` map to the level index at which that size is mapped.
int level = pagemap.max_page_size;
pt_entry_t *table = pagemap.top_level;
for (;;) {
int index = (virt_addr >> (12 + 9 * level)) & 0x1ff;
// Stop when we reach the level for the requested page size.
if (level == (int)page_size) {
table[index] = pte_new(phys_addr, ptflags);
break;
}
table = get_next_level(pagemap, table, virt_addr, page_size, level, index);
level--;
}
}
#else
#error Unknown architecture
#endif
@ -231,47 +399,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 +425,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 +434,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];
@ -47,8 +77,45 @@ void vmm_assert_4k_pages(void);
pagemap_t new_pagemap(int lv);
void map_page(pagemap_t pagemap, uint64_t virt_addr, uint64_t phys_addr, uint64_t flags, enum page_size page_size);
#elif defined (__riscv64)
// We use fake flags here because these don't properly map onto the
// RISC-V flags.
#define VMM_FLAG_WRITE ((uint64_t)1 << 0)
#define VMM_FLAG_NOEXEC ((uint64_t)1 << 1)
#define VMM_FLAG_FB ((uint64_t)1 << 2)
#define VMM_MAX_LEVEL 5
#define PAGING_MODE_RISCV_SV39 8
#define PAGING_MODE_RISCV_SV48 9
#define PAGING_MODE_RISCV_SV57 10
int paging_mode_va_bits(int paging_mode);
enum page_size {
Size4KiB,
Size2MiB,
Size1GiB,
Size512GiB,
Size256TiB
};
typedef struct {
enum page_size max_page_size;
int paging_mode;
void *top_level;
} pagemap_t;
uint64_t paging_mode_higher_half(int paging_mode);
int vmm_max_paging_mode(void);
pagemap_t new_pagemap(int paging_mode);
void map_page(pagemap_t pagemap, uint64_t virt_addr, uint64_t phys_addr, uint64_t flags, enum page_size page_size);
#else
#error Unknown architecture
#endif
int vmm_max_paging_mode(void);
#endif

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);

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