Compare commits
430 Commits
v4.x-branc
...
v5.x-branc
Author | SHA1 | Date | |
---|---|---|---|
|
e63d804f6f | ||
|
cad3c72fce | ||
|
7cd46f3d26 | ||
|
f4051f49db | ||
|
a5051f92bf | ||
|
ec564407da | ||
|
a0127f9f40 | ||
|
e49865a467 | ||
|
2bba72634f | ||
|
45b39285f1 | ||
|
a795dc1972 | ||
|
c1860c8d80 | ||
|
49cfba851c | ||
|
b348bb75e7 | ||
|
c1f5b21177 | ||
|
b474b6bad0 | ||
|
5323bce117 | ||
|
1bcbf817ed | ||
|
f81b9d2dc3 | ||
|
d0a1285feb | ||
|
a0c2f95a1d | ||
|
d421ebcb58 | ||
|
7117b85c86 | ||
|
3a81c3e13d | ||
|
a0997a598b | ||
|
212dbd32c1 | ||
|
a55f68b3bd | ||
|
a83dafe6f4 | ||
|
afdc556301 | ||
|
bfc518cc07 | ||
|
81c39fc080 | ||
|
87a88bf565 | ||
|
3fde8f0158 | ||
|
50f4383f93 | ||
|
c7df84e237 | ||
|
f1236373fe | ||
|
a36de776a7 | ||
|
a0fb5a04d3 | ||
|
042a6e9554 | ||
|
c5c43cb0fd | ||
|
5f7bcc0b1d | ||
|
45958f7162 | ||
|
e9b5511084 | ||
|
f4bfe1289a | ||
|
cdac49ebfb | ||
|
90b82dc43f | ||
|
e3d65aa628 | ||
|
f33732a2e5 | ||
|
09c430f286 | ||
|
2200161e7d | ||
|
f8bfe41e71 | ||
|
0f7ee05635 | ||
|
b54c3fc9cc | ||
|
756dd235ea | ||
|
09c87feaee | ||
|
916aa370b2 | ||
|
0ebf0245df | ||
|
8f789fc0ae | ||
|
b5cffbb6e8 | ||
|
9ff62c2a62 | ||
|
68f82c3d30 | ||
|
2642249edd | ||
|
e6a67c80a6 | ||
|
541dbd265c | ||
|
e207c03f69 | ||
|
57e4ae6e25 | ||
|
a30cad3556 | ||
|
ac0d9465f5 | ||
|
f0b899b5bc | ||
|
4abedffb43 | ||
|
50dab6c2f1 | ||
|
ba5d63b82a | ||
|
573d0095bf | ||
|
27a32e416c | ||
|
9a074530a9 | ||
|
a248b557bb | ||
|
d66df6b38a | ||
|
1e9a42e7ce | ||
|
b8fff872de | ||
|
820d4751d3 | ||
|
82ea6d6a57 | ||
|
030242d69a | ||
|
b64335f62a | ||
|
50b8ab2c26 | ||
|
2d0752f60c | ||
|
ff86be6be6 | ||
|
2f1dac0600 | ||
|
0ecb2ab895 | ||
|
474fc105a5 | ||
|
418f8d7280 | ||
|
722bde2cbc | ||
|
5bdb1bbf55 | ||
|
8f167bc2e5 | ||
|
d73cd37834 | ||
|
478b6f3806 | ||
|
4b452e69a4 | ||
|
98f30bfdd6 | ||
|
ba2597605b | ||
|
9921af54d0 | ||
|
a2e502328d | ||
|
dc68fcaff7 | ||
|
f365a46617 | ||
|
871a8053c2 | ||
|
49ecb6b577 | ||
|
997e2c756a | ||
|
bc1896c5bb | ||
|
e261a96fa4 | ||
|
1f82dd89c7 | ||
|
93942a3334 | ||
|
b72d033510 | ||
|
11f50a6aaa | ||
|
79e50a82af | ||
|
17e26c8c95 | ||
|
9333f1ca8b | ||
|
99d671ecf8 | ||
|
7882d89b4e | ||
|
1ad6d6013e | ||
|
2ac43a320f | ||
|
2d6a1e4535 | ||
|
d08ea721a5 | ||
|
6e41938206 | ||
|
67fd1a8d9f | ||
|
66268f7d7f | ||
|
cb14f44eb3 | ||
|
910a0d84a0 | ||
|
2da0a08072 | ||
|
670b635ae8 | ||
|
bc8188e275 | ||
|
38ccb76c40 | ||
|
7b1284808a | ||
|
34a2e85c34 | ||
|
ece02695e8 | ||
|
45fd1ac08f | ||
|
264decd0ef | ||
|
d0b9bbdca6 | ||
|
1c5fde5dc9 | ||
|
a069e220c0 | ||
|
b764792c97 | ||
|
a9e6e00994 | ||
|
2b154138fe | ||
|
cde874fe80 | ||
|
a627c732d5 | ||
|
b78309b45a | ||
|
666c5dfcd1 | ||
|
13042bd25e | ||
|
f6946a7f0c | ||
|
74a6b8e125 | ||
|
705719a229 | ||
|
e205d51ca4 | ||
|
fa7b2409e7 | ||
|
1f01ddfc6d | ||
|
9274ee656e | ||
|
e91196d452 | ||
|
bee1d50c1a | ||
|
fe083d3701 | ||
|
dce1c31ad5 | ||
|
f26b651e5f | ||
|
679fdd4351 | ||
|
4190710dc6 | ||
|
9079f3007d | ||
|
eac03c8c89 | ||
|
0125dcd67a | ||
|
844386487d | ||
|
71b175b7b9 | ||
|
153412f53e | ||
|
7989064599 | ||
|
836d1c2038 | ||
|
2c11fb337c | ||
|
73462a5116 | ||
|
f618eb26af | ||
|
e9186e1859 | ||
|
35808c593e | ||
|
717c60cd6a | ||
|
e0c3e6bdce | ||
|
df34599feb | ||
|
fdcb9a9243 | ||
|
1a4888858b | ||
|
8dd7973e23 | ||
|
36846549e0 | ||
|
172060e249 | ||
|
d7da6d63b5 | ||
|
2362f1a785 | ||
|
2a26d90394 | ||
|
64a0c6073b | ||
|
73b126e067 | ||
|
c41e3969a6 | ||
|
b991fb93f8 | ||
|
e57050d9c7 | ||
|
93ae0e9afc | ||
|
3613997108 | ||
|
eae24e64e5 | ||
|
2da6225f9e | ||
|
a3f84fc4a3 | ||
|
240d9688b0 | ||
|
7ad444936e | ||
|
eba0183b6e | ||
|
ebd1953e51 | ||
|
514522125b | ||
|
3438b8d235 | ||
|
e0f8d94de7 | ||
|
67d2631826 | ||
|
b66184cfbd | ||
|
012605adf9 | ||
|
d0df21abb9 | ||
|
01eeeb6e1d | ||
|
779571339e | ||
|
936240a3c6 | ||
|
a2dd3449a8 | ||
|
42027470c7 | ||
|
45ff0e2e93 | ||
|
d0ee1e7d65 | ||
|
698ca1a665 | ||
|
830251e68e | ||
|
d4334699e3 | ||
|
5a53f91e01 | ||
|
0196abf2ec | ||
|
2ea3f7e9d8 | ||
|
3bf159d81c | ||
|
9663318102 | ||
|
c202cce72c | ||
|
813c1e6c95 | ||
|
fadb9a7c13 | ||
|
7d6125d413 | ||
|
f71f506b0a | ||
|
08647f7d5c | ||
|
c7a7539d23 | ||
|
5f5c98866e | ||
|
7dc04b42cc | ||
|
9009404a11 | ||
|
674f490f7b | ||
|
b072a08f72 | ||
|
8d61d0ab3a | ||
|
d1e4b9946c | ||
|
828e3790a4 | ||
|
ca69475609 | ||
|
246276a538 | ||
|
980c122475 | ||
|
4ef529b4eb | ||
|
5bc6fbca3b | ||
|
fc4e283ad5 | ||
|
0f4beb1bfd | ||
|
9d6c64954c | ||
|
1dd75a18ac | ||
|
8bb12244be | ||
|
753bb820ae | ||
|
5f84ade177 | ||
|
959c44658e | ||
|
11ef3bced2 | ||
|
a786c26a26 | ||
|
8ee9dc1ebd | ||
|
d17e220e61 | ||
|
9bcad9d258 | ||
|
b4649f8808 | ||
|
1e65ada438 | ||
|
c924d7b7e5 | ||
|
ce7a552723 | ||
|
c7f344784c | ||
|
48053fd206 | ||
|
e909489635 | ||
|
a3f814b5f7 | ||
|
3ae87be595 | ||
|
9b07351208 | ||
|
82aec4b1b2 | ||
|
143d3d85de | ||
|
1099993b14 | ||
|
71b3ae548b | ||
|
caaf4f94a5 | ||
|
bcac8b6256 | ||
|
d744fc8c63 | ||
|
ec34c86d58 | ||
|
8b7dc549f7 | ||
|
7e46840b86 | ||
|
87bea2fe0d | ||
|
8d427d7699 | ||
|
cd8188d832 | ||
|
fb4b02a451 | ||
|
8c7655eacd | ||
|
c30afde043 | ||
|
843be07536 | ||
|
8c7a98310a | ||
|
191ad51eaa | ||
|
5c1b96b393 | ||
|
a7721872dd | ||
|
28dd8a1062 | ||
|
2091aa9c21 | ||
|
41d4b3af54 | ||
|
3dd0a6fb41 | ||
|
ac1c5d1b95 | ||
|
a085af55ec | ||
|
8caf7b5b75 | ||
|
a0d8c7b2ab | ||
|
2ee939725e | ||
|
1aba6b3aeb | ||
|
10bbba0066 | ||
|
b3c08f8122 | ||
|
fc6b69f0ac | ||
|
382d88913d | ||
|
040a15817f | ||
|
98bfcc6dbd | ||
|
6df8a35698 | ||
|
3fc36e9ac1 | ||
|
25c6c18c8b | ||
|
0748cf5bf2 | ||
|
a48036141f | ||
|
ba5aca6fd8 | ||
|
32d7aa1815 | ||
|
04d22b1e52 | ||
|
ffaaabf14a | ||
|
c2854bde82 | ||
|
f9399fd5a3 | ||
|
15127263ca | ||
|
d39baeaa80 | ||
|
28187433f9 | ||
|
9b68f081cf | ||
|
bf4c0f7d7a | ||
|
99f8c7b187 | ||
|
e924aa5f26 | ||
|
970292460d | ||
|
60c115658c | ||
|
20572082c1 | ||
|
07d8dd2c68 | ||
|
c477414c5c | ||
|
d82dc64b93 | ||
|
22c041ff08 | ||
|
1258f01bc2 | ||
|
144c481ed5 | ||
|
7e403e0059 | ||
|
ae771dd8a1 | ||
|
49f4ccd312 | ||
|
09faf82bc4 | ||
|
d8193abc98 | ||
|
ce4046d559 | ||
|
7e1d4a9870 | ||
|
3c541576f3 | ||
|
c7e62083fd | ||
|
f0d6aa8033 | ||
|
c14bb6059f | ||
|
e0aec79cb6 | ||
|
01ee09373c | ||
|
502f77b30f | ||
|
42b1db1063 | ||
|
b30d2dc978 | ||
|
da5896b764 | ||
|
6022f5bf23 | ||
|
96fe1aa2e0 | ||
|
d265cad7b6 | ||
|
ce33e9dff3 | ||
|
fa40b927cd | ||
|
d10d2baded | ||
|
af80341c8c | ||
|
53d20619ec | ||
|
2557aa8f46 | ||
|
4ba1b2fd9d | ||
|
3d95c8960c | ||
|
23f2c7dbac | ||
|
02c26a8738 | ||
|
b1319408dd | ||
|
7f09259c57 | ||
|
610a98d8b2 | ||
|
6e1c792e41 | ||
|
fb994e61c6 | ||
|
44a3f3f2f7 | ||
|
68e936e7f4 | ||
|
ac34ec411f | ||
|
ec9d384bf2 | ||
|
cc8ff90865 | ||
|
6cbb9c4577 | ||
|
ffa6d4e0c7 | ||
|
d187c576d8 | ||
|
ff8c5f318c | ||
|
f977548e84 | ||
|
48a7c12e5b | ||
|
d3c8a66918 | ||
|
b34954bb43 | ||
|
45312e66ae | ||
|
f6ba5991b5 | ||
|
0f1d86e7e4 | ||
|
8849d08eeb | ||
|
4d855fc17e | ||
|
e466501f92 | ||
|
96c184fdf6 | ||
|
7f046f67b9 | ||
|
e5d786158f | ||
|
0d7b1e1148 | ||
|
00e9f2ce46 | ||
|
a2ba71eb1d | ||
|
c849bfc10b | ||
|
bd7c3602bb | ||
|
97c928a354 | ||
|
64c897a82d | ||
|
714d8ac2ce | ||
|
4a4409e1b2 | ||
|
0cb98610f0 | ||
|
e062b4ed7d | ||
|
e67a75fe09 | ||
|
34a53292f7 | ||
|
b9f41799b4 | ||
|
390372533f | ||
|
b229d0cdf3 | ||
|
0a28a0959b | ||
|
dab2a35b3e | ||
|
d5ff44676b | ||
|
b1bfa2d2d8 | ||
|
a6189abdc1 | ||
|
e89d834457 | ||
|
87e09dba61 | ||
|
59bbd1f657 | ||
|
26f6ac3bb2 | ||
|
dc5ed66e67 | ||
|
f86a421209 | ||
|
0ae552a25c | ||
|
7f14f2f0d0 | ||
|
e76c8d47a9 | ||
|
50b524838a | ||
|
886523359c | ||
|
430e841903 | ||
|
708868c889 | ||
|
a95d475c89 | ||
|
2b71eaedb6 | ||
|
0f04f6860a | ||
|
7e6aad3113 | ||
|
ae4605936a | ||
|
c1e98f26c9 | ||
|
9680a1ad51 | ||
|
71eb143611 | ||
|
a1bcf3c09b | ||
|
8906518cd2 | ||
|
f8d714317b | ||
|
528be7230f | ||
|
82eb809111 |
26
.github/ISSUE_TEMPLATE/bug_report.md
vendored
26
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@ -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.
|
15
.github/workflows/check.yml
vendored
15
.github/workflows/check.yml
vendored
@ -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
|
||||
|
33
.github/workflows/release.yml
vendored
33
.github/workflows/release.yml
vendored
@ -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
11
.gitignore
vendored
@ -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
|
||||
|
25
CONFIG.md
25
CONFIG.md
@ -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`.
|
||||
|
@ -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:
|
||||
|
542
GNUmakefile.in
542
GNUmakefile.in
@ -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
31
PHILOSOPHY.md
Normal 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.
|
364
PROTOCOL.md
364
PROTOCOL.md
@ -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
143
README.md
@ -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,
|
||||
|
28
bootstrap
28
bootstrap
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
8
common/compress/gzip.h
Normal 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
|
@ -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
209
common/crypt/blake2b.c
Normal 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 *)¶m + 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
10
common/crypt/blake2b.h
Normal 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
|
@ -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++;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
11
common/efi_thunk.asm_uefi_riscv64
Normal file
11
common/efi_thunk.asm_uefi_riscv64
Normal 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
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
BIN
common/font.bin
BIN
common/font.bin
Binary file not shown.
@ -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) {
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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"
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
}
|
@ -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
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
104
common/lib/elf.c
104
common/lib/elf.c
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
1164
common/lib/gterm.c
1164
common/lib/gterm.c
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -5,7 +5,6 @@
|
||||
#include <fs/file.h>
|
||||
|
||||
struct image {
|
||||
size_t allocated_size;
|
||||
size_t x_size;
|
||||
size_t y_size;
|
||||
int type;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
@ -53,3 +53,5 @@ memcmp:
|
||||
|
||||
.done:
|
||||
ret
|
||||
|
||||
section .note.GNU-stack noalloc noexec nowrite progbits
|
||||
|
@ -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
57
common/lib/memory.s2.c
Normal 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
|
@ -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");
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -164,3 +164,5 @@ align 16
|
||||
.idt: dq 0
|
||||
.rm_idt: dw 0x3ff
|
||||
dd 0
|
||||
|
||||
section .note.GNU-stack noalloc noexec nowrite progbits
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -35,3 +35,5 @@ common_spinup:
|
||||
mov cr4, eax
|
||||
|
||||
call edi
|
||||
|
||||
section .note.GNU-stack noalloc noexec nowrite progbits
|
||||
|
47
common/lib/spinup.asm_riscv64
Normal file
47
common/lib/spinup.asm_riscv64
Normal 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
|
@ -60,3 +60,5 @@ common_spinup:
|
||||
mov cr4, eax
|
||||
|
||||
call edi
|
||||
|
||||
section .note.GNU-stack noalloc noexec nowrite progbits
|
||||
|
@ -93,3 +93,5 @@ bits 32
|
||||
mov cr4, eax
|
||||
|
||||
call edi
|
||||
|
||||
section .note.GNU-stack noalloc noexec nowrite progbits
|
||||
|
1393
common/lib/term.c
1393
common/lib/term.c
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
|
@ -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;
|
||||
}
|
@ -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);
|
||||
|
@ -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. ");
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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/ : {
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
81
common/linker_uefi_riscv64.ld.in
Normal file
81
common/linker_uefi_riscv64.ld.in
Normal 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.*)
|
||||
}
|
||||
}
|
@ -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)
|
||||
|
405
common/menu.c
405
common/menu.c
@ -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.");
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -23,3 +23,5 @@ menu:
|
||||
mov x29, xzr
|
||||
|
||||
b _menu
|
||||
|
||||
.section .note.GNU-stack,"",%progbits
|
||||
|
@ -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
|
||||
|
24
common/menu_thunk.asm_riscv64
Normal file
24
common/menu_thunk.asm_riscv64
Normal 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
|
@ -19,3 +19,5 @@ menu:
|
||||
push 0
|
||||
push 0
|
||||
jmp _menu
|
||||
|
||||
section .note.GNU-stack noalloc noexec nowrite progbits
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
220
common/mm/vmm.c
220
common/mm/vmm.c
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user