mirror of
https://github.com/EnderIce2/Fennix.git
synced 2025-07-01 10:29:16 +00:00
Compare commits
411 Commits
04edfd46bb
...
nightly
Author | SHA1 | Date | |
---|---|---|---|
2c1d6c2608
|
|||
97a892d114
|
|||
3be150da53
|
|||
455224ceb4
|
|||
e01f1dc97c
|
|||
76113df5a9
|
|||
1addd310ad
|
|||
3d92a87bef
|
|||
f7177f92cf
|
|||
6a6c3bfc67
|
|||
8dbeee4d9a
|
|||
5d5b674aed
|
|||
31bbc29c9f
|
|||
f5c8ae9323
|
|||
154d857c2e
|
|||
12ae5a83da
|
|||
13ce994edf
|
|||
814175ddaf
|
|||
43e7ddb9de
|
|||
0187fa5b66
|
|||
33c284091d
|
|||
9538589c11
|
|||
905b6933c9
|
|||
07d0ca0438
|
|||
7d37f8a8a1
|
|||
8103caa52c
|
|||
4929b76c7c
|
|||
d20d4f7bf9
|
|||
f06c0b19fa
|
|||
70a08e46bd
|
|||
2349610e47
|
|||
fda5ede37f
|
|||
81da8dd989
|
|||
557c7e6235
|
|||
83a7f83f81
|
|||
6592db3f4e
|
|||
d7abd36717
|
|||
7873d0e724
|
|||
9626ec4662
|
|||
dbb5a483e0
|
|||
aca55f993f
|
|||
41fe55fd1f
|
|||
c491351fd0
|
|||
75d51fb9d9
|
|||
21db83b943
|
|||
fa2e37f603
|
|||
fab3be67ee
|
|||
6e26184a04
|
|||
6b6028434d
|
|||
ca02557df4
|
|||
527ad803d3
|
|||
2791a602b5
|
|||
3404bbc3bc
|
|||
c254b96256
|
|||
1e4d404a43
|
|||
16ec6cbdb6
|
|||
ba99275700
|
|||
80c313b02d
|
|||
fe8682aa85
|
|||
cd23c59c46
|
|||
f5c9b561a9
|
|||
366fd97c0a
|
|||
d3fd61c068
|
|||
0a037f1ae1
|
|||
292bfa362a
|
|||
bcc2c9d0ab
|
|||
e270c9f35b
|
|||
7902726239
|
|||
abb7899a9d
|
|||
8c4c8d36de
|
|||
0fffc6c914
|
|||
34e24df7c9
|
|||
550e98e87c
|
|||
4ff6790072
|
|||
205ddb1e49
|
|||
0735743f44
|
|||
33eee9c628
|
|||
ef5d61df9d
|
|||
11d326b693
|
|||
5293bb2039
|
|||
bc84c406d9
|
|||
ed1f4f3c1b
|
|||
ec04e5abe9
|
|||
5ecfffc049
|
|||
c7d501b466
|
|||
1f646d6826
|
|||
3315d79742
|
|||
a1b58bacd8
|
|||
69122746de
|
|||
764dfe67a5
|
|||
3d87345a51
|
|||
eb89b060f6
|
|||
25713e0f13
|
|||
03147b532c
|
|||
d8cd27196d
|
|||
832833a56f
|
|||
a4e5f4785c
|
|||
a268f8dc2f
|
|||
a16a88b5f9
|
|||
2d2d28689c
|
|||
d4346202ca
|
|||
b1a30059ed
|
|||
58accf8acf
|
|||
24c0848797
|
|||
b232dc6b40
|
|||
120d67fb1a
|
|||
f6eb4bd3dc
|
|||
7e7e475dac
|
|||
23d0056098
|
|||
3edb4b4761
|
|||
fd24431eea
|
|||
5c1c26b135
|
|||
a333d8aa7c
|
|||
f054e9976a
|
|||
f87c3d7e11
|
|||
0041300a00
|
|||
fe6d7f4b08
|
|||
a1622cc885
|
|||
bd32020876
|
|||
44323c85a3
|
|||
027d77ed66
|
|||
bbb70eb621
|
|||
1593e3107d
|
|||
1a48d05042
|
|||
75dd958316
|
|||
cccbfd2c95
|
|||
bf20bd89ed
|
|||
c3fd55bb00
|
|||
c660a7fe4f
|
|||
91ad0e14df
|
|||
a6ca98987e
|
|||
f8f08a11db
|
|||
5d64c05446
|
|||
a1064d8978
|
|||
6d01cf4e69
|
|||
ffd992cd74
|
|||
8d71ed0ad5
|
|||
93d897e95c
|
|||
31181d5b5d
|
|||
2f18d390e4
|
|||
5ffb0e704d
|
|||
ad0c1e15e0
|
|||
b74d4db23b
|
|||
022d99f795
|
|||
3482131b3f
|
|||
0a32c19923
|
|||
36c5c8ad67
|
|||
6240d6638f
|
|||
7491f19f9a
|
|||
13d52897b8
|
|||
4cc058ab42
|
|||
a7f754c5e8
|
|||
9304cafe0c
|
|||
7b42b46942
|
|||
2ce0e0ed79
|
|||
d69eb73a59
|
|||
aa8f415b98
|
|||
ec792f1fe2
|
|||
4c31568329
|
|||
e9dd70c6c4
|
|||
4e9d25143e
|
|||
92fe4bdd81
|
|||
0b21c57ee5
|
|||
c412a75f91
|
|||
0cc4d5096b
|
|||
34bd348f25
|
|||
d251d9d03f | |||
8f88d9028e | |||
fcdc26c1f7 | |||
fc588f10bc | |||
527e1708ce | |||
1286c4cd90 | |||
0d8c65e44b | |||
27356b7826 | |||
d06b6d3270 | |||
f9476d8c57 | |||
79f2faf55b | |||
2d0245f2ac | |||
79e55140e3 | |||
ae7f39d0de | |||
be72d2dc06 | |||
a8e4dd08bb | |||
c2e31827d8 | |||
7087ce7ec5 | |||
36bb7b7a88 | |||
2080d1f2b7 | |||
b05a6a14e8 | |||
c4225f7bdf | |||
76b3d30db9 | |||
e89e984ccb | |||
dd1ffe0d17 | |||
3feb4e72aa | |||
a43fac0c2d | |||
67a3527e29 | |||
f4a96e0b2e | |||
7e69b8f82a | |||
8258d40115 | |||
568dffbca1 | |||
9a82d812d6 | |||
49ee634822 | |||
babf792c30 | |||
65f9a805e2 | |||
6e077acc66 | |||
5af9c9b0a2 | |||
201ace7eec | |||
40f46312f8 | |||
a53d41008c | |||
8a6910bf04 | |||
1d7a9edd46 | |||
58477bae6a | |||
cbc6238d9d | |||
9f393754f6 | |||
fc43512c75 | |||
551853c5d6 | |||
6b4faf9f78 | |||
4a6cf4f2e5 | |||
b008b8089c | |||
2f33ea4dfd | |||
87540ab0b9 | |||
88a3b0912b | |||
7ec85e67df | |||
67692f2cef | |||
cc81facf50 | |||
95cc190b54 | |||
1c842ef3d1 | |||
27ad61fa17 | |||
45d34c688f | |||
1ff62e22bf | |||
2c02da7eaf | |||
8ef7a25728 | |||
b4cc1d9e66 | |||
793ccfd5ba | |||
66362ed387 | |||
11e7d8c2dd | |||
e1e9ce050d | |||
92610b6678 | |||
15a9a21448 | |||
d4c4016c7c | |||
19055409cd | |||
839dfb74b2 | |||
0bfb45020f | |||
9e746c52bc | |||
3740b65263 | |||
77e51a6f2c | |||
42b8b6895f | |||
9da2650486 | |||
e01f488768 | |||
958a3ed263 | |||
a0e3993a3f | |||
edeecf7831 | |||
90fb9c7952 | |||
0a52ef4f68 | |||
5e0a80fa1c | |||
784f3c3df9 | |||
68acf428a2 | |||
9105c63465 | |||
659805960b | |||
451c5405e0 | |||
bd02b976a2 | |||
9bffe3e013 | |||
84298fc4eb | |||
87a2dc9444 | |||
426a84a1a9 | |||
8eed8909da | |||
09d0af1ea6 | |||
7b85636f8f | |||
95585fce5f | |||
bf1e3432d7 | |||
f824df9aad | |||
426499090e | |||
1af2cf657d | |||
f31d11f7ad | |||
851a8c140f | |||
ae2617dca2 | |||
adba9cc348 | |||
232e06f8f3 | |||
aea8a7bb08 | |||
65ab83b42b | |||
d3f6d51ed2 | |||
ca8dc6429b | |||
cfb5d9a0f4 | |||
8dab45ecfd | |||
88a5f06325 | |||
aab84cd3ab | |||
a3719eef3e | |||
0769a82f4b | |||
f978f2487e | |||
8859bfc438 | |||
5202601c4f | |||
78141b28c7 | |||
3f2584ac09 | |||
a2ce579a61 | |||
0958cdf7f8 | |||
7f3b2b4dbb | |||
f6f46d1bbe | |||
c12ee67592 | |||
74ff9579f3 | |||
d7cbeb9eba | |||
4d333f94bc | |||
e003af38ff | |||
d1c504f9a6 | |||
d46ed57dd7 | |||
a6d372aaad | |||
b3e0b30147 | |||
93e57f5dbe | |||
db5a42289a | |||
77136acccd | |||
258ac6e2f6 | |||
fbe4b94805 | |||
2c2e7d9de3 | |||
9dfa750444 | |||
4240183fa1 | |||
42f26787fb | |||
8d08ab933a | |||
c83c542f5b | |||
08319ef4c7 | |||
f4168e2815 | |||
123d11e4e3 | |||
b1a107fb65 | |||
d375acd0ec | |||
5e6e63ab1a | |||
ab4bc55270 | |||
e5acf4a99e | |||
5089cfa81b | |||
b5fce27037 | |||
0238f62894 | |||
ce59b6ea03 | |||
9dcb5abe89 | |||
4ac29bbce1 | |||
155f3bfab5 | |||
e960f9fcc8 | |||
4bb8ce6d00 | |||
2ae18af9a0 | |||
e61b5824db | |||
0f9a1915d1 | |||
6dfefc90c4 | |||
c688bd7a97 | |||
e927d93a48 | |||
d9235c6f90 | |||
afa87ec5f3 | |||
22d01c7a51 | |||
dfe9bbdbfa | |||
92ef18b412 | |||
d0a8d9dd62 | |||
f3e145e6f7 | |||
d9433256ab | |||
ade1c77361 | |||
3e656854bc | |||
6c3eefa85d | |||
2384791793 | |||
97af4d855f | |||
b0f0982fd4 | |||
bd1d117283 | |||
a1b040360c | |||
8f7938a1e5 | |||
b05868d120 | |||
24fd486764 | |||
23a17fae00 | |||
d7bccb6948 | |||
833d8d497a | |||
1b55332027 | |||
cbe651d2da | |||
9c9f5549d7 | |||
655a2d88f5 | |||
cd49a219df | |||
48067d8f58 | |||
c2412fe710 | |||
2f71bccef2 | |||
f5a813380b | |||
b54a32ba7a | |||
1c5c0b524e | |||
62e482facb | |||
1824c99ca0 | |||
e8b61e6d7f | |||
69bc044b09 | |||
c86d24030e | |||
4ced264c3c | |||
a25c5f4a96 | |||
c0acbf8790 | |||
7ce73ab813 | |||
0ab1833034 | |||
495a0ea609 | |||
72232d8bd2 | |||
6bd705f06a | |||
0912d4b383 | |||
4350393610 | |||
a8ff50541a | |||
a4c5ab7ef3 | |||
e147e1eff5 | |||
c09bdee89a | |||
3fa7acb116 | |||
749a1b1810 | |||
210e06429c | |||
137f16bc55 | |||
995ef471ab | |||
58f3442c6d | |||
3af04bce80 | |||
75c8dbd31b | |||
fbe9fbfbd1 | |||
e6933acfb0 | |||
07abdd9f6c | |||
9cb66f395b | |||
eb602e12c2 | |||
61b1e95629 | |||
2bb997597e | |||
463d16f8bc | |||
6cf3c62c83 | |||
3a85a5586f | |||
363200d443 | |||
d4001003a3 | |||
8bfed94ba9 |
127
.devcontainer/Dockerfile
Normal file
127
.devcontainer/Dockerfile
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
FROM mcr.microsoft.com/devcontainers/cpp:1-ubuntu-24.04
|
||||||
|
|
||||||
|
ARG REINSTALL_CMAKE_VERSION_FROM_SOURCE="none"
|
||||||
|
|
||||||
|
COPY ./reinstall-cmake.sh /tmp/
|
||||||
|
RUN <<EOF
|
||||||
|
if [ "${REINSTALL_CMAKE_VERSION_FROM_SOURCE}" != "none" ]; then
|
||||||
|
chmod +x /tmp/reinstall-cmake.sh && /tmp/reinstall-cmake.sh ${REINSTALL_CMAKE_VERSION_FROM_SOURCE};
|
||||||
|
fi
|
||||||
|
rm -f /tmp/reinstall-cmake.sh
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Update system and set noninteractive env
|
||||||
|
RUN export DEBIAN_FRONTEND=noninteractive && apt-get update
|
||||||
|
|
||||||
|
# Required packages for building gcc & binutils
|
||||||
|
RUN apt-get -y install --no-install-recommends \
|
||||||
|
build-essential \
|
||||||
|
bison \
|
||||||
|
flex \
|
||||||
|
libgmp-dev \
|
||||||
|
libmpfr-dev \
|
||||||
|
texinfo \
|
||||||
|
file \
|
||||||
|
python3-dev
|
||||||
|
|
||||||
|
# Required packages for building qemu
|
||||||
|
RUN apt-get -y install --no-install-recommends \
|
||||||
|
git \
|
||||||
|
libglib2.0-dev \
|
||||||
|
libfdt-dev \
|
||||||
|
libpixman-1-dev \
|
||||||
|
zlib1g-dev \
|
||||||
|
ninja-build \
|
||||||
|
libaio-dev \
|
||||||
|
libbluetooth-dev \
|
||||||
|
libcapstone-dev \
|
||||||
|
libbrlapi-dev \
|
||||||
|
libbz2-dev \
|
||||||
|
libcap-ng-dev \
|
||||||
|
libcurl4-gnutls-dev \
|
||||||
|
libgtk-3-dev \
|
||||||
|
libibverbs-dev \
|
||||||
|
libjpeg8-dev \
|
||||||
|
libncurses5-dev \
|
||||||
|
libnuma-dev \
|
||||||
|
librbd-dev \
|
||||||
|
librdmacm-dev \
|
||||||
|
libsasl2-dev \
|
||||||
|
libsdl2-dev \
|
||||||
|
libseccomp-dev \
|
||||||
|
libsnappy-dev \
|
||||||
|
libssh-dev \
|
||||||
|
libvde-dev \
|
||||||
|
libvdeplug-dev \
|
||||||
|
libvte-2.91-dev \
|
||||||
|
libxen-dev \
|
||||||
|
liblzo2-dev \
|
||||||
|
valgrind \
|
||||||
|
xfslibs-dev \
|
||||||
|
libnfs-dev \
|
||||||
|
libiscsi-dev \
|
||||||
|
python3-venv \
|
||||||
|
libslirp-dev \
|
||||||
|
ovmf
|
||||||
|
|
||||||
|
# Required packages for building test apps in userspace
|
||||||
|
RUN apt-get -y install --no-install-recommends \
|
||||||
|
mingw-w64 \
|
||||||
|
libtool \
|
||||||
|
libltdl-dev
|
||||||
|
|
||||||
|
# Required packages for building the OS and misc
|
||||||
|
RUN apt-get -y install --no-install-recommends \
|
||||||
|
grub2-common \
|
||||||
|
xorriso \
|
||||||
|
mtools \
|
||||||
|
grub-common \
|
||||||
|
grub-efi-amd64-bin \
|
||||||
|
grub-efi-amd64-signed \
|
||||||
|
grub-gfxpayload-lists \
|
||||||
|
grub-pc-bin \
|
||||||
|
grub-pc \
|
||||||
|
grub2-common \
|
||||||
|
pip \
|
||||||
|
cmake
|
||||||
|
|
||||||
|
# Install git-cliff
|
||||||
|
RUN pip install git-cliff --break-system-packages
|
||||||
|
|
||||||
|
# Install meson
|
||||||
|
RUN pip install meson --break-system-packages
|
||||||
|
|
||||||
|
# Configure git
|
||||||
|
RUN <<EOF
|
||||||
|
git config --global advice.detachedHead false
|
||||||
|
git config --global core.autocrlf input
|
||||||
|
git config --global init.defaultbranch master
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Set display environment variable for QEMU
|
||||||
|
ENV DISPLAY=:0
|
||||||
|
ENV NO_AT_BRIDGE=1
|
||||||
|
|
||||||
|
# Set PATH
|
||||||
|
RUN <<EOF
|
||||||
|
echo PATH=$PATH:/workspaces/Fennix/cross/bin >> /etc/profile
|
||||||
|
EOF
|
||||||
|
|
||||||
|
ENV CHMOD_KVM=1
|
||||||
|
|
||||||
|
# Remove autoconf & automake
|
||||||
|
RUN sudo apt-get -y remove autoconf automake
|
||||||
|
|
||||||
|
# Required packages for building gcc & binutils
|
||||||
|
RUN <<EOF
|
||||||
|
wget https://launchpad.net/ubuntu/+archive/primary/+files/autoconf_2.69-11.1_all.deb -O /tmp/autoconf.deb
|
||||||
|
sudo dpkg --force-all -i /tmp/autoconf.deb
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Required packages for building gcc & binutils
|
||||||
|
RUN <<EOF
|
||||||
|
wget https://ftp.gnu.org/gnu/automake/automake-1.15.1.tar.gz -O /tmp/automake.tar.gz
|
||||||
|
tar -xzf /tmp/automake.tar.gz -C /tmp
|
||||||
|
cd /tmp/automake-1.15.1
|
||||||
|
./configure && make && sudo make install
|
||||||
|
EOF
|
45
.devcontainer/devcontainer.json
Normal file
45
.devcontainer/devcontainer.json
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
|
||||||
|
// README at: https://github.com/devcontainers/templates/tree/main/src/cpp
|
||||||
|
{
|
||||||
|
"name": "Fennix",
|
||||||
|
"build": {
|
||||||
|
"dockerfile": "Dockerfile"
|
||||||
|
},
|
||||||
|
"customizations": {
|
||||||
|
"vscode": {
|
||||||
|
"extensions": [
|
||||||
|
"ms-azuretools.vscode-docker",
|
||||||
|
"eamodio.gitlens",
|
||||||
|
"EditorConfig.EditorConfig",
|
||||||
|
"naumovs.color-highlight",
|
||||||
|
"Gruntfuggly.todo-tree",
|
||||||
|
"ms-vscode.hexeditor",
|
||||||
|
"vivaxy.vscode-conventional-commits",
|
||||||
|
"webfreak.debug",
|
||||||
|
"maziac.asm-code-lens",
|
||||||
|
"Seven1bit.vscode-ext-ansi-color-highlight",
|
||||||
|
"ms-vsliveshare.vsliveshare",
|
||||||
|
"maziac.hex-hover-converter",
|
||||||
|
"ms-vscode.makefile-tools"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// From this line below are for qemu, so not that important.
|
||||||
|
"initializeCommand": "[ -x \"$(command -v xhost)\" ] && xhost +local:docker || true", // "xhost -local:docker" to disable
|
||||||
|
"mounts": [
|
||||||
|
{
|
||||||
|
"source": "/tmp/.X11-unix",
|
||||||
|
"target": "/tmp/.X11-unix",
|
||||||
|
"type": "bind"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"source": "/run/user/1000/pulse/native",
|
||||||
|
"target": "/run/user/1000/pulse/native",
|
||||||
|
"type": "bind"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"runArgs": [
|
||||||
|
"--privileged",
|
||||||
|
"--network=host"
|
||||||
|
]
|
||||||
|
}
|
59
.devcontainer/reinstall-cmake.sh
Normal file
59
.devcontainer/reinstall-cmake.sh
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
#-------------------------------------------------------------------------------------------------------------
|
||||||
|
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
# Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information.
|
||||||
|
#-------------------------------------------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
set -e
|
||||||
|
|
||||||
|
CMAKE_VERSION=${1:-"none"}
|
||||||
|
|
||||||
|
if [ "${CMAKE_VERSION}" = "none" ]; then
|
||||||
|
echo "No CMake version specified, skipping CMake reinstallation"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Cleanup temporary directory and associated files when exiting the script.
|
||||||
|
cleanup() {
|
||||||
|
EXIT_CODE=$?
|
||||||
|
set +e
|
||||||
|
if [[ -n "${TMP_DIR}" ]]; then
|
||||||
|
echo "Executing cleanup of tmp files"
|
||||||
|
rm -Rf "${TMP_DIR}"
|
||||||
|
fi
|
||||||
|
exit $EXIT_CODE
|
||||||
|
}
|
||||||
|
trap cleanup EXIT
|
||||||
|
|
||||||
|
|
||||||
|
echo "Installing CMake..."
|
||||||
|
apt-get -y purge --auto-remove cmake
|
||||||
|
mkdir -p /opt/cmake
|
||||||
|
|
||||||
|
architecture=$(dpkg --print-architecture)
|
||||||
|
case "${architecture}" in
|
||||||
|
arm64)
|
||||||
|
ARCH=aarch64 ;;
|
||||||
|
amd64)
|
||||||
|
ARCH=x86_64 ;;
|
||||||
|
*)
|
||||||
|
echo "Unsupported architecture ${architecture}."
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
CMAKE_BINARY_NAME="cmake-${CMAKE_VERSION}-linux-${ARCH}.sh"
|
||||||
|
CMAKE_CHECKSUM_NAME="cmake-${CMAKE_VERSION}-SHA-256.txt"
|
||||||
|
TMP_DIR=$(mktemp -d -t cmake-XXXXXXXXXX)
|
||||||
|
|
||||||
|
echo "${TMP_DIR}"
|
||||||
|
cd "${TMP_DIR}"
|
||||||
|
|
||||||
|
curl -sSL "https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/${CMAKE_BINARY_NAME}" -O
|
||||||
|
curl -sSL "https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/${CMAKE_CHECKSUM_NAME}" -O
|
||||||
|
|
||||||
|
sha256sum -c --ignore-missing "${CMAKE_CHECKSUM_NAME}"
|
||||||
|
sh "${TMP_DIR}/${CMAKE_BINARY_NAME}" --prefix=/opt/cmake --skip-license
|
||||||
|
|
||||||
|
ln -s /opt/cmake/bin/cmake /usr/local/bin/cmake
|
||||||
|
ln -s /opt/cmake/bin/ctest /usr/local/bin/ctest
|
26
.editorconfig
Normal file
26
.editorconfig
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
# EditorConfig is awesome: https://editorconfig.org
|
||||||
|
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
end_of_line = lf
|
||||||
|
insert_final_newline = true
|
||||||
|
indent_style = tab
|
||||||
|
indent_size = 4
|
||||||
|
|
||||||
|
[Makefile]
|
||||||
|
indent_style = tab
|
||||||
|
|
||||||
|
[.github/**]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
[{CMakeLists.txt,*.cmake}]
|
||||||
|
indent_size = 2
|
||||||
|
indent_style = space
|
||||||
|
|
||||||
|
[*.md]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
|
trim_trailing_whitespace = false
|
86
.github/workflows/codeql.yml
vendored
86
.github/workflows/codeql.yml
vendored
@ -1,86 +0,0 @@
|
|||||||
name: "CodeQL Advanced"
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [ "master" ]
|
|
||||||
pull_request:
|
|
||||||
branches: [ "master" ]
|
|
||||||
schedule:
|
|
||||||
- cron: '27 20 * * 0'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
analyze:
|
|
||||||
name: Analyze (${{ matrix.language }})
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
permissions:
|
|
||||||
security-events: write
|
|
||||||
packages: read
|
|
||||||
actions: read
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
defaults:
|
|
||||||
run:
|
|
||||||
shell: bash
|
|
||||||
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
include:
|
|
||||||
- language: c-cpp
|
|
||||||
build-mode: manual
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Check for cache
|
|
||||||
id: check-cache
|
|
||||||
run: |
|
|
||||||
if [ -z "${{ runner.os }}-cross-${{ hashFiles('tools/Makefile') }}" ]; then
|
|
||||||
echo "No cache found, cancelling job."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Initialize CodeQL
|
|
||||||
uses: github/codeql-action/init@v3
|
|
||||||
with:
|
|
||||||
languages: ${{ matrix.language }}
|
|
||||||
build-mode: ${{ matrix.build-mode }}
|
|
||||||
|
|
||||||
- if: matrix.build-mode == 'manual'
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
echo 'If you are using a "manual" build mode for one or more of the' \
|
|
||||||
'languages you are analyzing, replace this with the commands to build' \
|
|
||||||
'your code, for example:'
|
|
||||||
echo ' make bootstrap'
|
|
||||||
echo ' make release'
|
|
||||||
exit 0
|
|
||||||
|
|
||||||
- name: Install Packages
|
|
||||||
run: |
|
|
||||||
sudo apt update
|
|
||||||
sudo apt -y install rustc xorriso mtools genisoimage ovmf nasm doxygen make gcc-mingw-w64-x86-64 gcc-mingw-w64-i686 mingw-w64 build-essential bison flex libgmp3-dev libmpc-dev libmpfr-dev texinfo
|
|
||||||
make --quiet -C tools do_limine
|
|
||||||
make --quiet -C Drivers prepare
|
|
||||||
make --quiet -C Userspace prepare
|
|
||||||
make --quiet -C Kernel prepare
|
|
||||||
|
|
||||||
- name: Cache cross
|
|
||||||
id: cache-cross
|
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: tools/cross
|
|
||||||
key: ${{ runner.os }}-cross-${{ hashFiles('tools/Makefile') }}
|
|
||||||
|
|
||||||
- name: Build OS
|
|
||||||
run: |
|
|
||||||
make build_userspace
|
|
||||||
make build_drivers
|
|
||||||
make build_kernel
|
|
||||||
make build_userspace
|
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
|
||||||
uses: github/codeql-action/analyze@v3
|
|
||||||
with:
|
|
||||||
category: "/language:${{matrix.language}}"
|
|
34
.github/workflows/docs.yml
vendored
34
.github/workflows/docs.yml
vendored
@ -1,34 +0,0 @@
|
|||||||
name: Deploy Documentation
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [ master ]
|
|
||||||
pull_request:
|
|
||||||
branches: [ master ]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
deploydoc:
|
|
||||||
name: Deploy Documentation to GitHub Pages
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout code
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
submodules: recursive
|
|
||||||
|
|
||||||
- name: Update System
|
|
||||||
run: sudo apt update
|
|
||||||
|
|
||||||
- name: Install Doxygen
|
|
||||||
run: sudo apt -y install doxygen make
|
|
||||||
|
|
||||||
- name: Generate Documentation
|
|
||||||
run: make doxygen
|
|
||||||
|
|
||||||
- name: Copy GitHub Pages Website
|
|
||||||
run: cp -r tools/website/* doxygen-doc/
|
|
||||||
|
|
||||||
- name: Deploy documentation
|
|
||||||
uses: JamesIves/github-pages-deploy-action@v4
|
|
||||||
with:
|
|
||||||
folder: doxygen-doc
|
|
313
.github/workflows/makefile.yml
vendored
313
.github/workflows/makefile.yml
vendored
@ -11,208 +11,215 @@ jobs:
|
|||||||
name: Build Cross-Compiler & Toolchain
|
name: Build Cross-Compiler & Toolchain
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
|
|
||||||
- name: Cache cross Folder
|
- name: Cache cross Folder
|
||||||
id: cache-cross
|
id: cache-cross
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: tools/cross
|
path: tools/cross
|
||||||
key: ${{ runner.os }}-cross-${{ hashFiles('tools/Makefile') }}
|
key: ${{ runner.os }}-cross-${{ hashFiles('tools/Makefile') }}
|
||||||
|
|
||||||
- name: Update System
|
- name: Prepare Environment for Dev Container
|
||||||
if: steps.cache-cross.outputs.cache-hit != 'true'
|
|
||||||
run: sudo apt update
|
|
||||||
|
|
||||||
- name: Install GCC Dependencies
|
|
||||||
if: steps.cache-cross.outputs.cache-hit != 'true'
|
|
||||||
run: sudo apt -y install build-essential bison flex libgmp3-dev libmpc-dev libmpfr-dev texinfo libzstd-dev libisl-dev m4 automake gettext gperf dejagnu guile-3.0 guile-3.0-dev expect tcl autogen tex-common sphinx-common git ssh diffutils patch autoconf2.69 libtool wget dpkg
|
|
||||||
|
|
||||||
- name: Check autoconf
|
|
||||||
if: steps.cache-cross.outputs.cache-hit != 'true'
|
|
||||||
run: |
|
run: |
|
||||||
if [ "$(autoconf --version | head -n 1 | awk '{print $NF}')" != "2.69" ]; then
|
sudo mkdir -p /tmp/.X11-unix
|
||||||
echo "Autoconf version is not 2.69, performing additional steps..."
|
sudo mkdir -p /run/user/1000/pulse
|
||||||
wget https://launchpad.net/ubuntu/+archive/primary/+files/autoconf_2.69-11.1_all.deb
|
sudo touch /run/user/1000/pulse/native
|
||||||
sudo dpkg --force-all -i ./autoconf_2.69-11.1_all.deb
|
|
||||||
|
- name: Run make ci-setup in dev container
|
||||||
|
if: steps.cache-cross.outputs.cache-hit != 'true'
|
||||||
|
uses: devcontainers/ci@v0.3
|
||||||
|
with:
|
||||||
|
push: never
|
||||||
|
runCmd: |
|
||||||
|
/usr/bin/make ci-setup
|
||||||
|
|
||||||
|
analyze:
|
||||||
|
name: Analyze (${{ matrix.language }})
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: [buildcompiler]
|
||||||
|
permissions:
|
||||||
|
security-events: write
|
||||||
|
packages: read
|
||||||
|
actions: read
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
shell: bash
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- language: c-cpp
|
||||||
|
build-mode: manual
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Check for cache
|
||||||
|
id: check-cache
|
||||||
|
run: |
|
||||||
|
if [ -z "${{ runner.os }}-cross-${{ hashFiles('tools/Makefile') }}" ]; then
|
||||||
|
echo "No cache found, cancelling job."
|
||||||
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Check automake
|
- name: Initialize CodeQL
|
||||||
if: steps.cache-cross.outputs.cache-hit != 'true'
|
uses: github/codeql-action/init@v3
|
||||||
run: |
|
|
||||||
if [ "$(automake --version | head -n 1 | awk '{print $NF}')" != "1.15.1" ]; then
|
|
||||||
echo "Automake version is not 1.15.1, performing additional steps..."
|
|
||||||
wget https://ftp.gnu.org/gnu/automake/automake-1.15.1.tar.gz
|
|
||||||
tar -xzf automake-1.15.1.tar.gz
|
|
||||||
cd automake-1.15.1
|
|
||||||
./configure
|
|
||||||
make
|
|
||||||
sudo make install
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Clone All
|
|
||||||
if: steps.cache-cross.outputs.cache-hit != 'true'
|
|
||||||
run: make --quiet -C tools __clone_all_no_qemu
|
|
||||||
|
|
||||||
- name: Compile Binutils
|
|
||||||
if: steps.cache-cross.outputs.cache-hit != 'true'
|
|
||||||
run: make --quiet -C tools do_binutils
|
|
||||||
|
|
||||||
- name: Compile GCC
|
|
||||||
if: steps.cache-cross.outputs.cache-hit != 'true'
|
|
||||||
run: make --quiet -C tools do_gcc
|
|
||||||
|
|
||||||
- name: Clean Up
|
|
||||||
if: steps.cache-cross.outputs.cache-hit != 'true'
|
|
||||||
run: |
|
|
||||||
cd tools
|
|
||||||
rm -rf binutils-gdb gcc
|
|
||||||
|
|
||||||
compile64:
|
|
||||||
name: Build amd64
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: [buildcompiler]
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
languages: ${{ matrix.language }}
|
||||||
|
build-mode: ${{ matrix.build-mode }}
|
||||||
|
|
||||||
- name: Update & Install Required Packages
|
- if: matrix.build-mode == 'manual'
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
echo 'If you are using a "manual" build mode for one or more of the' \
|
||||||
|
'languages you are analyzing, replace this with the commands to build' \
|
||||||
|
'your code, for example:'
|
||||||
|
echo ' make bootstrap'
|
||||||
|
echo ' make release'
|
||||||
|
exit 0
|
||||||
|
|
||||||
|
- name: Install Packages
|
||||||
run: |
|
run: |
|
||||||
sudo apt update
|
sudo apt update
|
||||||
sudo apt install rustc xorriso mtools genisoimage ovmf nasm doxygen make meson gcc-10 g++-10 gcc-mingw-w64-x86-64 gcc-mingw-w64-i686 mingw-w64 -y
|
sudo apt --no-install-recommends -y install rustc xorriso mtools genisoimage ovmf nasm doxygen make gcc-mingw-w64-x86-64 gcc-mingw-w64-i686 mingw-w64 build-essential bison flex libgmp3-dev libmpc-dev libmpfr-dev texinfo
|
||||||
make --quiet -C tools do_limine
|
make --quiet -C tools do_limine
|
||||||
make --quiet -C Drivers prepare
|
make --quiet prepare
|
||||||
make --quiet -C Userspace prepare
|
|
||||||
make --quiet -C Kernel prepare
|
|
||||||
|
|
||||||
- name: Cache cross Folder
|
- name: Cache cross
|
||||||
id: cache-cross
|
id: cache-cross
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: tools/cross
|
path: tools/cross
|
||||||
key: ${{ runner.os }}-cross-${{ hashFiles('tools/Makefile') }}
|
key: ${{ runner.os }}-cross-${{ hashFiles('tools/Makefile') }}
|
||||||
|
|
||||||
- name: Configure config.mk
|
- name: Build OS
|
||||||
run: sed -i 's/.*OSARCH = .*/OSARCH = amd64/' ./config.mk && cat config.mk | grep OSARCH
|
|
||||||
|
|
||||||
- name: Compile Debug and Release ISO
|
|
||||||
run: |
|
run: |
|
||||||
make build
|
make build_userspace
|
||||||
mv Fennix.iso Fennix-debug.iso
|
make build_drivers
|
||||||
make clean
|
make build_kernel
|
||||||
sed -i 's/.*DEBUG = .*/DEBUG = 0/' ./config.mk && cat config.mk | grep DEBUG
|
make build_userspace
|
||||||
make build
|
|
||||||
mv Fennix.iso Fennix-release.iso
|
|
||||||
|
|
||||||
- name: Upload Artifact (Fennix-debug.iso)
|
- name: Perform CodeQL Analysis
|
||||||
uses: actions/upload-artifact@v3
|
uses: github/codeql-action/analyze@v3
|
||||||
with:
|
with:
|
||||||
name: Fennix-amd64-debug
|
category: "/language:${{matrix.language}}"
|
||||||
path: Fennix-debug.iso
|
|
||||||
|
|
||||||
- name: Upload Artifact (Fennix-release.iso)
|
compile:
|
||||||
uses: actions/upload-artifact@v3
|
name: Build OS
|
||||||
with:
|
|
||||||
name: Fennix-amd64-release
|
|
||||||
path: Fennix-release.iso
|
|
||||||
|
|
||||||
compile32:
|
|
||||||
name: Build i386
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: [buildcompiler]
|
needs: [buildcompiler]
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
|
fetch-depth: 0
|
||||||
- name: Update & Install Required Packages
|
|
||||||
run: |
|
|
||||||
sudo apt update
|
|
||||||
sudo apt install rustc xorriso mtools genisoimage ovmf nasm doxygen make meson gcc-10 g++-10 gcc-mingw-w64-x86-64 gcc-mingw-w64-i686 mingw-w64 -y
|
|
||||||
make --quiet -C tools do_limine
|
|
||||||
make --quiet -C Drivers prepare
|
|
||||||
make --quiet -C Userspace prepare
|
|
||||||
make --quiet -C Kernel prepare
|
|
||||||
|
|
||||||
- name: Cache cross Folder
|
- name: Cache cross Folder
|
||||||
id: cache-cross
|
id: cache-cross
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: tools/cross
|
path: tools/cross
|
||||||
key: ${{ runner.os }}-cross-${{ hashFiles('tools/Makefile') }}
|
key: ${{ runner.os }}-cross-${{ hashFiles('tools/Makefile') }}
|
||||||
|
|
||||||
- name: Configure config.mk
|
- name: Prepare Environment for Dev Container
|
||||||
run: sed -i 's/.*OSARCH = .*/OSARCH = i386/' ./config.mk && cat config.mk | grep OSARCH
|
|
||||||
|
|
||||||
- name: Compile Debug and Release ISO
|
|
||||||
run: |
|
run: |
|
||||||
make build
|
sudo mkdir -p /tmp/.X11-unix
|
||||||
mv Fennix.iso Fennix-debug.iso
|
sudo mkdir -p /run/user/1000/pulse
|
||||||
make clean
|
sudo touch /run/user/1000/pulse/native
|
||||||
sed -i 's/.*DEBUG = .*/DEBUG = 0/' ./config.mk && cat config.mk | grep DEBUG
|
|
||||||
make build
|
|
||||||
mv Fennix.iso Fennix-release.iso
|
|
||||||
|
|
||||||
- name: Upload Artifact (Fennix-debug.iso)
|
- name: Build AMD64 Debug
|
||||||
uses: actions/upload-artifact@v3
|
if: always()
|
||||||
|
uses: devcontainers/ci@v0.3
|
||||||
with:
|
with:
|
||||||
name: Fennix-i386-debug
|
push: never
|
||||||
path: Fennix-debug.iso
|
runCmd: /usr/bin/make __ci-amd64-debug
|
||||||
|
|
||||||
- name: Upload Artifact (Fennix-release.iso)
|
- name: Build AMD64 Release
|
||||||
uses: actions/upload-artifact@v3
|
if: always()
|
||||||
|
uses: devcontainers/ci@v0.3
|
||||||
with:
|
with:
|
||||||
name: Fennix-i386-release
|
push: never
|
||||||
path: Fennix-release.iso
|
runCmd: /usr/bin/make __ci-amd64-release
|
||||||
|
|
||||||
compilearm64:
|
- name: Build i386 Debug
|
||||||
name: Build aarch64
|
if: always()
|
||||||
|
uses: devcontainers/ci@v0.3
|
||||||
|
with:
|
||||||
|
push: never
|
||||||
|
runCmd: /usr/bin/make __ci-i386-debug
|
||||||
|
|
||||||
|
- name: Build i386 Release
|
||||||
|
if: always()
|
||||||
|
uses: devcontainers/ci@v0.3
|
||||||
|
with:
|
||||||
|
push: never
|
||||||
|
runCmd: /usr/bin/make __ci-i386-release
|
||||||
|
|
||||||
|
- name: Build ARM Debug
|
||||||
|
if: always()
|
||||||
|
uses: devcontainers/ci@v0.3
|
||||||
|
with:
|
||||||
|
push: never
|
||||||
|
runCmd: /usr/bin/make __ci-arm-debug
|
||||||
|
|
||||||
|
- name: Build ARM Release
|
||||||
|
if: always()
|
||||||
|
uses: devcontainers/ci@v0.3
|
||||||
|
with:
|
||||||
|
push: never
|
||||||
|
runCmd: /usr/bin/make __ci-arm-release
|
||||||
|
|
||||||
|
- name: Build AArch64 Debug
|
||||||
|
if: always()
|
||||||
|
uses: devcontainers/ci@v0.3
|
||||||
|
with:
|
||||||
|
push: never
|
||||||
|
runCmd: /usr/bin/make __ci-aarch64-debug
|
||||||
|
|
||||||
|
- name: Build AArch64 Release
|
||||||
|
if: always()
|
||||||
|
uses: devcontainers/ci@v0.3
|
||||||
|
with:
|
||||||
|
push: never
|
||||||
|
runCmd: /usr/bin/make __ci-aarch64-release
|
||||||
|
|
||||||
|
- name: Build Prepare Archive
|
||||||
|
if: always()
|
||||||
|
uses: devcontainers/ci@v0.3
|
||||||
|
with:
|
||||||
|
push: never
|
||||||
|
runCmd: /usr/bin/make __ci-prepare-archive
|
||||||
|
|
||||||
|
- name: Upload Artifact
|
||||||
|
if: always()
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: artifacts
|
||||||
|
path: artifacts/
|
||||||
|
|
||||||
|
nightly:
|
||||||
|
if: always()
|
||||||
|
name: Upload Nightly Build to GitHub Releases
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: [buildcompiler]
|
needs: [compile]
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Update & Install Required Packages
|
- name: Download All Builds
|
||||||
run: |
|
uses: actions/download-artifact@v4
|
||||||
sudo apt update
|
|
||||||
sudo apt install rustc xorriso mtools genisoimage ovmf nasm doxygen make meson gcc-10 g++-10 gcc-mingw-w64-x86-64 gcc-mingw-w64-i686 mingw-w64 -y
|
|
||||||
make --quiet -C tools do_limine
|
|
||||||
make --quiet -C Drivers prepare
|
|
||||||
make --quiet -C Userspace prepare
|
|
||||||
make --quiet -C Kernel prepare
|
|
||||||
|
|
||||||
- name: Cache cross Folder
|
- name: Update Nightly
|
||||||
id: cache-cross
|
run: gh release upload nightly artifacts/* -R ${{github.repository}} --clobber
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: tools/cross
|
|
||||||
key: ${{ runner.os }}-cross-${{ hashFiles('tools/Makefile') }}
|
|
||||||
|
|
||||||
- name: Configure config.mk
|
env:
|
||||||
run: sed -i 's/.*OSARCH = .*/OSARCH = aarch64/' ./config.mk && cat config.mk | grep OSARCH
|
GH_TOKEN: ${{ github.token }}
|
||||||
|
|
||||||
- name: Compile Debug and Release ISO
|
|
||||||
run: |
|
|
||||||
make build
|
|
||||||
mv Fennix.iso Fennix-debug.iso
|
|
||||||
make clean
|
|
||||||
sed -i 's/.*DEBUG = .*/DEBUG = 0/' ./config.mk && cat config.mk | grep DEBUG
|
|
||||||
make build
|
|
||||||
mv Fennix.iso Fennix-release.iso
|
|
||||||
|
|
||||||
- name: Upload Artifact (Fennix-debug.iso)
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: Fennix-aarch64-debug
|
|
||||||
path: Fennix-debug.iso
|
|
||||||
|
|
||||||
- name: Upload Artifact (Fennix-release.iso)
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: Fennix-aarch64-release
|
|
||||||
path: Fennix-release.iso
|
|
||||||
|
33
.github/workflows/website.yml
vendored
Normal file
33
.github/workflows/website.yml
vendored
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
name: Deploy Website
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ master ]
|
||||||
|
paths:
|
||||||
|
- tools/website/**
|
||||||
|
- Kernel/include/interface/**
|
||||||
|
- Doxyfile
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
deploydoc:
|
||||||
|
name: Deploy Website to GitHub Pages
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout code 🛎️
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install Doxygen 📦
|
||||||
|
run: |
|
||||||
|
sudo apt update
|
||||||
|
sudo apt --no-install-recommends -y install doxygen make
|
||||||
|
|
||||||
|
- name: Generate Documentation 📚
|
||||||
|
run: make doxygen
|
||||||
|
|
||||||
|
- name: Copy GitHub Pages Website 📁
|
||||||
|
run: cp -r tools/website/* doxygen-doc/
|
||||||
|
|
||||||
|
- name: Deploy documentation 🚀
|
||||||
|
uses: JamesIves/github-pages-deploy-action@v4
|
||||||
|
with:
|
||||||
|
folder: doxygen-doc
|
23
.gitignore
vendored
23
.gitignore
vendored
@ -1,23 +1,10 @@
|
|||||||
iso_tmp_data
|
iso_tmp_data
|
||||||
initrd_tmp_data
|
artifacts
|
||||||
initrd/usr/include/*
|
tmp_rootfs
|
||||||
!initrd/usr/include/.gitkeep
|
rootfs/usr/include/*
|
||||||
tools/*
|
!rootfs/usr/include/.gitkeep
|
||||||
!tools/ExtMemDbg
|
|
||||||
!tools/stage2_eltorito
|
|
||||||
!tools/*.md
|
|
||||||
!tools/README.md
|
|
||||||
!tools/website
|
|
||||||
!tools/Makefile
|
|
||||||
!tools/*.c
|
|
||||||
!tools/*.patch
|
|
||||||
!tools/*.cpp
|
|
||||||
!tools/*.cfg
|
|
||||||
!tools/acpi
|
|
||||||
!tools/doxygen
|
|
||||||
!tools/.gdbinit
|
|
||||||
doxygen-doc
|
doxygen-doc
|
||||||
initrd.tar
|
rootfs.tar.gz
|
||||||
.dccache
|
.dccache
|
||||||
*.log
|
*.log
|
||||||
*.log.*
|
*.log.*
|
||||||
|
130
.vscode/launch.json
vendored
130
.vscode/launch.json
vendored
@ -2,55 +2,141 @@
|
|||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"configurations": [
|
"configurations": [
|
||||||
{
|
{
|
||||||
"name": "Launch QEMU & debug the kernel",
|
"name": "Debug Kernel (x64)",
|
||||||
"type": "cppdbg",
|
"type": "cppdbg",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"program": "${workspaceFolder}/../Kernel/fennix.elf",
|
"program": "${workspaceFolder}/../Kernel/fennix.elf",
|
||||||
"cwd": "${workspaceFolder}",
|
"cwd": "${workspaceFolder}",
|
||||||
"args": [],
|
|
||||||
"targetArchitecture": "x64",
|
"targetArchitecture": "x64",
|
||||||
"MIMode": "gdb",
|
"MIMode": "gdb",
|
||||||
"miDebuggerServerAddress": "/tmp/gdb-fennix",
|
"miDebuggerServerAddress": "/tmp/gdb-fennix",
|
||||||
"miDebuggerPath": "${workspaceFolder}/../tools/cross/bin/x86_64-fennix-gdb",
|
"miDebuggerPath": "${workspaceFolder}/../tools/cross/bin/x86_64-fennix-gdb",
|
||||||
"miDebuggerArgs": "",
|
|
||||||
"externalConsole": false,
|
"externalConsole": false,
|
||||||
"additionalSOLibSearchPath": "${workspaceFolder}",
|
|
||||||
"internalConsoleOptions": "neverOpen",
|
"internalConsoleOptions": "neverOpen",
|
||||||
"customLaunchSetupCommands": [
|
|
||||||
// {
|
|
||||||
// "text": "target remote localhost:1234",
|
|
||||||
// "description": "Connect to QEMU remote debugger"
|
|
||||||
// }
|
|
||||||
],
|
|
||||||
"setupCommands": [
|
"setupCommands": [
|
||||||
{
|
|
||||||
"description": "Enable pretty-printing for gdb",
|
|
||||||
"text": "-enable-pretty-printing",
|
|
||||||
"ignoreFailures": true
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"text": "set breakpoint pending on",
|
"text": "set breakpoint pending on",
|
||||||
"description": "Make breakpoint pending on future shared library load."
|
"description": "Make breakpoint pending on future shared library load."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"text": "file ${workspaceFolder}/../Kernel/fennix.elf",
|
"text": "add-symbol-file ${workspaceFolder}/../tmp_rootfs/bin/utest",
|
||||||
"description": "Load binary"
|
"description": "/bin/utest (0x00400000)",
|
||||||
|
"ignoreFailures": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"text": "add-symbol-file ${workspaceFolder}/../initrd_tmp_data/bin/utest",
|
"text": "add-symbol-file ${workspaceFolder}/../tmp_rootfs/bin/libc_test",
|
||||||
"description": "Load /bin/utest",
|
"description": "/bin/libc_test (0x00600000)",
|
||||||
"ignoreFailures": true
|
"ignoreFailures": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"text": "source ${workspaceFolder}/../tools/.gdbinit"
|
"text": "source ${workspaceFolder}/../tools/.gdbinit"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"preLaunchTask": "launch-qemu"
|
"preLaunchTask": "QEMU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Debug Kernel (x86)",
|
||||||
|
"type": "cppdbg",
|
||||||
|
"request": "launch",
|
||||||
|
"program": "${workspaceFolder}/../Kernel/fennix.elf",
|
||||||
|
"cwd": "${workspaceFolder}",
|
||||||
|
"targetArchitecture": "x86",
|
||||||
|
"MIMode": "gdb",
|
||||||
|
"miDebuggerServerAddress": "/tmp/gdb-fennix",
|
||||||
|
"miDebuggerPath": "${workspaceFolder}/../tools/cross/bin/i386-fennix-gdb",
|
||||||
|
"externalConsole": false,
|
||||||
|
"internalConsoleOptions": "neverOpen",
|
||||||
|
"setupCommands": [
|
||||||
|
{
|
||||||
|
"text": "set breakpoint pending on",
|
||||||
|
"description": "Make breakpoint pending on future shared library load."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "add-symbol-file ${workspaceFolder}/../tmp_rootfs/bin/utest",
|
||||||
|
"description": "/bin/utest (0x00400000)",
|
||||||
|
"ignoreFailures": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "add-symbol-file ${workspaceFolder}/../tmp_rootfs/bin/libc_test",
|
||||||
|
"description": "/bin/libc_test (0x00600000)",
|
||||||
|
"ignoreFailures": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "source ${workspaceFolder}/../tools/.gdbinit"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"preLaunchTask": "QEMU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Debug Kernel (arm64)",
|
||||||
|
"type": "cppdbg",
|
||||||
|
"request": "launch",
|
||||||
|
"program": "${workspaceFolder}/../Kernel/fennix.elf",
|
||||||
|
"cwd": "${workspaceFolder}",
|
||||||
|
"targetArchitecture": "arm64",
|
||||||
|
"MIMode": "gdb",
|
||||||
|
"miDebuggerServerAddress": "/tmp/gdb-fennix",
|
||||||
|
"miDebuggerPath": "${workspaceFolder}/../tools/cross/bin/aarch64-fennix-gdb",
|
||||||
|
"externalConsole": false,
|
||||||
|
"internalConsoleOptions": "neverOpen",
|
||||||
|
"setupCommands": [
|
||||||
|
{
|
||||||
|
"text": "set breakpoint pending on",
|
||||||
|
"description": "Make breakpoint pending on future shared library load."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "add-symbol-file ${workspaceFolder}/../tmp_rootfs/bin/utest",
|
||||||
|
"description": "/bin/utest (0x00400000)",
|
||||||
|
"ignoreFailures": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "add-symbol-file ${workspaceFolder}/../tmp_rootfs/bin/libc_test",
|
||||||
|
"description": "/bin/libc_test (0x00600000)",
|
||||||
|
"ignoreFailures": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "source ${workspaceFolder}/../tools/.gdbinit"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"preLaunchTask": "QEMU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Debug Kernel (arm)",
|
||||||
|
"type": "cppdbg",
|
||||||
|
"request": "launch",
|
||||||
|
"program": "${workspaceFolder}/../Kernel/fennix.elf",
|
||||||
|
"cwd": "${workspaceFolder}",
|
||||||
|
"targetArchitecture": "arm",
|
||||||
|
"MIMode": "gdb",
|
||||||
|
"miDebuggerServerAddress": "/tmp/gdb-fennix",
|
||||||
|
"miDebuggerPath": "${workspaceFolder}/../tools/cross/bin/arm-fennix-gdb",
|
||||||
|
"externalConsole": false,
|
||||||
|
"internalConsoleOptions": "neverOpen",
|
||||||
|
"setupCommands": [
|
||||||
|
{
|
||||||
|
"text": "set breakpoint pending on",
|
||||||
|
"description": "Make breakpoint pending on future shared library load."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "add-symbol-file ${workspaceFolder}/../tmp_rootfs/bin/utest",
|
||||||
|
"description": "/bin/utest (0x00400000)",
|
||||||
|
"ignoreFailures": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "add-symbol-file ${workspaceFolder}/../tmp_rootfs/bin/libc_test",
|
||||||
|
"description": "/bin/libc_test (0x00600000)",
|
||||||
|
"ignoreFailures": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "source ${workspaceFolder}/../tools/.gdbinit"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"preLaunchTask": "QEMU"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "gdb",
|
"type": "gdb",
|
||||||
"request": "attach",
|
"request": "attach",
|
||||||
"name": "Launch QEMU & attach to gdbserver",
|
"name": "Launch QEMU & attach to gdbserver (x64)",
|
||||||
"executable": "${workspaceFolder}/../Kernel/fennix.elf",
|
"executable": "${workspaceFolder}/../Kernel/fennix.elf",
|
||||||
"target": "/tmp/gdb-fennix",
|
"target": "/tmp/gdb-fennix",
|
||||||
"remote": true,
|
"remote": true,
|
||||||
@ -63,7 +149,7 @@
|
|||||||
],
|
],
|
||||||
"internalConsoleOptions": "neverOpen",
|
"internalConsoleOptions": "neverOpen",
|
||||||
"printCalls": false,
|
"printCalls": false,
|
||||||
"preLaunchTask": "launch-qemu"
|
"preLaunchTask": "QEMU"
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@ -16,5 +16,6 @@
|
|||||||
"**/tools/qemu/**": true,
|
"**/tools/qemu/**": true,
|
||||||
"**/tools/cross/**": true,
|
"**/tools/cross/**": true,
|
||||||
"**/doxygen-doc/**": true,
|
"**/doxygen-doc/**": true,
|
||||||
}
|
},
|
||||||
|
"cmake.ignoreCMakeListsMissing": true
|
||||||
}
|
}
|
478
.vscode/tasks.json
vendored
478
.vscode/tasks.json
vendored
@ -2,13 +2,240 @@
|
|||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"tasks": [
|
"tasks": [
|
||||||
{
|
{
|
||||||
"label": "launch-qemu",
|
"label": "Clean",
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
"command": "make -C ../ build && make -C ../ vscode_debug_only",
|
"command": "make clean",
|
||||||
"isBackground": true,
|
"isBackground": false,
|
||||||
"problemMatcher": [],
|
"hide": false,
|
||||||
"group": {
|
"group": {
|
||||||
"kind": "build",
|
"kind": "build",
|
||||||
|
"isDefault": false
|
||||||
|
},
|
||||||
|
"presentation": {
|
||||||
|
"reveal": "never",
|
||||||
|
"panel": "shared"
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"cwd": "${workspaceFolder}/../",
|
||||||
|
"shell": {
|
||||||
|
"executable": "bash",
|
||||||
|
"args": [
|
||||||
|
"-c"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Build",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "make build",
|
||||||
|
"isBackground": false,
|
||||||
|
"hide": false,
|
||||||
|
"group": {
|
||||||
|
"kind": "build",
|
||||||
|
"isDefault": false
|
||||||
|
},
|
||||||
|
"presentation": {
|
||||||
|
"reveal": "always",
|
||||||
|
"panel": "shared"
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"cwd": "${workspaceFolder}/../",
|
||||||
|
"shell": {
|
||||||
|
"executable": "bash",
|
||||||
|
"args": [
|
||||||
|
"-c"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Run",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "make qemu",
|
||||||
|
"isBackground": false,
|
||||||
|
"hide": false,
|
||||||
|
"dependsOn": [
|
||||||
|
"Build"
|
||||||
|
],
|
||||||
|
"group": {
|
||||||
|
"kind": "test",
|
||||||
|
"isDefault": true
|
||||||
|
},
|
||||||
|
"presentation": {
|
||||||
|
"reveal": "always",
|
||||||
|
"panel": "shared"
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"cwd": "${workspaceFolder}/../",
|
||||||
|
"shell": {
|
||||||
|
"executable": "bash",
|
||||||
|
"args": [
|
||||||
|
"-c"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Build Bootloader",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "make -C ../ build_bootloader",
|
||||||
|
"isBackground": false,
|
||||||
|
"hide": true,
|
||||||
|
"group": {
|
||||||
|
"kind": "build",
|
||||||
|
"isDefault": false
|
||||||
|
},
|
||||||
|
"presentation": {
|
||||||
|
"reveal": "always",
|
||||||
|
"panel": "shared"
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"shell": {
|
||||||
|
"executable": "bash",
|
||||||
|
"args": [
|
||||||
|
"-c"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Build Kernel",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "make -C ../ build_kernel",
|
||||||
|
"isBackground": false,
|
||||||
|
"hide": true,
|
||||||
|
"dependsOn": [
|
||||||
|
"Build Bootloader"
|
||||||
|
],
|
||||||
|
"group": {
|
||||||
|
"kind": "build",
|
||||||
|
"isDefault": false
|
||||||
|
},
|
||||||
|
"presentation": {
|
||||||
|
"reveal": "always",
|
||||||
|
"panel": "shared"
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"shell": {
|
||||||
|
"executable": "bash",
|
||||||
|
"args": [
|
||||||
|
"-c"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Build Drivers",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "make -C ../ build_drivers",
|
||||||
|
"isBackground": false,
|
||||||
|
"hide": true,
|
||||||
|
"dependsOn": [
|
||||||
|
"Build Kernel"
|
||||||
|
],
|
||||||
|
"group": {
|
||||||
|
"kind": "build",
|
||||||
|
"isDefault": false
|
||||||
|
},
|
||||||
|
"presentation": {
|
||||||
|
"reveal": "always",
|
||||||
|
"panel": "shared"
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"shell": {
|
||||||
|
"executable": "bash",
|
||||||
|
"args": [
|
||||||
|
"-c"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Build Userspace",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "make -C ../ build_userspace",
|
||||||
|
"isBackground": false,
|
||||||
|
"hide": true,
|
||||||
|
"dependsOn": [
|
||||||
|
"Build Drivers"
|
||||||
|
],
|
||||||
|
"group": {
|
||||||
|
"kind": "build",
|
||||||
|
"isDefault": false
|
||||||
|
},
|
||||||
|
"presentation": {
|
||||||
|
"reveal": "always",
|
||||||
|
"panel": "shared"
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"shell": {
|
||||||
|
"executable": "bash",
|
||||||
|
"args": [
|
||||||
|
"-c"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Build Image",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "make -C ../ build_image",
|
||||||
|
"isBackground": false,
|
||||||
|
"hide": true,
|
||||||
|
"dependsOn": [
|
||||||
|
"Build Userspace"
|
||||||
|
],
|
||||||
|
"group": {
|
||||||
|
"kind": "build",
|
||||||
|
"isDefault": false
|
||||||
|
},
|
||||||
|
"presentation": {
|
||||||
|
"reveal": "always",
|
||||||
|
"panel": "shared"
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"shell": {
|
||||||
|
"executable": "bash",
|
||||||
|
"args": [
|
||||||
|
"-c"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "QEMU",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "make",
|
||||||
|
"args": [
|
||||||
|
"-C",
|
||||||
|
"../",
|
||||||
|
"vscode_debug_only"
|
||||||
|
],
|
||||||
|
"isBackground": true,
|
||||||
|
// "problemMatcher": "$tsc-watch",
|
||||||
|
"problemMatcher": [
|
||||||
|
{
|
||||||
|
"pattern": [
|
||||||
|
{
|
||||||
|
"regexp": ".",
|
||||||
|
"file": 1,
|
||||||
|
"location": 2,
|
||||||
|
"message": 3
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"background": {
|
||||||
|
"activeOnStart": true,
|
||||||
|
"beginsPattern": ".",
|
||||||
|
"endsPattern": "CPU Reset",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"dependsOn": [
|
||||||
|
"Build Image"
|
||||||
|
],
|
||||||
|
"group": {
|
||||||
|
"kind": "test",
|
||||||
"isDefault": true
|
"isDefault": true
|
||||||
},
|
},
|
||||||
"presentation": {
|
"presentation": {
|
||||||
@ -23,6 +250,249 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "CI AMD64 Debug",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "make __ci-amd64-debug",
|
||||||
|
"isBackground": false,
|
||||||
|
"hide": true,
|
||||||
|
"dependsOn": [
|
||||||
|
"Clean"
|
||||||
|
],
|
||||||
|
"group": {
|
||||||
|
"kind": "build",
|
||||||
|
"isDefault": false
|
||||||
|
},
|
||||||
|
"presentation": {
|
||||||
|
"reveal": "always",
|
||||||
|
"panel": "shared"
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"cwd": "${workspaceFolder}/../",
|
||||||
|
"shell": {
|
||||||
|
"executable": "bash",
|
||||||
|
"args": [
|
||||||
|
"-c"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "CI AMD64 Release",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "make __ci-amd64-release",
|
||||||
|
"isBackground": false,
|
||||||
|
"hide": true,
|
||||||
|
"dependsOn": [
|
||||||
|
"CI AMD64 Debug"
|
||||||
|
],
|
||||||
|
"group": {
|
||||||
|
"kind": "build",
|
||||||
|
"isDefault": false
|
||||||
|
},
|
||||||
|
"presentation": {
|
||||||
|
"reveal": "always",
|
||||||
|
"panel": "shared"
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"cwd": "${workspaceFolder}/../",
|
||||||
|
"shell": {
|
||||||
|
"executable": "bash",
|
||||||
|
"args": [
|
||||||
|
"-c"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "CI i386 Debug",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "make __ci-i386-debug",
|
||||||
|
"isBackground": false,
|
||||||
|
"hide": true,
|
||||||
|
"dependsOn": [
|
||||||
|
"CI AMD64 Release"
|
||||||
|
],
|
||||||
|
"group": {
|
||||||
|
"kind": "build",
|
||||||
|
"isDefault": false
|
||||||
|
},
|
||||||
|
"presentation": {
|
||||||
|
"reveal": "always",
|
||||||
|
"panel": "shared"
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"cwd": "${workspaceFolder}/../",
|
||||||
|
"shell": {
|
||||||
|
"executable": "bash",
|
||||||
|
"args": [
|
||||||
|
"-c"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "CI i386 Release",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "make __ci-i386-release",
|
||||||
|
"isBackground": false,
|
||||||
|
"hide": true,
|
||||||
|
"dependsOn": [
|
||||||
|
"CI i386 Debug"
|
||||||
|
],
|
||||||
|
"group": {
|
||||||
|
"kind": "build",
|
||||||
|
"isDefault": false
|
||||||
|
},
|
||||||
|
"presentation": {
|
||||||
|
"reveal": "always",
|
||||||
|
"panel": "shared"
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"cwd": "${workspaceFolder}/../",
|
||||||
|
"shell": {
|
||||||
|
"executable": "bash",
|
||||||
|
"args": [
|
||||||
|
"-c"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "CI ARM Debug",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "make __ci-arm-debug",
|
||||||
|
"isBackground": false,
|
||||||
|
"hide": true,
|
||||||
|
"dependsOn": [
|
||||||
|
"CI i386 Release"
|
||||||
|
],
|
||||||
|
"group": {
|
||||||
|
"kind": "build",
|
||||||
|
"isDefault": false
|
||||||
|
},
|
||||||
|
"presentation": {
|
||||||
|
"reveal": "always",
|
||||||
|
"panel": "shared"
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"cwd": "${workspaceFolder}/../",
|
||||||
|
"shell": {
|
||||||
|
"executable": "bash",
|
||||||
|
"args": [
|
||||||
|
"-c"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "CI ARM Release",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "make __ci-arm-release",
|
||||||
|
"isBackground": false,
|
||||||
|
"hide": true,
|
||||||
|
"dependsOn": [
|
||||||
|
"CI ARM Debug"
|
||||||
|
],
|
||||||
|
"group": {
|
||||||
|
"kind": "build",
|
||||||
|
"isDefault": false
|
||||||
|
},
|
||||||
|
"presentation": {
|
||||||
|
"reveal": "always",
|
||||||
|
"panel": "shared"
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"cwd": "${workspaceFolder}/../",
|
||||||
|
"shell": {
|
||||||
|
"executable": "bash",
|
||||||
|
"args": [
|
||||||
|
"-c"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "CI AARCH64 Debug",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "make __ci-aarch64-debug",
|
||||||
|
"isBackground": false,
|
||||||
|
"hide": true,
|
||||||
|
"dependsOn": [
|
||||||
|
"CI ARM Release"
|
||||||
|
],
|
||||||
|
"group": {
|
||||||
|
"kind": "build",
|
||||||
|
"isDefault": false
|
||||||
|
},
|
||||||
|
"presentation": {
|
||||||
|
"reveal": "always",
|
||||||
|
"panel": "shared"
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"cwd": "${workspaceFolder}/../",
|
||||||
|
"shell": {
|
||||||
|
"executable": "bash",
|
||||||
|
"args": [
|
||||||
|
"-c"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "CI AARCH64 Release",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "make __ci-aarch64-release",
|
||||||
|
"isBackground": false,
|
||||||
|
"hide": true,
|
||||||
|
"dependsOn": [
|
||||||
|
"CI AARCH64 Debug"
|
||||||
|
],
|
||||||
|
"group": {
|
||||||
|
"kind": "build",
|
||||||
|
"isDefault": false
|
||||||
|
},
|
||||||
|
"presentation": {
|
||||||
|
"reveal": "always",
|
||||||
|
"panel": "shared"
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"cwd": "${workspaceFolder}/../",
|
||||||
|
"shell": {
|
||||||
|
"executable": "bash",
|
||||||
|
"args": [
|
||||||
|
"-c"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Test CI Build",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "make __ci-restore-config",
|
||||||
|
"isBackground": false,
|
||||||
|
"dependsOn": [
|
||||||
|
"CI AARCH64 Release",
|
||||||
|
"clean"
|
||||||
|
],
|
||||||
|
"group": {
|
||||||
|
"kind": "build",
|
||||||
|
"isDefault": false
|
||||||
|
},
|
||||||
|
"presentation": {
|
||||||
|
"reveal": "always",
|
||||||
|
"panel": "shared"
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"cwd": "${workspaceFolder}/../",
|
||||||
|
"shell": {
|
||||||
|
"executable": "bash",
|
||||||
|
"args": [
|
||||||
|
"-c"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
13
Bootloader/.editorconfig
Normal file
13
Bootloader/.editorconfig
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# EditorConfig is awesome: https://editorconfig.org
|
||||||
|
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
end_of_line = lf
|
||||||
|
insert_final_newline = true
|
||||||
|
indent_style = tab
|
||||||
|
indent_size = 4
|
||||||
|
|
||||||
|
[Makefile]
|
||||||
|
indent_style = tab
|
10
Bootloader/.gitignore
vendored
Normal file
10
Bootloader/.gitignore
vendored
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
gnu-efi
|
||||||
|
include/*
|
||||||
|
!include/stdbool.h
|
||||||
|
!include/types.h
|
||||||
|
*.o
|
||||||
|
*.su
|
||||||
|
*.EFI
|
||||||
|
*.map
|
||||||
|
*.bin
|
||||||
|
*.elf
|
96
Bootloader/.vscode/c_boilerplates.code-snippets
vendored
Normal file
96
Bootloader/.vscode/c_boilerplates.code-snippets
vendored
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
{
|
||||||
|
"Lynx Bootloader C++ Header": {
|
||||||
|
"isFileTemplate": true,
|
||||||
|
"scope": "c,cpp",
|
||||||
|
"prefix": [
|
||||||
|
"head",
|
||||||
|
],
|
||||||
|
"body": [
|
||||||
|
"/*",
|
||||||
|
"\tThis file is part of Lynx Bootloader.",
|
||||||
|
"",
|
||||||
|
"\tLynx Bootloader is free software: you can redistribute it and/or",
|
||||||
|
"\tmodify it under the terms of the GNU General Public License as",
|
||||||
|
"\tpublished by the Free Software Foundation, either version 3 of",
|
||||||
|
"\tthe License, or (at your option) any later version.",
|
||||||
|
"",
|
||||||
|
"\tLynx Bootloader is distributed in the hope that it will be useful,",
|
||||||
|
"\tbut WITHOUT ANY WARRANTY; without even the implied warranty of",
|
||||||
|
"\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the",
|
||||||
|
"\tGNU General Public License for more details.",
|
||||||
|
"",
|
||||||
|
"\tYou should have received a copy of the GNU General Public License",
|
||||||
|
"\talong with Lynx Bootloader. If not, see <https://www.gnu.org/licenses/>.",
|
||||||
|
"*/",
|
||||||
|
"",
|
||||||
|
"#pragma once",
|
||||||
|
"",
|
||||||
|
"$0",
|
||||||
|
"",
|
||||||
|
"$1",
|
||||||
|
""
|
||||||
|
],
|
||||||
|
"description": "Create kernel header."
|
||||||
|
},
|
||||||
|
"Lynx Bootloader C Header": {
|
||||||
|
"isFileTemplate": true,
|
||||||
|
"scope": "c,cpp",
|
||||||
|
"prefix": [
|
||||||
|
"headc",
|
||||||
|
],
|
||||||
|
"body": [
|
||||||
|
"/*",
|
||||||
|
"\tThis file is part of Lynx Bootloader.",
|
||||||
|
"",
|
||||||
|
"\tLynx Bootloader is free software: you can redistribute it and/or",
|
||||||
|
"\tmodify it under the terms of the GNU General Public License as",
|
||||||
|
"\tpublished by the Free Software Foundation, either version 3 of",
|
||||||
|
"\tthe License, or (at your option) any later version.",
|
||||||
|
"",
|
||||||
|
"\tLynx Bootloader is distributed in the hope that it will be useful,",
|
||||||
|
"\tbut WITHOUT ANY WARRANTY; without even the implied warranty of",
|
||||||
|
"\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the",
|
||||||
|
"\tGNU General Public License for more details.",
|
||||||
|
"",
|
||||||
|
"\tYou should have received a copy of the GNU General Public License",
|
||||||
|
"\talong with Lynx Bootloader. If not, see <https://www.gnu.org/licenses/>.",
|
||||||
|
"*/",
|
||||||
|
"",
|
||||||
|
"#ifndef __LYNX_BOOTLOADER_${1:header}_H__",
|
||||||
|
"#define __LYNX_BOOTLOADER_${1:header}_H__",
|
||||||
|
"",
|
||||||
|
"#include <types.h>",
|
||||||
|
"",
|
||||||
|
"$0",
|
||||||
|
"",
|
||||||
|
"#endif // !__LYNX_BOOTLOADER_${1:header}_H__",
|
||||||
|
""
|
||||||
|
],
|
||||||
|
"description": "Create kernel header."
|
||||||
|
},
|
||||||
|
"License": {
|
||||||
|
"isFileTemplate": true,
|
||||||
|
"prefix": [
|
||||||
|
"license",
|
||||||
|
],
|
||||||
|
"body": [
|
||||||
|
"/*",
|
||||||
|
"\tThis file is part of Lynx Bootloader.",
|
||||||
|
"",
|
||||||
|
"\tLynx Bootloader is free software: you can redistribute it and/or",
|
||||||
|
"\tmodify it under the terms of the GNU General Public License as",
|
||||||
|
"\tpublished by the Free Software Foundation, either version 3 of",
|
||||||
|
"\tthe License, or (at your option) any later version.",
|
||||||
|
"",
|
||||||
|
"\tLynx Bootloader is distributed in the hope that it will be useful,",
|
||||||
|
"\tbut WITHOUT ANY WARRANTY; without even the implied warranty of",
|
||||||
|
"\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the",
|
||||||
|
"\tGNU General Public License for more details.",
|
||||||
|
"",
|
||||||
|
"\tYou should have received a copy of the GNU General Public License",
|
||||||
|
"\talong with Lynx Bootloader. If not, see <https://www.gnu.org/licenses/>.",
|
||||||
|
"*/"
|
||||||
|
],
|
||||||
|
"description": "Create kernel license."
|
||||||
|
}
|
||||||
|
}
|
184
Bootloader/.vscode/c_cpp_properties.json
vendored
Normal file
184
Bootloader/.vscode/c_cpp_properties.json
vendored
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
{
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Fennix x64 (Linux, GCC, debug)",
|
||||||
|
"includePath": [
|
||||||
|
"${workspaceFolder}/include",
|
||||||
|
"${workspaceFolder}/include/**"
|
||||||
|
],
|
||||||
|
"defines": [
|
||||||
|
"DEBUG=\"1\""
|
||||||
|
],
|
||||||
|
"forcedInclude": [
|
||||||
|
"${workspaceFolder}/.vscode/preinclude.h"
|
||||||
|
],
|
||||||
|
"compilerPath": "${workspaceFolder}/../tools/cross/bin/x86_64-fennix-gcc",
|
||||||
|
"cStandard": "c17",
|
||||||
|
"cppStandard": "c++20",
|
||||||
|
"intelliSenseMode": "gcc-x64",
|
||||||
|
"configurationProvider": "ms-vscode.makefile-tools",
|
||||||
|
"compilerArgs": [
|
||||||
|
// Compiler flags
|
||||||
|
"-fno-pic",
|
||||||
|
"-fno-pie",
|
||||||
|
"-mno-red-zone",
|
||||||
|
"-march=core2",
|
||||||
|
"-pipe",
|
||||||
|
"-mcmodel=kernel",
|
||||||
|
"-fno-builtin",
|
||||||
|
"-m64",
|
||||||
|
"-fcoroutines",
|
||||||
|
// Warnings
|
||||||
|
"-Wall",
|
||||||
|
"-Wextra",
|
||||||
|
"-Wfloat-equal",
|
||||||
|
"-Wpointer-arith",
|
||||||
|
"-Wcast-align",
|
||||||
|
"-Wredundant-decls",
|
||||||
|
"-Winit-self",
|
||||||
|
"-Wswitch-default",
|
||||||
|
"-Wstrict-overflow=5",
|
||||||
|
"-Wconversion",
|
||||||
|
// C++ flags
|
||||||
|
"-fno-rtti",
|
||||||
|
"-fno-exceptions",
|
||||||
|
// Linker flags
|
||||||
|
"-T${workspaceFolder}/arch/amd64/linker.ld",
|
||||||
|
"-Wl,-static,--no-dynamic-linker,-ztext",
|
||||||
|
"-nostdlib",
|
||||||
|
"-nodefaultlibs",
|
||||||
|
"-nolibc",
|
||||||
|
"-zmax-page-size=0x1000",
|
||||||
|
"-shared",
|
||||||
|
// Debug flags
|
||||||
|
"-ggdb3",
|
||||||
|
"-O0",
|
||||||
|
"-fdiagnostics-color=always",
|
||||||
|
"-fverbose-asm",
|
||||||
|
"-fstack-usage",
|
||||||
|
"-fstack-check",
|
||||||
|
"-fsanitize=undefined",
|
||||||
|
// VSCode flags
|
||||||
|
"-ffreestanding",
|
||||||
|
"-nostdinc",
|
||||||
|
"-nostdinc++"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Fennix x32 (Linux, GCC, debug)",
|
||||||
|
"includePath": [
|
||||||
|
"${workspaceFolder}/include",
|
||||||
|
"${workspaceFolder}/include/**"
|
||||||
|
],
|
||||||
|
"forcedInclude": [
|
||||||
|
"${workspaceFolder}/.vscode/preinclude.h"
|
||||||
|
],
|
||||||
|
"defines": [
|
||||||
|
"DEBUG=\"1\""
|
||||||
|
],
|
||||||
|
"compilerPath": "${workspaceFolder}/../tools/cross/bin/i386-fennix-gcc",
|
||||||
|
"cStandard": "c17",
|
||||||
|
"cppStandard": "c++20",
|
||||||
|
"intelliSenseMode": "gcc-x86",
|
||||||
|
"configurationProvider": "ms-vscode.makefile-tools",
|
||||||
|
"compilerArgs": [
|
||||||
|
// Compiler flags
|
||||||
|
"-fno-pic",
|
||||||
|
"-fno-pie",
|
||||||
|
"-mno-80387",
|
||||||
|
"-mno-mmx",
|
||||||
|
"-mno-3dnow",
|
||||||
|
"-mno-red-zone",
|
||||||
|
"-march=pentium",
|
||||||
|
"-pipe",
|
||||||
|
"-msoft-float",
|
||||||
|
"-fno-builtin",
|
||||||
|
"-m32",
|
||||||
|
"-fcoroutines",
|
||||||
|
// Warnings
|
||||||
|
"-Wall",
|
||||||
|
"-Wextra",
|
||||||
|
"-Wfloat-equal",
|
||||||
|
"-Wpointer-arith",
|
||||||
|
"-Wcast-align",
|
||||||
|
"-Wredundant-decls",
|
||||||
|
"-Winit-self",
|
||||||
|
"-Wswitch-default",
|
||||||
|
"-Wstrict-overflow=5",
|
||||||
|
"-Wconversion",
|
||||||
|
// C++ flags
|
||||||
|
"-fno-rtti",
|
||||||
|
"-fno-exceptions",
|
||||||
|
// Linker flags
|
||||||
|
"-T${workspaceFolder}/arch/i386/linker.ld",
|
||||||
|
"-Wl,-static,--no-dynamic-linker,-ztext",
|
||||||
|
"-nostdlib",
|
||||||
|
"-nodefaultlibs",
|
||||||
|
"-nolibc",
|
||||||
|
"-zmax-page-size=0x1000",
|
||||||
|
"-shared",
|
||||||
|
// Debug flags
|
||||||
|
"-ggdb3",
|
||||||
|
"-O0",
|
||||||
|
"-fdiagnostics-color=always",
|
||||||
|
"-fverbose-asm",
|
||||||
|
"-fstack-usage",
|
||||||
|
"-fstack-check",
|
||||||
|
"-fsanitize=undefined",
|
||||||
|
// VSCode flags
|
||||||
|
"-ffreestanding",
|
||||||
|
"-nostdinc",
|
||||||
|
"-nostdinc++"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Fennix Arm (Linux, GCC, debug)",
|
||||||
|
"includePath": [
|
||||||
|
"${workspaceFolder}/include",
|
||||||
|
"${workspaceFolder}/include/**"
|
||||||
|
],
|
||||||
|
"forcedInclude": [
|
||||||
|
"${workspaceFolder}/.vscode/preinclude.h"
|
||||||
|
],
|
||||||
|
"defines": [
|
||||||
|
"DEBUG=\"1\""
|
||||||
|
],
|
||||||
|
"compilerPath": "${workspaceFolder}/../tools/cross/bin/arm-fennix-gcc",
|
||||||
|
"cStandard": "c17",
|
||||||
|
"cppStandard": "c++20",
|
||||||
|
"intelliSenseMode": "linux-gcc-arm",
|
||||||
|
"configurationProvider": "ms-vscode.makefile-tools",
|
||||||
|
"compilerArgs": [
|
||||||
|
// VSCode flags
|
||||||
|
"-ffreestanding",
|
||||||
|
"-nostdinc",
|
||||||
|
"-nostdinc++"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Fennix Aarch64 (Linux, GCC, debug)",
|
||||||
|
"includePath": [
|
||||||
|
"${workspaceFolder}/include",
|
||||||
|
"${workspaceFolder}/include/**"
|
||||||
|
],
|
||||||
|
"forcedInclude": [
|
||||||
|
"${workspaceFolder}/.vscode/preinclude.h"
|
||||||
|
],
|
||||||
|
"defines": [
|
||||||
|
"DEBUG=\"1\""
|
||||||
|
],
|
||||||
|
"compilerPath": "${workspaceFolder}/../tools/cross/bin/aarch64-fennix-gcc",
|
||||||
|
"cStandard": "c17",
|
||||||
|
"cppStandard": "c++20",
|
||||||
|
"intelliSenseMode": "linux-gcc-arm64",
|
||||||
|
"configurationProvider": "ms-vscode.makefile-tools",
|
||||||
|
"compilerArgs": [
|
||||||
|
// VSCode flags
|
||||||
|
"-ffreestanding",
|
||||||
|
"-nostdinc",
|
||||||
|
"-nostdinc++"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"version": 4
|
||||||
|
}
|
1
Bootloader/.vscode/launch.json
vendored
Symbolic link
1
Bootloader/.vscode/launch.json
vendored
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../.vscode/launch.json
|
11
Bootloader/.vscode/preinclude.h
vendored
Normal file
11
Bootloader/.vscode/preinclude.h
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#undef __linux__
|
||||||
|
#undef __WIN32__
|
||||||
|
#undef __WIN64__
|
||||||
|
#undef _WIN32
|
||||||
|
#undef _WIN64
|
||||||
|
#undef __APPLE__
|
||||||
|
#undef __clang__
|
||||||
|
#define __vscode__ 1
|
||||||
|
#define __kernel__ 1
|
||||||
|
#define GIT_COMMIT "0000000000000000000000000000000000000000"
|
||||||
|
#define GIT_COMMIT_SHORT "0000000"
|
23
Bootloader/.vscode/settings.json
vendored
Normal file
23
Bootloader/.vscode/settings.json
vendored
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"C_Cpp.errorSquiggles": "enabled",
|
||||||
|
"C_Cpp.autocompleteAddParentheses": true,
|
||||||
|
"C_Cpp.codeAnalysis.clangTidy.enabled": true,
|
||||||
|
"C_Cpp.clang_format_style": "Visual Studio",
|
||||||
|
"C_Cpp.default.intelliSenseMode": "gcc-x64",
|
||||||
|
"C_Cpp.default.cStandard": "c17",
|
||||||
|
"C_Cpp.default.cppStandard": "c++20",
|
||||||
|
"C_Cpp.intelliSenseMemoryLimit": 16384,
|
||||||
|
"editor.smoothScrolling": true,
|
||||||
|
"editor.cursorSmoothCaretAnimation": "on",
|
||||||
|
"C_Cpp.codeAnalysis.clangTidy.checks.disabled": [
|
||||||
|
"clang-analyzer-security.insecureAPI.strcpy",
|
||||||
|
"clang-diagnostic-unknown-warning-option",
|
||||||
|
"clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling",
|
||||||
|
"clang-diagnostic-implicit-exception-spec-mismatch",
|
||||||
|
"clang-diagnostic-unknown-attributes",
|
||||||
|
"clang-diagnostic-user-defined-literals",
|
||||||
|
"clang-diagnostic-non-pod-varargs",
|
||||||
|
"clang-diagnostic-non-pod-varargs",
|
||||||
|
"clang-diagnostic-non-pod-varargs"
|
||||||
|
]
|
||||||
|
}
|
1
Bootloader/.vscode/tasks.json
vendored
Symbolic link
1
Bootloader/.vscode/tasks.json
vendored
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../.vscode/tasks.json
|
56
Bootloader/Makefile
Normal file
56
Bootloader/Makefile
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
GNUEFI_RELEASE_VERSION=3.0.18
|
||||||
|
|
||||||
|
GIT_COMMIT = $(shell git rev-parse HEAD)
|
||||||
|
GIT_COMMIT_SHORT = $(shell git rev-parse --short HEAD)
|
||||||
|
|
||||||
|
export CC := $(__CONF_CC)
|
||||||
|
export CXX := $(__CONF_CXX)
|
||||||
|
export LD := $(__CONF_LD)
|
||||||
|
export AS := $(__CONF_AS)
|
||||||
|
export AR := $(__CONF_AR)
|
||||||
|
export NM := $(__CONF_NM)
|
||||||
|
export OBJCOPY := $(__CONF_OBJCOPY)
|
||||||
|
export OBJDUMP := $(__CONF_OBJDUMP)
|
||||||
|
export GDB := $(__CONF_GDB)
|
||||||
|
|
||||||
|
default:
|
||||||
|
$(error Do not run this Makefile directly!)
|
||||||
|
|
||||||
|
prepare:
|
||||||
|
ifeq ("$(wildcard ./gnu-efi)", "")
|
||||||
|
wget https://freefr.dl.sourceforge.net/project/gnu-efi/gnu-efi-$(GNUEFI_RELEASE_VERSION).tar.bz2
|
||||||
|
tar -xf gnu-efi-$(GNUEFI_RELEASE_VERSION).tar.bz2
|
||||||
|
rm gnu-efi-$(GNUEFI_RELEASE_VERSION).tar.bz2
|
||||||
|
mv ./gnu-efi-$(GNUEFI_RELEASE_VERSION) ./gnu-efi
|
||||||
|
cp -a ./gnu-efi/inc/. ./include
|
||||||
|
endif
|
||||||
|
# echo "PREPARE > Compiling gnu-efi for x86_64"
|
||||||
|
# make -C gnu-efi all ARCH=x86_64 \
|
||||||
|
# AR=$(TOOLCHAIN_AMD64_PREFIX)ar \
|
||||||
|
# AS=$(TOOLCHAIN_AMD64_PREFIX)as \
|
||||||
|
# CC=$(TOOLCHAIN_AMD64_PREFIX)gcc \
|
||||||
|
# LD=$(TOOLCHAIN_AMD64_PREFIX)ld
|
||||||
|
# echo "PREPARE > Compiling gnu-efi for arm"
|
||||||
|
# make -C gnu-efi all ARCH=arm \
|
||||||
|
# AR=$(TOOLCHAIN_ARM_PREFIX)ar \
|
||||||
|
# AS=$(TOOLCHAIN_ARM_PREFIX)as \
|
||||||
|
# CC=$(TOOLCHAIN_ARM_PREFIX)gcc \
|
||||||
|
# LD=$(TOOLCHAIN_ARM_PREFIX)ld \
|
||||||
|
# CFLAGS="-I$(CURDIR)/gnu-efi/inc"
|
||||||
|
# echo "PREPARE > Compiling gnu-efi for aarch64"
|
||||||
|
# make -C gnu-efi all ARCH=aarch64 \
|
||||||
|
# AR=$(TOOLCHAIN_AARCH64_PREFIX)ar \
|
||||||
|
# AS=$(TOOLCHAIN_AARCH64_PREFIX)as \
|
||||||
|
# CC=$(TOOLCHAIN_AARCH64_PREFIX)gcc \
|
||||||
|
# LD=$(TOOLCHAIN_AARCH64_PREFIX)ld
|
||||||
|
|
||||||
|
build:
|
||||||
|
$(MAKE) -C common build
|
||||||
|
$(MAKE) -C firmware build
|
||||||
|
# $(MAKE) -C uefi build
|
||||||
|
|
||||||
|
clean:
|
||||||
|
$(MAKE) -C common clean
|
||||||
|
$(MAKE) -C firmware clean
|
||||||
|
# $(MAKE) -C uefi clean
|
||||||
|
rm -f boot.bin
|
13
Bootloader/README.md
Normal file
13
Bootloader/README.md
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# Lynx Bootloader
|
||||||
|
|
||||||
|
> [!CAUTION]
|
||||||
|
> The project is in early stages of development and is not yet ready for production use.
|
||||||
|
>
|
||||||
|
> Use at your own risk.
|
||||||
|
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
|
||||||
|
### [bios](bios)
|
||||||
|
|
||||||
|
### [uefi](uefi)
|
19
Bootloader/common/Makefile
Normal file
19
Bootloader/common/Makefile
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
define find-sources
|
||||||
|
$(shell find ./ -type f -name '$1' -print0 | xargs -0)
|
||||||
|
endef
|
||||||
|
|
||||||
|
BMP_SOURCES := $(call find-sources,*.bmp)
|
||||||
|
PSF_SOURCES := $(call find-sources,*.psf)
|
||||||
|
S_SOURCES := $(call find-sources,*.S)
|
||||||
|
s_SOURCES := $(call find-sources,*.s)
|
||||||
|
C_SOURCES := $(call find-sources,*.c)
|
||||||
|
CXX_SOURCES := $(call find-sources,*.cpp)
|
||||||
|
|
||||||
|
OBJ = $(BMP_SOURCES:.bmp=.o) $(PSF_SOURCES:.psf=.o) $(s_SOURCES:.s=.o) $(S_SOURCES:.S=.o) $(C_SOURCES:.c=.o) $(CXX_SOURCES:.cpp=.o)
|
||||||
|
|
||||||
|
default:
|
||||||
|
$(error Do not run this Makefile directly!)
|
||||||
|
|
||||||
|
build:
|
||||||
|
|
||||||
|
clean:
|
21
Bootloader/common/main.c
Normal file
21
Bootloader/common/main.c
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Lynx Bootloader.
|
||||||
|
|
||||||
|
Lynx Bootloader is free software: you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation, either version 3 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
Lynx Bootloader is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Lynx Bootloader. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
8
Bootloader/firmware/Makefile
Normal file
8
Bootloader/firmware/Makefile
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
default:
|
||||||
|
$(error Do not run this Makefile directly!)
|
||||||
|
|
||||||
|
build:
|
||||||
|
$(MAKE) -C $(OSARCH) build
|
||||||
|
|
||||||
|
clean:
|
||||||
|
$(MAKE) -C $(OSARCH) clean
|
64
Bootloader/firmware/aarch64/Makefile
Normal file
64
Bootloader/firmware/aarch64/Makefile
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
define find-sources
|
||||||
|
$(shell find ./ -type f -name '$1' $(shell echo $(foreach board,$(filter-out $(BOARD_TYPE),$(AVAILABLE_BOARDS)), -not -path \"./$(board)/*\")) -print0 | xargs -0)
|
||||||
|
endef
|
||||||
|
|
||||||
|
S_SOURCES := $(call find-sources,*.S)
|
||||||
|
s_SOURCES := $(call find-sources,*.s)
|
||||||
|
C_SOURCES := $(call find-sources,*.c)
|
||||||
|
|
||||||
|
define find-common-sources
|
||||||
|
$(shell find ../../common -type f -name '$1' -print0 | xargs -0)
|
||||||
|
endef
|
||||||
|
|
||||||
|
C_COMMON_SOURCES := $(call find-common-sources,*.c)
|
||||||
|
|
||||||
|
OBJ = $(s_SOURCES:.s=.o) $(S_SOURCES:.S=.o) $(C_SOURCES:.c=.o) $(C_COMMON_SOURCES:.c=.o)
|
||||||
|
|
||||||
|
LDFLAGS = -static -nostdlib -nodefaultlibs -nolibc \
|
||||||
|
-Wl,-static,--no-dynamic-linker,-ztext \
|
||||||
|
-zmax-page-size=0x1000 \
|
||||||
|
-Wl,-Map boot.map -fno-pic -fno-pie
|
||||||
|
|
||||||
|
CFLAGS := \
|
||||||
|
$(INCLUDE_DIR) \
|
||||||
|
-D__kernel__='1' \
|
||||||
|
-DGIT_COMMIT='"$(GIT_COMMIT)"' \
|
||||||
|
-DGIT_COMMIT_SHORT='"$(GIT_COMMIT_SHORT)"' \
|
||||||
|
-fno-pic -fno-pie -fno-builtin -I../../include
|
||||||
|
|
||||||
|
CFLAGS += -mcmodel=large
|
||||||
|
LDFLAGS += -T$(BOARD_TYPE)/linker.ld
|
||||||
|
|
||||||
|
ifeq ($(DEBUG), 1)
|
||||||
|
CFLAGS += -DDEBUG -ggdb3 -O0 -fdiagnostics-color=always
|
||||||
|
# CFLAGS += -fsanitize=undefined
|
||||||
|
CFLAGS += -fstack-check -fverbose-asm
|
||||||
|
LDFLAGS += -ggdb3 -O0
|
||||||
|
ASFLAGS += -g --gstabs+ --gdwarf-5 -D
|
||||||
|
endif # DEBUG
|
||||||
|
|
||||||
|
default:
|
||||||
|
$(error Do not run this Makefile directly!)
|
||||||
|
|
||||||
|
build: boot.bin
|
||||||
|
|
||||||
|
boot.bin: $(OBJ)
|
||||||
|
$(info Linking $@)
|
||||||
|
$(CC) $(LDFLAGS) $(OBJ) -o tmp.elf
|
||||||
|
$(OBJCOPY) tmp.elf -O binary ../../boot.bin
|
||||||
|
# rm tmp.elf
|
||||||
|
|
||||||
|
%.o: %.c $(HEADERS)
|
||||||
|
$(info Compiling $<)
|
||||||
|
$(CC) $(CFLAGS) -fstack-protector-all -std=c17 -c $< -o $@
|
||||||
|
|
||||||
|
%.o: %.S
|
||||||
|
$(info Compiling $<)
|
||||||
|
$(AS) $(ASFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
%.o: %.s
|
||||||
|
$(info Compiling $<)
|
||||||
|
$(AS) $(ASFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f $(OBJ) boot.map
|
1
Bootloader/firmware/aarch64/raspi3
Symbolic link
1
Bootloader/firmware/aarch64/raspi3
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
./raspi4
|
49
Bootloader/firmware/aarch64/raspi4/boot.S
Normal file
49
Bootloader/firmware/aarch64/raspi4/boot.S
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Lynx Bootloader.
|
||||||
|
|
||||||
|
Lynx Bootloader is free software: you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation, either version 3 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
Lynx Bootloader is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Lynx Bootloader. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.section ".text.boot"
|
||||||
|
|
||||||
|
.extern __bss_start
|
||||||
|
.extern __bss_end
|
||||||
|
.extern __bss_size
|
||||||
|
|
||||||
|
.global _start
|
||||||
|
_start:
|
||||||
|
/* Keep only the main core */
|
||||||
|
mrs x1, mpidr_el1
|
||||||
|
and x1, x1, #3
|
||||||
|
cbz x1, 2f
|
||||||
|
|
||||||
|
/* Halt */
|
||||||
|
1: wfe
|
||||||
|
b 1b
|
||||||
|
|
||||||
|
/* Initialize the stack */
|
||||||
|
2: ldr x1, =_start
|
||||||
|
mov sp, x1
|
||||||
|
|
||||||
|
/* Clear the BSS */
|
||||||
|
ldr x1, =__bss_start
|
||||||
|
ldr w2, =__bss_size
|
||||||
|
3: cbz w2, 4f
|
||||||
|
str xzr, [x1], #8
|
||||||
|
sub w2, w2, #1
|
||||||
|
cbnz w2, 3b
|
||||||
|
|
||||||
|
/* Start the kernel */
|
||||||
|
4: bl _aarch64_start
|
||||||
|
b 1b
|
32
Bootloader/firmware/aarch64/raspi4/init.c
Normal file
32
Bootloader/firmware/aarch64/raspi4/init.c
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Lynx Bootloader.
|
||||||
|
|
||||||
|
Lynx Bootloader is free software: you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation, either version 3 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
Lynx Bootloader is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Lynx Bootloader. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
uintptr_t __stack_chk_guard = 0;
|
||||||
|
|
||||||
|
__noreturn __no_stack_protector void __stack_chk_fail(void)
|
||||||
|
{
|
||||||
|
while (1)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main();
|
||||||
|
__attribute__((section(".bootstrap.text"))) void _aarch64_start(uint64_t dtb_ptr32, uint64_t x1, uint64_t x2, uint64_t x3)
|
||||||
|
{
|
||||||
|
main();
|
||||||
|
}
|
70
Bootloader/firmware/aarch64/raspi4/linker.ld
Normal file
70
Bootloader/firmware/aarch64/raspi4/linker.ld
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Lynx Bootloader.
|
||||||
|
|
||||||
|
Lynx Bootloader is free software: you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation, either version 3 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
Lynx Bootloader is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Lynx Bootloader. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
OUTPUT_FORMAT("elf64-littleaarch64")
|
||||||
|
OUTPUT_ARCH(aarch64)
|
||||||
|
|
||||||
|
ENTRY(_start)
|
||||||
|
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
. = 0x80000;
|
||||||
|
__start = .;
|
||||||
|
__text_start = .;
|
||||||
|
.text :
|
||||||
|
{
|
||||||
|
KEEP(*(.text.boot))
|
||||||
|
*(.text)
|
||||||
|
}
|
||||||
|
. = ALIGN(4096);
|
||||||
|
__text_end = .;
|
||||||
|
|
||||||
|
__rodata_start = .;
|
||||||
|
.rodata :
|
||||||
|
{
|
||||||
|
*(.rodata)
|
||||||
|
}
|
||||||
|
. = ALIGN(4096);
|
||||||
|
__rodata_end = .;
|
||||||
|
|
||||||
|
__data_start = .;
|
||||||
|
.data :
|
||||||
|
{
|
||||||
|
*(.data)
|
||||||
|
}
|
||||||
|
. = ALIGN(4096);
|
||||||
|
__data_end = .;
|
||||||
|
|
||||||
|
__bss_start = .;
|
||||||
|
.bss :
|
||||||
|
{
|
||||||
|
bss = .;
|
||||||
|
*(.bss)
|
||||||
|
}
|
||||||
|
. = ALIGN(4096);
|
||||||
|
__bss_end = .;
|
||||||
|
__bss_size = __bss_end - __bss_start; /* SIZEOF(.bss); */
|
||||||
|
__end = .;
|
||||||
|
|
||||||
|
/DISCARD/ :
|
||||||
|
{
|
||||||
|
*(.comment*)
|
||||||
|
*(.gnu*)
|
||||||
|
*(.note*)
|
||||||
|
*(.eh_frame*)
|
||||||
|
}
|
||||||
|
}
|
6
Bootloader/firmware/amd64/Makefile
Normal file
6
Bootloader/firmware/amd64/Makefile
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
default:
|
||||||
|
$(error Do not run this Makefile directly!)
|
||||||
|
|
||||||
|
build:
|
||||||
|
|
||||||
|
clean:
|
6
Bootloader/firmware/arm/Makefile
Normal file
6
Bootloader/firmware/arm/Makefile
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
default:
|
||||||
|
$(error Do not run this Makefile directly!)
|
||||||
|
|
||||||
|
build:
|
||||||
|
|
||||||
|
clean:
|
6
Bootloader/firmware/i386/Makefile
Normal file
6
Bootloader/firmware/i386/Makefile
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
default:
|
||||||
|
$(error Do not run this Makefile directly!)
|
||||||
|
|
||||||
|
build:
|
||||||
|
|
||||||
|
clean:
|
@ -1,25 +1,26 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of Fennix Drivers.
|
This file is part of Lynx Bootloader.
|
||||||
|
|
||||||
Fennix Drivers is free software: you can redistribute it and/or
|
Lynx Bootloader is free software: you can redistribute it and/or
|
||||||
modify it under the terms of the GNU General Public License as
|
modify it under the terms of the GNU General Public License as
|
||||||
published by the Free Software Foundation, either version 3 of
|
published by the Free Software Foundation, either version 3 of
|
||||||
the License, or (at your option) any later version.
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
Fennix Drivers is distributed in the hope that it will be useful,
|
Lynx Bootloader is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with Fennix Drivers. If not, see <https://www.gnu.org/licenses/>.
|
along with Lynx Bootloader. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#ifndef __STDBOOL_H__
|
||||||
|
#define __STDBOOL_H__
|
||||||
|
|
||||||
#include <types.h>
|
|
||||||
|
|
||||||
EXTERNC int cxx_Panic();
|
typedef int bool;
|
||||||
EXTERNC int cxx_Probe();
|
#define true 1
|
||||||
EXTERNC int cxx_Initialize();
|
#define false 0
|
||||||
EXTERNC int cxx_Finalize();
|
|
||||||
|
#endif /* __STDBOOL_H__ */
|
496
Bootloader/include/types.h
Normal file
496
Bootloader/include/types.h
Normal file
@ -0,0 +1,496 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Lynx Bootloader.
|
||||||
|
|
||||||
|
Lynx Bootloader is free software: you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation, either version 3 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
Lynx Bootloader is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Lynx Bootloader. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __FENNIX_KERNEL_TYPES_H__
|
||||||
|
#define __FENNIX_KERNEL_TYPES_H__
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* It doesn't do anything.
|
||||||
|
*
|
||||||
|
* Used to specify a function that is dependent on the architecture.
|
||||||
|
* It's architecture specific variant is defined in arch/<arch>/...
|
||||||
|
*/
|
||||||
|
#define arch
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
#define EXTERNC extern "C"
|
||||||
|
#define START_EXTERNC \
|
||||||
|
EXTERNC \
|
||||||
|
{
|
||||||
|
#define END_EXTERNC \
|
||||||
|
}
|
||||||
|
#else // __cplusplus
|
||||||
|
#define EXTERNC
|
||||||
|
#define START_EXTERNC
|
||||||
|
#define END_EXTERNC
|
||||||
|
#endif // __cplusplus
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
#define NULL 0
|
||||||
|
#else // __cplusplus
|
||||||
|
#define NULL ((void *)0)
|
||||||
|
#endif // __cplusplus
|
||||||
|
|
||||||
|
#define asm __asm__
|
||||||
|
#define asmv __asm__ volatile
|
||||||
|
|
||||||
|
#define inf_loop while (1)
|
||||||
|
#define ilp inf_loop; /* Used for debugging */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
#define foreach for
|
||||||
|
#define in :
|
||||||
|
|
||||||
|
#define forItr(itr, container) \
|
||||||
|
for (auto itr = container.begin(); \
|
||||||
|
itr != container.end(); ++itr)
|
||||||
|
|
||||||
|
#define r_cst(t, v) reinterpret_cast<t>(v)
|
||||||
|
#define c_cst(t, v) const_cast<t>(v)
|
||||||
|
#define s_cst(t, v) static_cast<t>(v)
|
||||||
|
#define d_cst(t, v) dynamic_cast<t>(v)
|
||||||
|
#endif // __cplusplus
|
||||||
|
|
||||||
|
#define UNUSED(x) (void)(x)
|
||||||
|
#define CONCAT(x, y) x##y
|
||||||
|
|
||||||
|
#ifndef __va_list__
|
||||||
|
typedef __builtin_va_list va_list;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define va_start(v, l) __builtin_va_start(v, l)
|
||||||
|
#define va_end(v) __builtin_va_end(v)
|
||||||
|
#define va_arg(v, l) __builtin_va_arg(v, l)
|
||||||
|
|
||||||
|
#define ALIGN_UP(x, align) ((__typeof__(x))(((uintptr_t)(x) + ((align) - 1)) & (~((align) - 1))))
|
||||||
|
#define ALIGN_DOWN(x, align) ((__typeof__(x))((x) & (~((align) - 1))))
|
||||||
|
|
||||||
|
#define offsetof(type, member) __builtin_offsetof(type, member)
|
||||||
|
|
||||||
|
#define RGB_TO_HEX(r, g, b) ((r << 16) | (g << 8) | (b))
|
||||||
|
|
||||||
|
#define MAX(a, b) \
|
||||||
|
({ \
|
||||||
|
__typeof__(a) _a = (a); \
|
||||||
|
__typeof__(b) _b = (b); \
|
||||||
|
_a > _b ? _a : _b; \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define MIN(a, b) \
|
||||||
|
({ \
|
||||||
|
__typeof__(a) _a = (a); \
|
||||||
|
__typeof__(b) _b = (b); \
|
||||||
|
_a < _b ? _a : _b; \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define ROUND_UP(x, y) (((x) + (y) - 1) & ~((y) - 1))
|
||||||
|
#define ROUND_DOWN(x, y) ((x) & ~((y) - 1))
|
||||||
|
|
||||||
|
#define VPOKE(type, address) (*((volatile type *)(address)))
|
||||||
|
#define POKE(type, address) (*((type *)(address)))
|
||||||
|
|
||||||
|
#ifndef __SIG_ATOMIC_TYPE__
|
||||||
|
#define __SIG_ATOMIC_TYPE__ int
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef __INT8_TYPE__ int8_t;
|
||||||
|
typedef __INT16_TYPE__ int16_t;
|
||||||
|
typedef __INT32_TYPE__ int32_t;
|
||||||
|
typedef __INT64_TYPE__ int64_t;
|
||||||
|
|
||||||
|
typedef __UINT8_TYPE__ uint8_t;
|
||||||
|
typedef __UINT16_TYPE__ uint16_t;
|
||||||
|
typedef __UINT32_TYPE__ uint32_t;
|
||||||
|
typedef __UINT64_TYPE__ uint64_t;
|
||||||
|
|
||||||
|
typedef __INT_LEAST8_TYPE__ int_least8_t;
|
||||||
|
typedef __INT_LEAST16_TYPE__ int_least16_t;
|
||||||
|
typedef __INT_LEAST32_TYPE__ int_least32_t;
|
||||||
|
typedef __INT_LEAST64_TYPE__ int_least64_t;
|
||||||
|
|
||||||
|
typedef __UINT_LEAST8_TYPE__ uint_least8_t;
|
||||||
|
typedef __UINT_LEAST16_TYPE__ uint_least16_t;
|
||||||
|
typedef __UINT_LEAST32_TYPE__ uint_least32_t;
|
||||||
|
typedef __UINT_LEAST64_TYPE__ uint_least64_t;
|
||||||
|
|
||||||
|
typedef __INT_FAST8_TYPE__ int_fast8_t;
|
||||||
|
typedef __INT_FAST16_TYPE__ int_fast16_t;
|
||||||
|
typedef __INT_FAST32_TYPE__ int_fast32_t;
|
||||||
|
typedef __INT_FAST64_TYPE__ int_fast64_t;
|
||||||
|
|
||||||
|
typedef __UINT_FAST8_TYPE__ uint_fast8_t;
|
||||||
|
typedef __UINT_FAST16_TYPE__ uint_fast16_t;
|
||||||
|
typedef __UINT_FAST32_TYPE__ uint_fast32_t;
|
||||||
|
typedef __UINT_FAST64_TYPE__ uint_fast64_t;
|
||||||
|
|
||||||
|
typedef __INTPTR_TYPE__ intptr_t;
|
||||||
|
typedef __UINTPTR_TYPE__ uintptr_t;
|
||||||
|
|
||||||
|
typedef __INTMAX_TYPE__ intmax_t;
|
||||||
|
typedef __UINTMAX_TYPE__ uintmax_t;
|
||||||
|
|
||||||
|
typedef __PTRDIFF_TYPE__ ptrdiff_t;
|
||||||
|
typedef __SIZE_TYPE__ size_t;
|
||||||
|
#ifndef __cplusplus
|
||||||
|
typedef __WCHAR_TYPE__ wchar_t;
|
||||||
|
#endif
|
||||||
|
typedef __WINT_TYPE__ wint_t;
|
||||||
|
typedef __SIG_ATOMIC_TYPE__ sig_atomic_t;
|
||||||
|
// TODO: ssize_t
|
||||||
|
typedef intptr_t ssize_t;
|
||||||
|
|
||||||
|
#if defined(__amd64__) || defined(__aarch64__)
|
||||||
|
typedef int64_t off_t;
|
||||||
|
typedef int64_t off64_t;
|
||||||
|
typedef uint32_t mode_t;
|
||||||
|
typedef uint64_t dev_t;
|
||||||
|
typedef uint64_t ino64_t;
|
||||||
|
typedef uint64_t ino_t;
|
||||||
|
typedef uint32_t nlink_t;
|
||||||
|
typedef int64_t blksize_t;
|
||||||
|
typedef int64_t blkcnt_t;
|
||||||
|
typedef int64_t blkcnt64_t;
|
||||||
|
typedef int64_t time_t;
|
||||||
|
typedef uint32_t uid_t;
|
||||||
|
typedef uint32_t gid_t;
|
||||||
|
typedef int64_t clock_t;
|
||||||
|
typedef int32_t pid_t;
|
||||||
|
#elif defined(__i386__) || defined(__arm__)
|
||||||
|
typedef int32_t off_t;
|
||||||
|
typedef long long off64_t;
|
||||||
|
typedef uint32_t mode_t;
|
||||||
|
typedef int32_t dev_t;
|
||||||
|
typedef int32_t ino64_t;
|
||||||
|
typedef int32_t ino_t;
|
||||||
|
typedef uint32_t nlink_t;
|
||||||
|
typedef int blksize_t;
|
||||||
|
typedef int32_t blkcnt_t;
|
||||||
|
typedef int32_t blkcnt64_t;
|
||||||
|
typedef int32_t time_t;
|
||||||
|
typedef uint32_t uid_t;
|
||||||
|
typedef uint32_t gid_t;
|
||||||
|
typedef long clock_t;
|
||||||
|
typedef int pid_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
template <typename T>
|
||||||
|
class ptr_t
|
||||||
|
{
|
||||||
|
T ptr;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ptr_t() : ptr(nullptr) {}
|
||||||
|
ptr_t(T p) : ptr(p) {}
|
||||||
|
ptr_t(int p) : ptr((T)(uintptr_t)p) {}
|
||||||
|
ptr_t(const ptr_t<T> &other) : ptr(other.ptr) {}
|
||||||
|
|
||||||
|
operator T() { return ptr; }
|
||||||
|
operator uintptr_t() { return (uintptr_t)ptr; }
|
||||||
|
|
||||||
|
operator bool() { return (void *)(uintptr_t)ptr != nullptr; }
|
||||||
|
|
||||||
|
ptr_t<T> &operator=(const ptr_t<T> &other)
|
||||||
|
{
|
||||||
|
ptr = other.ptr;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr_t<T> &operator+=(uintptr_t offset)
|
||||||
|
{
|
||||||
|
ptr = (T)((uintptr_t)ptr + offset);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr_t<T> &operator-=(uintptr_t offset)
|
||||||
|
{
|
||||||
|
ptr = (T)((uintptr_t)ptr - offset);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const ptr_t<T> &other) const { return ptr == other.ptr; }
|
||||||
|
bool operator==(auto other) const { return (uintptr_t)ptr == (uintptr_t)other; }
|
||||||
|
|
||||||
|
bool operator!=(const ptr_t<T> &other) const { return ptr != other.ptr; }
|
||||||
|
bool operator!=(auto other) const { return (uintptr_t)ptr != (uintptr_t)other; }
|
||||||
|
|
||||||
|
bool operator>(const ptr_t<T> &other) const { return ptr > other.ptr; }
|
||||||
|
bool operator>(auto other) const { return (uintptr_t)ptr > (uintptr_t)other; }
|
||||||
|
|
||||||
|
bool operator<(const ptr_t<T> &other) const { return ptr < other.ptr; }
|
||||||
|
bool operator<(auto other) const { return (uintptr_t)ptr < (uintptr_t)other; }
|
||||||
|
|
||||||
|
bool operator>=(const ptr_t<T> &other) const { return ptr >= other.ptr; }
|
||||||
|
bool operator>=(auto other) const { return (uintptr_t)ptr >= (uintptr_t)other; }
|
||||||
|
|
||||||
|
bool operator<=(const ptr_t<T> &other) const { return ptr <= other.ptr; }
|
||||||
|
bool operator<=(auto other) const { return (uintptr_t)ptr <= (uintptr_t)other; }
|
||||||
|
|
||||||
|
ptr_t<T> operator+(auto offset) const { return ptr_t<T>((void *)((uintptr_t)ptr + offset)); }
|
||||||
|
ptr_t<T> operator-(auto offset) const { return ptr_t<T>((void *)((uintptr_t)ptr - offset)); }
|
||||||
|
|
||||||
|
T operator->() { return ptr; }
|
||||||
|
T operator*() { return *ptr; }
|
||||||
|
};
|
||||||
|
#endif // __cplusplus
|
||||||
|
|
||||||
|
#define INT8_MAX __INT8_MAX__
|
||||||
|
#define INT8_MIN (-INT8_MAX - 1)
|
||||||
|
#define UINT8_MAX __UINT8_MAX__
|
||||||
|
#define INT16_MAX __INT16_MAX__
|
||||||
|
#define INT16_MIN (-INT16_MAX - 1)
|
||||||
|
#define UINT16_MAX __UINT16_MAX__
|
||||||
|
#define INT32_MAX __INT32_MAX__
|
||||||
|
#define INT32_MIN (-INT32_MAX - 1)
|
||||||
|
#define UINT32_MAX __UINT32_MAX__
|
||||||
|
#define INT64_MAX __INT64_MAX__
|
||||||
|
#define INT64_MIN (-INT64_MAX - 1)
|
||||||
|
#define UINT64_MAX __UINT64_MAX__
|
||||||
|
|
||||||
|
#define INT_LEAST8_MAX __INT_LEAST8_MAX__
|
||||||
|
#define INT_LEAST8_MIN (-INT_LEAST8_MAX - 1)
|
||||||
|
#define UINT_LEAST8_MAX __UINT_LEAST8_MAX__
|
||||||
|
#define INT_LEAST16_MAX __INT_LEAST16_MAX__
|
||||||
|
#define INT_LEAST16_MIN (-INT_LEAST16_MAX - 1)
|
||||||
|
#define UINT_LEAST16_MAX __UINT_LEAST16_MAX__
|
||||||
|
#define INT_LEAST32_MAX __INT_LEAST32_MAX__
|
||||||
|
#define INT_LEAST32_MIN (-INT_LEAST32_MAX - 1)
|
||||||
|
#define UINT_LEAST32_MAX __UINT_LEAST32_MAX__
|
||||||
|
#define INT_LEAST64_MAX __INT_LEAST64_MAX__
|
||||||
|
#define INT_LEAST64_MIN (-INT_LEAST64_MAX - 1)
|
||||||
|
#define UINT_LEAST64_MAX __UINT_LEAST64_MAX__
|
||||||
|
|
||||||
|
#define INT_FAST8_MAX __INT_FAST8_MAX__
|
||||||
|
#define INT_FAST8_MIN (-INT_FAST8_MAX - 1)
|
||||||
|
#define UINT_FAST8_MAX __UINT_FAST8_MAX__
|
||||||
|
#define INT_FAST16_MAX __INT_FAST16_MAX__
|
||||||
|
#define INT_FAST16_MIN (-INT_FAST16_MAX - 1)
|
||||||
|
#define UINT_FAST16_MAX __UINT_FAST16_MAX__
|
||||||
|
#define INT_FAST32_MAX __INT_FAST32_MAX__
|
||||||
|
#define INT_FAST32_MIN (-INT_FAST32_MAX - 1)
|
||||||
|
#define UINT_FAST32_MAX __UINT_FAST32_MAX__
|
||||||
|
#define INT_FAST64_MAX __INT_FAST64_MAX__
|
||||||
|
#define INT_FAST64_MIN (-INT_FAST64_MAX - 1)
|
||||||
|
#define UINT_FAST64_MAX __UINT_FAST64_MAX__
|
||||||
|
|
||||||
|
#define INTPTR_MAX __INTPTR_MAX__
|
||||||
|
#define INTPTR_MIN (-INTPTR_MAX - 1)
|
||||||
|
#define UINTPTR_MAX __UINTPTR_MAX__
|
||||||
|
|
||||||
|
#define INTMAX_MAX __INTMAX_MAX__
|
||||||
|
#define INTMAX_MIN (-INTMAX_MAX - 1)
|
||||||
|
#define UINTMAX_MAX __UINTMAX_MAX__
|
||||||
|
|
||||||
|
#define PTRDIFF_MAX __PTRDIFF_MAX__
|
||||||
|
#define PTRDIFF_MIN (-PTRDIFF_MAX - 1)
|
||||||
|
|
||||||
|
#define SIG_ATOMIC_MAX __SIG_ATOMIC_MAX__
|
||||||
|
#define SIG_ATOMIC_MIN __SIG_ATOMIC_MIN__
|
||||||
|
|
||||||
|
#define SIZE_MAX __SIZE_MAX__
|
||||||
|
|
||||||
|
#define WCHAR_MAX __WCHAR_MAX__
|
||||||
|
#define WCHAR_MIN __WCHAR_MIN__
|
||||||
|
|
||||||
|
#define WINT_MAX __WINT_MAX__
|
||||||
|
#define WINT_MIN __WINT_MIN__
|
||||||
|
|
||||||
|
#if defined(__amd64__)
|
||||||
|
#define BREAK __asm__ __volatile__("int $0x3" \
|
||||||
|
: \
|
||||||
|
: \
|
||||||
|
: "memory");
|
||||||
|
#elif defined(__i386__)
|
||||||
|
#define BREAK __asm__ __volatile__("int $0x3" \
|
||||||
|
: \
|
||||||
|
: \
|
||||||
|
: "memory");
|
||||||
|
#elif defined(__aarch64__)
|
||||||
|
#define BREAK __asm__ __volatile__("brk #0" \
|
||||||
|
: \
|
||||||
|
: \
|
||||||
|
: "memory");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __INT48_TYPE__
|
||||||
|
typedef __INT48_TYPE__ int48_t;
|
||||||
|
typedef __UINT48_TYPE__ uint48_t;
|
||||||
|
typedef int48_t int_least48_t;
|
||||||
|
typedef uint48_t uint_least48_t;
|
||||||
|
typedef int48_t int_fast48_t;
|
||||||
|
typedef uint48_t uint_fast48_t;
|
||||||
|
#else // __INT48_TYPE__
|
||||||
|
typedef __INT64_TYPE__ int48_t;
|
||||||
|
typedef __UINT64_TYPE__ uint48_t;
|
||||||
|
typedef int48_t int_least48_t;
|
||||||
|
typedef uint48_t uint_least48_t;
|
||||||
|
typedef int48_t int_fast48_t;
|
||||||
|
typedef uint48_t uint_fast48_t;
|
||||||
|
#endif // __INT48_TYPE__
|
||||||
|
|
||||||
|
#define b4(x) ((x & 0x0F) << 4 | (x & 0xF0) >> 4)
|
||||||
|
#define b8(x) ((x) & 0xFF)
|
||||||
|
#define b16(x) __builtin_bswap16(x)
|
||||||
|
#define b32(x) __builtin_bswap32(x)
|
||||||
|
#define b48(x) (((((x) & 0x0000000000ff) << 40) | \
|
||||||
|
(((x) & 0x00000000ff00) << 24) | \
|
||||||
|
(((x) & 0x000000ff0000) << 8) | \
|
||||||
|
(((x) & 0x0000ff000000) >> 8) | \
|
||||||
|
(((x) & 0x00ff00000000) >> 24) | \
|
||||||
|
(((x) & 0xff0000000000) >> 40)))
|
||||||
|
#define b64(x) __builtin_bswap64(x)
|
||||||
|
|
||||||
|
/* https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html */
|
||||||
|
|
||||||
|
/** No optimization (the default); generates
|
||||||
|
* unoptimized code but has the fastest compilation time.
|
||||||
|
*/
|
||||||
|
#define O0 __attribute__((optimize("O0")))
|
||||||
|
|
||||||
|
/** Moderate optimization;
|
||||||
|
* optimizes reasonably well but does not degrade
|
||||||
|
* compilation time significantly. */
|
||||||
|
#define O1 __attribute__((optimize("O1")))
|
||||||
|
|
||||||
|
/** Full optimization; generates highly
|
||||||
|
* optimized code and has the slowest compilation time.
|
||||||
|
*/
|
||||||
|
#define O2 __attribute__((optimize("O2")))
|
||||||
|
|
||||||
|
/** Full optimization as in -O2;
|
||||||
|
* also uses more aggressive automatic inlining of
|
||||||
|
* subprograms within a unit (Inlining of Subprograms)
|
||||||
|
* and attempts to vectorize loops. */
|
||||||
|
#define O3 __attribute__((optimize("O3")))
|
||||||
|
|
||||||
|
/** Optimize space usage (code and data)
|
||||||
|
* of resulting program.
|
||||||
|
*/
|
||||||
|
#define Os __attribute__((optimize("Os")))
|
||||||
|
|
||||||
|
/** Disregard strict standards compliance.
|
||||||
|
* -Ofast enables all -O3 optimizations.
|
||||||
|
* It also enables optimizations that are not valid for
|
||||||
|
* all standard-compliant programs.
|
||||||
|
*/
|
||||||
|
#define Ofast __attribute__((optimize("Ofast")))
|
||||||
|
|
||||||
|
/** Optimize for size.
|
||||||
|
* -Oz enables all -Os optimizations that do not typically
|
||||||
|
* increase code size.
|
||||||
|
*/
|
||||||
|
#define Oz __attribute__((optimize("Oz")))
|
||||||
|
|
||||||
|
/** Optimize for debugging.
|
||||||
|
* -Og enables optimizations that do not interfere with
|
||||||
|
* debugging.
|
||||||
|
*/
|
||||||
|
#define Og __attribute__((optimize("Og")))
|
||||||
|
|
||||||
|
#define __unused __attribute__((unused))
|
||||||
|
#define __packed __attribute__((packed))
|
||||||
|
#define __naked __attribute__((naked))
|
||||||
|
#define __aligned(x) __attribute__((aligned(x)))
|
||||||
|
#define __section(x) __attribute__((section(x)))
|
||||||
|
#define __noreturn __attribute__((noreturn))
|
||||||
|
#define __weak __attribute__((weak))
|
||||||
|
#define __alias(x) __attribute__((alias(x)))
|
||||||
|
#define __always_inline __attribute__((always_inline))
|
||||||
|
#define __noinline __attribute__((noinline))
|
||||||
|
#define __pure __attribute__((pure))
|
||||||
|
#define __const __attribute__((const))
|
||||||
|
#define __malloc __attribute__((malloc))
|
||||||
|
#define __returns_twice __attribute__((returns_twice))
|
||||||
|
#define __used __attribute__((used))
|
||||||
|
#define __deprecated __attribute__((deprecated))
|
||||||
|
#define __deprecated_msg(x) __attribute__((deprecated(x)))
|
||||||
|
#define __weakref(x) __attribute__((weakref(x)))
|
||||||
|
#define __weakrefalias(x) __attribute__((weakref(#x)))
|
||||||
|
#define __visibility(x) __attribute__((visibility(x)))
|
||||||
|
#define __constructor __attribute__((constructor))
|
||||||
|
#define __destructor __attribute__((destructor))
|
||||||
|
#define __cleanup(x) __attribute__((cleanup(x)))
|
||||||
|
#define __fallthrough __attribute__((fallthrough))
|
||||||
|
#define __nonnull(x) __attribute__((nonnull x))
|
||||||
|
#define __nonnull_all __attribute__((nonnull))
|
||||||
|
#define __returns_nonnull __attribute__((returns_nonnull))
|
||||||
|
#define __sentinel __attribute__((sentinel))
|
||||||
|
#define __sentinel_all __attribute__((sentinel(0)))
|
||||||
|
#define __format(x, y, z) __attribute__((format(x, y, z)))
|
||||||
|
#define __format_arg(x) __attribute__((format_arg(x)))
|
||||||
|
#define __nonnull_params(x) __attribute__((nonnull x))
|
||||||
|
#define __nonnull_all __attribute__((nonnull))
|
||||||
|
#define __warn_unused_result __attribute__((warn_unused_result))
|
||||||
|
#define __no_stack_protector __attribute__((no_stack_protector))
|
||||||
|
#define __no_instrument_function __attribute__((no_instrument_function))
|
||||||
|
#define __no_debug __attribute__((no_debug))
|
||||||
|
#define __target(x) __attribute__((target(x)))
|
||||||
|
#define __min_vector_width(x) __attribute__((min_vector_width(x)))
|
||||||
|
|
||||||
|
// sanitizer
|
||||||
|
#define __no_sanitize(x) __attribute__((no_sanitize(x)))
|
||||||
|
#define __no_sanitize_address __attribute__((no_sanitize_address))
|
||||||
|
#define __no_sanitize_thread __attribute__((no_sanitize_thread))
|
||||||
|
#define __no_sanitize_undefined __attribute__((no_sanitize_undefined))
|
||||||
|
#define __no_sanitize_coverage __attribute__((no_sanitize_coverage))
|
||||||
|
|
||||||
|
#define __synchronize __sync_synchronize()
|
||||||
|
#define __sync __synchronize
|
||||||
|
|
||||||
|
#define __unreachable __builtin_unreachable()
|
||||||
|
|
||||||
|
#define likely(x) __builtin_expect(!!(x), 1)
|
||||||
|
#define unlikely(x) __builtin_expect(!!(x), 0)
|
||||||
|
|
||||||
|
#define NoSecurityAnalysis __no_stack_protector __no_sanitize_address __no_sanitize_undefined __no_sanitize_thread
|
||||||
|
#define nsa NoSecurityAnalysis
|
||||||
|
|
||||||
|
#define NIF __no_instrument_function
|
||||||
|
|
||||||
|
#define int3 \
|
||||||
|
__asm__ __volatile__("int3" \
|
||||||
|
: \
|
||||||
|
: \
|
||||||
|
: "memory")
|
||||||
|
|
||||||
|
#define StackPush(stack, type, value) \
|
||||||
|
*((type *)--stack) = value
|
||||||
|
|
||||||
|
#define StackPop(stack, type) \
|
||||||
|
*((type *)stack++)
|
||||||
|
|
||||||
|
#define ReturnLogError(ret, format, ...) \
|
||||||
|
{ \
|
||||||
|
trace(format, ##__VA_ARGS__); \
|
||||||
|
return ret; \
|
||||||
|
} \
|
||||||
|
while (0) \
|
||||||
|
__builtin_unreachable()
|
||||||
|
|
||||||
|
#define AssertReturnError(condition, ret) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
if (__builtin_expect(!!(!(condition)), 0)) \
|
||||||
|
{ \
|
||||||
|
error("\"%s\" failed!", #condition); \
|
||||||
|
return ret; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#endif // !__FENNIX_KERNEL_TYPES_H__
|
137
Bootloader/uefi/Makefile
Normal file
137
Bootloader/uefi/Makefile
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
BOOT_FILENAME = BOOTX64.EFI
|
||||||
|
|
||||||
|
GNUEFI_RELEASE_VERSION=3.0.18
|
||||||
|
|
||||||
|
GIT_COMMIT = $(shell git rev-parse HEAD)
|
||||||
|
GIT_COMMIT_SHORT = $(shell git rev-parse --short HEAD)
|
||||||
|
|
||||||
|
HEADERS := $(sort $(dir $(wildcard ../include/*)))
|
||||||
|
INCLUDE_DIR = -I../include
|
||||||
|
|
||||||
|
define find-sources
|
||||||
|
$(shell find ./ -type f -name '$1' -print0 | xargs -0)
|
||||||
|
endef
|
||||||
|
|
||||||
|
BMP_SOURCES := $(call find-sources,*.bmp)
|
||||||
|
PSF_SOURCES := $(call find-sources,*.psf)
|
||||||
|
S_SOURCES := $(call find-sources,*.S)
|
||||||
|
s_SOURCES := $(call find-sources,*.s)
|
||||||
|
C_SOURCES := $(call find-sources,*.c)
|
||||||
|
CXX_SOURCES := $(call find-sources,*.cpp)
|
||||||
|
|
||||||
|
OBJ = $(BMP_SOURCES:.bmp=.o) $(PSF_SOURCES:.psf=.o) $(s_SOURCES:.s=.o) $(S_SOURCES:.S=.o) $(C_SOURCES:.c=.o) $(CXX_SOURCES:.cpp=.o)
|
||||||
|
|
||||||
|
LDFLAGS = -static -nostdlib -nodefaultlibs -nolibc \
|
||||||
|
-Wl,-static,--no-dynamic-linker,-ztext \
|
||||||
|
-zmax-page-size=0x1000 \
|
||||||
|
-Wl,-Map kernel.map -fno-pic -fno-pie
|
||||||
|
|
||||||
|
# Disable all warnings by adding "-w" in WARNCFLAG and if you want to treat the warnings as errors, add "-Werror"
|
||||||
|
# -Wconversion this may be re-added later
|
||||||
|
WARNCFLAG = -Wall -Wextra \
|
||||||
|
-Wfloat-equal -Wpointer-arith -Wcast-align \
|
||||||
|
-Wredundant-decls -Winit-self -Wswitch-default \
|
||||||
|
-Wstrict-overflow=5 -Wno-error=cpp -Werror \
|
||||||
|
-Wno-unused-parameter -Wno-error=format
|
||||||
|
|
||||||
|
CFLAG_STACK_PROTECTOR := -fstack-protector-all
|
||||||
|
|
||||||
|
# https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html
|
||||||
|
CFLAGS := \
|
||||||
|
$(INCLUDE_DIR) \
|
||||||
|
-D__kernel__='1' \
|
||||||
|
-DKERNEL_NAME='"$(OSNAME)"' \
|
||||||
|
-DKERNEL_ARCH='"$(OSARCH)"' \
|
||||||
|
-DKERNEL_VERSION='"$(KERNEL_VERSION)"' \
|
||||||
|
-DGIT_COMMIT='"$(GIT_COMMIT)"' \
|
||||||
|
-DGIT_COMMIT_SHORT='"$(GIT_COMMIT_SHORT)"' \
|
||||||
|
-fno-pic -fno-pie -fno-builtin
|
||||||
|
|
||||||
|
ifeq ($(OSARCH), amd64)
|
||||||
|
CFLAGS += -march=core2 -mcmodel=kernel -m64 -mno-red-zone
|
||||||
|
LDFLAGS += -T../linker.ld
|
||||||
|
else ifeq ($(OSARCH), i386)
|
||||||
|
CFLAGS += -march=pentium -m32 -mno-red-zone
|
||||||
|
LDFLAGS += -T../linker.ld
|
||||||
|
else ifeq ($(OSARCH), arm)
|
||||||
|
CFLAGS += -march=armv7-a -mfloat-abi=softfp -ggdb3
|
||||||
|
LDFLAGS += -T../linker.ld
|
||||||
|
WARNCFLAG += -w
|
||||||
|
else ifeq ($(OSARCH), aarch64)
|
||||||
|
CFLAGS += -march=armv9.4-a -mtune=cortex-a72 -mlittle-endian -mcmodel=large
|
||||||
|
LDFLAGS += -T../linker.ld
|
||||||
|
endif # OSARCH
|
||||||
|
|
||||||
|
# -finstrument-functions for __cyg_profile_func_enter & __cyg_profile_func_exit. Used for profiling and debugging.
|
||||||
|
ifeq ($(DEBUG), 1)
|
||||||
|
# CFLAGS += --coverage
|
||||||
|
# CFLAGS += -pg
|
||||||
|
# CFLAGS += -finstrument-functions
|
||||||
|
CFLAGS += -DDEBUG -ggdb3 -O0 -fdiagnostics-color=always -fstack-usage -fsanitize=undefined
|
||||||
|
ifeq ($(OSARCH), amd64)
|
||||||
|
CFLAGS += -fverbose-asm
|
||||||
|
endif # amd64
|
||||||
|
ifeq ($(OSARCH), arm)
|
||||||
|
CFLAGS += -fstack-check -fverbose-asm
|
||||||
|
endif # arm
|
||||||
|
ifeq ($(OSARCH), aarch64)
|
||||||
|
CFLAGS += -fstack-check -fverbose-asm
|
||||||
|
endif # aarch64
|
||||||
|
LDFLAGS += -ggdb3 -O0
|
||||||
|
ASFLAGS += -g --gstabs+ --gdwarf-5 -D
|
||||||
|
WARNCFLAG += -Wno-unused-function -Wno-maybe-uninitialized -Wno-builtin-declaration-mismatch -Wno-unknown-pragmas -Wno-unused-parameter -Wno-unused-variable
|
||||||
|
endif # DEBUG
|
||||||
|
|
||||||
|
default:
|
||||||
|
$(error Do not run this Makefile directly!)
|
||||||
|
|
||||||
|
build: $(BOOT_FILENAME)
|
||||||
|
|
||||||
|
$(BOOT_FILENAME): $(OBJ)
|
||||||
|
$(info Linking $@)
|
||||||
|
$(LD) -shared -Bsymbolic -L../gnu-efi/x86_64/lib -L../gnu-efi/x86_64/gnuefi -T../gnu-efi/gnuefi/elf_x86_64_efi.lds ../gnu-efi/x86_64/gnuefi/crt0-efi-x86_64.o $(OBJ) -o tmp.so -lgnuefi -lefi
|
||||||
|
objcopy -j .text -j .sdata -j .data -j .dynamic -j .dynsym -j .rel -j .rela -j .rel.* -j .rela.* -j .reloc --target efi-app-x86_64 --subsystem=10 tmp.so BOOTX64.EFI
|
||||||
|
rm tmp.so
|
||||||
|
|
||||||
|
%.o: %.c $(HEADERS)
|
||||||
|
$(info Compiling $<)
|
||||||
|
$(CC) -I../include -fpic -ffreestanding -fno-stack-protector -fno-stack-check -fshort-wchar -mno-red-zone -maccumulate-outgoing-args -c $< -o $@
|
||||||
|
|
||||||
|
%.o: %.cpp $(HEADERS)
|
||||||
|
$(info Compiling $<)
|
||||||
|
$(CC) -I../include -fpic -ffreestanding -fno-stack-protector -fno-stack-check -fshort-wchar -mno-red-zone -maccumulate-outgoing-args -c $< -o $@
|
||||||
|
|
||||||
|
%.o: %.S
|
||||||
|
$(info Compiling $<)
|
||||||
|
$(AS) $(ASFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
%.o: %.s
|
||||||
|
$(info Compiling $<)
|
||||||
|
$(AS) $(ASFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
%.o: %.psf
|
||||||
|
ifeq ($(OSARCH), amd64)
|
||||||
|
$(OBJCOPY) -O elf64-x86-64 -I binary $< $@
|
||||||
|
else ifeq ($(OSARCH), i386)
|
||||||
|
$(OBJCOPY) -O elf32-i386 -I binary $< $@
|
||||||
|
else ifeq ($(OSARCH), arm)
|
||||||
|
$(OBJCOPY) -O elf32-littlearm -I binary $< $@
|
||||||
|
else ifeq ($(OSARCH), aarch64)
|
||||||
|
$(OBJCOPY) -O elf64-littleaarch64 -I binary $< $@
|
||||||
|
endif
|
||||||
|
$(NM) $@
|
||||||
|
|
||||||
|
%.o: %.bmp
|
||||||
|
ifeq ($(OSARCH), amd64)
|
||||||
|
$(OBJCOPY) -O elf64-x86-64 -I binary $< $@
|
||||||
|
else ifeq ($(OSARCH), i386)
|
||||||
|
$(OBJCOPY) -O elf32-i386 -I binary $< $@
|
||||||
|
else ifeq ($(OSARCH), arm)
|
||||||
|
$(OBJCOPY) -O elf32-littlearm -I binary $< $@
|
||||||
|
else ifeq ($(OSARCH), aarch64)
|
||||||
|
$(OBJCOPY) -O elf64-littlearch64 -I binary $< $@
|
||||||
|
endif
|
||||||
|
$(NM) $@
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f kernel.map kernel_dump.map kernel_dump_intel.map $(OBJ) $(STACK_USAGE_OBJ) $(GCNO_OBJ) $(BOOT_FILENAME)
|
27
Bootloader/uefi/main.c
Normal file
27
Bootloader/uefi/main.c
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Lynx Bootloader.
|
||||||
|
|
||||||
|
Lynx Bootloader is free software: you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation, either version 3 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
Lynx Bootloader is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Lynx Bootloader. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <efi.h>
|
||||||
|
#include <efilib.h>
|
||||||
|
|
||||||
|
EFI_STATUS EFIAPI efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
|
||||||
|
{
|
||||||
|
InitializeLib(ImageHandle, SystemTable);
|
||||||
|
SystemTable->BootServices->SetWatchdogTimer(0, 0, 0, NULL);
|
||||||
|
Print(L"Lynx Bootloader © EnderIce2 2025\n");
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
1883
CHANGELOG.md
Normal file
1883
CHANGELOG.md
Normal file
File diff suppressed because it is too large
Load Diff
@ -62,6 +62,8 @@ Follow the coding style used in the repository to ensure consistency. Adhere to:
|
|||||||
- Start function and global declaration names with an uppercase letter.
|
- Start function and global declaration names with an uppercase letter.
|
||||||
- Start local variable names with a lowercase letter.
|
- Start local variable names with a lowercase letter.
|
||||||
- Maintain consistent formatting and commenting guidelines.
|
- Maintain consistent formatting and commenting guidelines.
|
||||||
|
- Commit messages must follow [Conventional Commits](https://conventionalcommits.org).
|
||||||
|
- Release versions must follow [Semantic Versioning](https://semver.org).
|
||||||
|
|
||||||
Refer to the [style guide document](STYLE_GUIDE.md) if available.
|
Refer to the [style guide document](STYLE_GUIDE.md) if available.
|
||||||
|
|
||||||
|
15
CREDITS.md
15
CREDITS.md
@ -27,6 +27,9 @@ License information can be found in the [LICENSES.md](LICENSES.md) file.
|
|||||||
## CPUID 0x7
|
## CPUID 0x7
|
||||||
- [CPUID](https://en.wikipedia.org/wiki/CPUID)
|
- [CPUID](https://en.wikipedia.org/wiki/CPUID)
|
||||||
|
|
||||||
|
## KVM CPUID
|
||||||
|
- [kernel.org KVM CPUID](https://www.kernel.org/doc/html/v6.9/virt/kvm/x86/cpuid.html?highlight=cpuid)
|
||||||
|
|
||||||
## Network
|
## Network
|
||||||
- [Beej's Guide to Network Programming](https://web.archive.org/web/20051210132103/http://users.pcnet.ro/dmoroian/beej/Beej.html)
|
- [Beej's Guide to Network Programming](https://web.archive.org/web/20051210132103/http://users.pcnet.ro/dmoroian/beej/Beej.html)
|
||||||
- [UDP Socket Programming](https://web.archive.org/web/20060229214053/http://www.cs.rutgers.edu/~pxk/417/notes/sockets/udp.html)
|
- [UDP Socket Programming](https://web.archive.org/web/20060229214053/http://www.cs.rutgers.edu/~pxk/417/notes/sockets/udp.html)
|
||||||
@ -120,6 +123,18 @@ License information can be found in the [LICENSES.md](LICENSES.md) file.
|
|||||||
## UART
|
## UART
|
||||||
- [Interfacing the Serial / RS232 Port V5.0](http://www.senet.com.au/~cpeacock)
|
- [Interfacing the Serial / RS232 Port V5.0](http://www.senet.com.au/~cpeacock)
|
||||||
|
|
||||||
|
## UEFI
|
||||||
|
- [U-Boot EFI Commands](https://docs.u-boot.org/en/latest/usage/cmd/efi.html)
|
||||||
|
- [UEFI Specification 2.10](https://uefi.org/sites/default/files/resources/UEFI_Spec_2_10_Aug29.pdf)
|
||||||
|
- [UEFI Boot Process Overview](https://gist.github.com/Velocet/d394281d96191e235ff46a8aa2018d80)
|
||||||
|
- [Rust OS Development: UEFI](https://blog.malware.re/2023/09/01/rust-os-part2/index.html)
|
||||||
|
- [GUIDs Database](https://github.com/DSecurity/efiSeek/blob/master/data/guids-db.ini)
|
||||||
|
|
||||||
|
## BGRT
|
||||||
|
- [BGRT on OSDev](https://wiki.osdev.org/BGRT)
|
||||||
|
- [BMP File Structure @ Gdansk University of Technology](http://www.ue.eti.pg.gda.pl/fpgalab/zadania.spartan3/zad_vga_struktura_pliku_bmp_en.html)
|
||||||
|
- [BGRT @ Purdue University](https://engineering.purdue.edu/ece264/16au/hw/HW13)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
Special thanks to all contributors and the creators of the referenced projects and resources!
|
Special thanks to all contributors and the creators of the referenced projects and resources!
|
||||||
|
13
Drivers/.editorconfig
Normal file
13
Drivers/.editorconfig
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# EditorConfig is awesome: https://editorconfig.org
|
||||||
|
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
end_of_line = lf
|
||||||
|
insert_final_newline = true
|
||||||
|
indent_style = tab
|
||||||
|
indent_size = 4
|
||||||
|
|
||||||
|
[Makefile]
|
||||||
|
indent_style = tab
|
31
Drivers/.vscode/c_cpp_properties.json
vendored
31
Drivers/.vscode/c_cpp_properties.json
vendored
@ -35,10 +35,8 @@
|
|||||||
"-ffunction-sections",
|
"-ffunction-sections",
|
||||||
"-msoft-float",
|
"-msoft-float",
|
||||||
"-fno-builtin",
|
"-fno-builtin",
|
||||||
|
|
||||||
// C++ flags
|
// C++ flags
|
||||||
"-fexceptions",
|
"-fexceptions",
|
||||||
|
|
||||||
// Linker flags
|
// Linker flags
|
||||||
"-fPIC",
|
"-fPIC",
|
||||||
"-fPIE",
|
"-fPIE",
|
||||||
@ -50,7 +48,6 @@
|
|||||||
"-nolibc",
|
"-nolibc",
|
||||||
"-zmax-page-size=0x1000",
|
"-zmax-page-size=0x1000",
|
||||||
"-static",
|
"-static",
|
||||||
|
|
||||||
// VSCode flags
|
// VSCode flags
|
||||||
"-ffreestanding",
|
"-ffreestanding",
|
||||||
"-nostdinc",
|
"-nostdinc",
|
||||||
@ -91,10 +88,8 @@
|
|||||||
"-ffunction-sections",
|
"-ffunction-sections",
|
||||||
"-msoft-float",
|
"-msoft-float",
|
||||||
"-fno-builtin",
|
"-fno-builtin",
|
||||||
|
|
||||||
// C++ flags
|
// C++ flags
|
||||||
"-fexceptions",
|
"-fexceptions",
|
||||||
|
|
||||||
// Linker flags
|
// Linker flags
|
||||||
"-fPIC",
|
"-fPIC",
|
||||||
"-fPIE",
|
"-fPIE",
|
||||||
@ -106,12 +101,36 @@
|
|||||||
"-nolibc",
|
"-nolibc",
|
||||||
"-zmax-page-size=0x1000",
|
"-zmax-page-size=0x1000",
|
||||||
"-static",
|
"-static",
|
||||||
|
|
||||||
// VSCode flags
|
// VSCode flags
|
||||||
"-ffreestanding",
|
"-ffreestanding",
|
||||||
"-nostdinc",
|
"-nostdinc",
|
||||||
"-nostdinc++"
|
"-nostdinc++"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Fennix Aarch64 (Linux, GCC, debug)",
|
||||||
|
"includePath": [
|
||||||
|
"${workspaceFolder}/include",
|
||||||
|
"${workspaceFolder}/include/**"
|
||||||
|
],
|
||||||
|
"defines": [
|
||||||
|
"__debug_vscode__",
|
||||||
|
"KERNEL_NAME=\"Fennix\"",
|
||||||
|
"KERNEL_VERSION=\"1.0\"",
|
||||||
|
"GIT_COMMIT=\"0000000000000000000000000000000000000000\"",
|
||||||
|
"GIT_COMMIT_SHORT=\"0000000\"",
|
||||||
|
"DEBUG=\"1\""
|
||||||
|
],
|
||||||
|
"compilerPath": "${workspaceFolder}/../tools/cross/bin/aarch64-fennix-gcc",
|
||||||
|
"cStandard": "c17",
|
||||||
|
"cppStandard": "c++20",
|
||||||
|
"intelliSenseMode": "linux-gcc-arm64",
|
||||||
|
"configurationProvider": "ms-vscode.makefile-tools",
|
||||||
|
"compilerArgs": [
|
||||||
|
"-ffreestanding",
|
||||||
|
"-nostdinc",
|
||||||
|
"-nostdinc++"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"version": 4
|
"version": 4
|
||||||
|
@ -43,26 +43,47 @@ endif
|
|||||||
export DRIVER_LDFLAGS
|
export DRIVER_LDFLAGS
|
||||||
export DRIVER_CFLAGS
|
export DRIVER_CFLAGS
|
||||||
|
|
||||||
|
copy_driver_signatures:
|
||||||
|
@TMP_FILE="$(OUTPUT_DIR)../../Kernel/drivers/trusted.c.tmp"; \
|
||||||
|
OUT_FILE="$(OUTPUT_DIR)../../Kernel/drivers/trusted.c"; \
|
||||||
|
mkdir -p $(OUTPUT_DIR)../../Kernel/drivers/; \
|
||||||
|
echo "const char *trusted_drivers[] = {" > $$TMP_FILE; \
|
||||||
|
find $(OUTPUT_DIR) -name "*.drv" -exec sha512sum {} \; | awk '{gsub(/.*\//, "", $$2); gsub(/\./, "_", $$2); sub(/_drv$$/, "_drv", $$2); print "\"" $$1 "\"," }' >> $$TMP_FILE; \
|
||||||
|
echo "};" >> $$TMP_FILE; \
|
||||||
|
echo "const __SIZE_TYPE__ trusted_drivers_count = sizeof(trusted_drivers) / sizeof(trusted_drivers[0]);" >> $$TMP_FILE; \
|
||||||
|
if [ ! -f $$OUT_FILE ] || ! cmp -s $$TMP_FILE $$OUT_FILE; then \
|
||||||
|
mv $$TMP_FILE $$OUT_FILE; \
|
||||||
|
printf '\033[0;32m[trusted.c updated]\033[0m\n'; \
|
||||||
|
else \
|
||||||
|
rm $$TMP_FILE; \
|
||||||
|
printf '\033[0;33m[trusted.c unchanged]\033[0m\n'; \
|
||||||
|
fi
|
||||||
|
|
||||||
build:
|
build:
|
||||||
cp -rf ../Kernel/include/interface/* include/
|
cp -rf ../Kernel/include/interface/* include/
|
||||||
mkdir -p out
|
mkdir -p out
|
||||||
make -C library build
|
$(MAKE) -C library build
|
||||||
make -C audio build
|
ifneq ($(filter amd64 i386,$(OSARCH)),)
|
||||||
make -C input build
|
$(MAKE) -C audio build
|
||||||
make -C misc build
|
$(MAKE) -C input build
|
||||||
make -C network build
|
$(MAKE) -C misc build
|
||||||
make -C storage build
|
$(MAKE) -C network build
|
||||||
make -C filesystem build
|
$(MAKE) -C storage build
|
||||||
|
$(MAKE) -C filesystem build
|
||||||
|
endif
|
||||||
|
$(MAKE) copy_driver_signatures
|
||||||
|
|
||||||
prepare:
|
prepare:
|
||||||
$(info Nothing to prepare)
|
$(info Nothing to prepare)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf out
|
rm -rf out
|
||||||
make -C library clean
|
$(MAKE) -C library clean
|
||||||
make -C audio clean
|
ifneq ($(filter amd64 i386,$(OSARCH)),)
|
||||||
make -C input clean
|
$(MAKE) -C audio clean
|
||||||
make -C misc clean
|
$(MAKE) -C input clean
|
||||||
make -C network clean
|
$(MAKE) -C misc clean
|
||||||
make -C storage clean
|
$(MAKE) -C network clean
|
||||||
make -C filesystem clean
|
$(MAKE) -C storage clean
|
||||||
|
$(MAKE) -C filesystem clean
|
||||||
|
endif
|
||||||
|
@ -1,35 +0,0 @@
|
|||||||
default:
|
|
||||||
$(error Do not run this Makefile directly!)
|
|
||||||
|
|
||||||
S_SOURCES = $(shell find ./ -type f -name '*.S')
|
|
||||||
C_SOURCES = $(shell find ./ -type f -name '*.c')
|
|
||||||
CXX_SOURCES = $(shell find ./ -type f -name '*.cpp')
|
|
||||||
HEADERS = $(sort $(dir $(wildcard ../../include/*)))
|
|
||||||
OBJ = $(C_SOURCES:.c=.o) $(CXX_SOURCES:.cpp=.o) $(S_SOURCES:.S=.o)
|
|
||||||
STACK_USAGE_OBJ = $(C_SOURCES:.c=.su) $(CXX_SOURCES:.cpp=.su)
|
|
||||||
|
|
||||||
FILENAME = $(notdir $(shell pwd)).drv
|
|
||||||
|
|
||||||
build: $(FILENAME)
|
|
||||||
mv $(FILENAME) $(OUTPUT_DIR)$(FILENAME)
|
|
||||||
|
|
||||||
$(FILENAME): $(OBJ)
|
|
||||||
$(info Linking $@)
|
|
||||||
$(CC) $(DRIVER_LDFLAGS) $(OBJ) $(OUTPUT_DIR)dcrt0.o -L$(OUTPUT_DIR) -lkernel -o $@
|
|
||||||
|
|
||||||
WARNCFLAG = -Wall -Wextra
|
|
||||||
|
|
||||||
%.o: %.c $(HEADERS)
|
|
||||||
$(info Compiling $<)
|
|
||||||
$(CC) $(DRIVER_CFLAGS) $(WARNCFLAG) -std=c17 -c $< -o $@
|
|
||||||
|
|
||||||
%.o: %.cpp $(HEADERS)
|
|
||||||
$(info Compiling $<)
|
|
||||||
$(CXX) $(DRIVER_CFLAGS) $(WARNCFLAG) -std=c++20 -fno-exceptions -fno-rtti -c $< -o $@
|
|
||||||
|
|
||||||
%.o: %.S
|
|
||||||
$(info Compiling $<)
|
|
||||||
$(AS) -o $@ $<
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -f file.map $(OBJ) $(STACK_USAGE_OBJ)
|
|
@ -1,881 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of Fennix Kernel.
|
|
||||||
|
|
||||||
Fennix Kernel is free software: you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU General Public License as
|
|
||||||
published by the Free Software Foundation, either version 3 of
|
|
||||||
the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
Fennix Kernel is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#include <audio.h>
|
|
||||||
#include <regs.h>
|
|
||||||
#include <base.h>
|
|
||||||
#include <pci.h>
|
|
||||||
#include <io.h>
|
|
||||||
#include <fs.h>
|
|
||||||
|
|
||||||
#define DescriptorListLength 0x20
|
|
||||||
|
|
||||||
enum AudioVolumeValues
|
|
||||||
{
|
|
||||||
AV_Maximum = 0x0,
|
|
||||||
AV_Minimum = 0x3F,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum AudioEncodingValues
|
|
||||||
{
|
|
||||||
AE_PCMs8,
|
|
||||||
AE_PCMu8,
|
|
||||||
|
|
||||||
AE_PCMs16le,
|
|
||||||
AE_PCMs20le,
|
|
||||||
AE_PCMs24le,
|
|
||||||
AE_PCMs32le,
|
|
||||||
|
|
||||||
AE_PCMu16le,
|
|
||||||
AE_PCMu20le,
|
|
||||||
AE_PCMu24le,
|
|
||||||
AE_PCMu32le,
|
|
||||||
|
|
||||||
AE_PCMs16be,
|
|
||||||
AE_PCMs20be,
|
|
||||||
AE_PCMs24be,
|
|
||||||
AE_PCMs32be,
|
|
||||||
|
|
||||||
AE_PCMu16be,
|
|
||||||
AE_PCMu20be,
|
|
||||||
AE_PCMu24be,
|
|
||||||
AE_PCMu32be,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum NativeAudioMixerRegisters
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @brief Reset Register
|
|
||||||
* @note Length: word
|
|
||||||
*/
|
|
||||||
NAM_Reset = 0x00,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Master Volume Register
|
|
||||||
* @note Length: word
|
|
||||||
*/
|
|
||||||
NAM_MasterVolume = 0x02,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Microphone Volume Register
|
|
||||||
* @note Length: word
|
|
||||||
*/
|
|
||||||
NAM_MicrophoneVolume = 0x0E,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief PCM Out Volume Register
|
|
||||||
* @note Length: word
|
|
||||||
*/
|
|
||||||
NAM_PCMOutVolume = 0x18,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Select Record Input Register
|
|
||||||
* @note Length: word
|
|
||||||
*/
|
|
||||||
NAM_SelectRecordInput = 0x1A,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Record Gain Register
|
|
||||||
* @note Length: word
|
|
||||||
*/
|
|
||||||
NAM_RecordGain = 0x1C,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Record Gain Microphone Register
|
|
||||||
* @note Length: word
|
|
||||||
*/
|
|
||||||
NAM_RecordGainMicrophone = 0x1E,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum NativeAudioBusMasterRegisters
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @brief Register box for PCM IN
|
|
||||||
* @note Length: below
|
|
||||||
*/
|
|
||||||
NABM_PCMInBox = 0x00,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Register box for PCM OUT
|
|
||||||
* @note Length: below
|
|
||||||
*/
|
|
||||||
NABM_PCMOutBox = 0x10,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Register box for Microphone
|
|
||||||
* @note Length: below
|
|
||||||
*/
|
|
||||||
NABM_MicrophoneBox = 0x20,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Global Control Register
|
|
||||||
* @note Length: dword
|
|
||||||
*/
|
|
||||||
NABM_GlobalControl = 0x2C, /* 0x30 */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Global Status Register
|
|
||||||
* @note Length: dword
|
|
||||||
*/
|
|
||||||
NABM_GlobalStatus = 0x30, /* 0x34 */
|
|
||||||
};
|
|
||||||
|
|
||||||
enum NativeAudioBusMasterBoxOffsets
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @brief Physical Address of Buffer Descriptor List
|
|
||||||
* @note Length: dword
|
|
||||||
*/
|
|
||||||
NABMBOFF_BufferDescriptorList = 0x00,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Number of Actual Processed Buffer Descriptor Entry
|
|
||||||
* @note Length: byte
|
|
||||||
*/
|
|
||||||
NABMBOFF_BufferDescriptorEntry = 0x04,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Number of all Descriptor Entries
|
|
||||||
* @note Length: byte
|
|
||||||
*/
|
|
||||||
NABMBOFF_DescriptorEntries = 0x05,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Status of transferring Data
|
|
||||||
* @note Length: word
|
|
||||||
*/
|
|
||||||
NABMBOFF_Status = 0x06,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Number of transferred Samples in Actual Processed Entry
|
|
||||||
* @note Length: word
|
|
||||||
*/
|
|
||||||
NABMBOFF_TransferredSamples = 0x08,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Number of next processed Buffer Entry
|
|
||||||
* @note Length: byte
|
|
||||||
*/
|
|
||||||
NABMBOFF_NextProcessedBufferEntry = 0x0A,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Transfer Control
|
|
||||||
* @note Length: byte
|
|
||||||
*/
|
|
||||||
NABMBOFF_TransferControl = 0x0B,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum OutputPulseCodeModulationRegisters
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @brief Physical Address of Buffer Descriptor List
|
|
||||||
* @note Length: dword
|
|
||||||
*/
|
|
||||||
PCMOUT_BufferDescriptorList = (int)NABM_PCMOutBox + (int)NABMBOFF_BufferDescriptorList,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Number of Actual Processed Buffer Descriptor Entry
|
|
||||||
* @note Length: byte
|
|
||||||
*/
|
|
||||||
PCMOUT_BufferDescriptorEntry = (int)NABM_PCMOutBox + (int)NABMBOFF_BufferDescriptorEntry,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Number of all Descriptor Entries
|
|
||||||
* @note Length: byte
|
|
||||||
*/
|
|
||||||
PCMOUT_DescriptorEntries = (int)NABM_PCMOutBox + (int)NABMBOFF_DescriptorEntries,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Status of transferring Data
|
|
||||||
* @note Length: word
|
|
||||||
*/
|
|
||||||
PCMOUT_Status = (int)NABM_PCMOutBox + (int)NABMBOFF_Status,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Number of transferred Samples in Actual Processed Entry
|
|
||||||
* @note Length: word
|
|
||||||
*/
|
|
||||||
PCMOUT_TransferredSamples = (int)NABM_PCMOutBox + (int)NABMBOFF_TransferredSamples,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Number of next processed Buffer Entry
|
|
||||||
* @note Length: byte
|
|
||||||
*/
|
|
||||||
PCMOUT_NextProcessedBufferEntry = (int)NABM_PCMOutBox + (int)NABMBOFF_NextProcessedBufferEntry,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Transfer Control
|
|
||||||
* @note Length: byte
|
|
||||||
*/
|
|
||||||
PCMOUT_TransferControl = (int)NABM_PCMOutBox + (int)NABMBOFF_TransferControl,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum TransferControlRegisters
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @brief DMA controller control
|
|
||||||
*
|
|
||||||
* 0 = Pause transfer
|
|
||||||
* 1 = Transfer sound data
|
|
||||||
*/
|
|
||||||
TC_DMAControllerControl = 0x01,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Reset
|
|
||||||
*
|
|
||||||
* 0 = Remove reset condition
|
|
||||||
* 1 = Reset this NABM register box, this bit is cleared by card when is reset complete
|
|
||||||
*/
|
|
||||||
TC_TransferReset = 0x02,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Last Buffer Entry Interrupt enable
|
|
||||||
*
|
|
||||||
* 0 = Disable interrupt
|
|
||||||
* 1 = Enable interrupt
|
|
||||||
*/
|
|
||||||
TC_LastBufferEntryInterruptEnable = 0x04,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief IOC Interrupt enable
|
|
||||||
*
|
|
||||||
* 0 = Disable interrupt
|
|
||||||
* 1 = Enable interrupt
|
|
||||||
*/
|
|
||||||
TC_IOCInterruptEnable = 0x08,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Fifo ERROR Interrupt enable
|
|
||||||
*
|
|
||||||
* 0 = Disable interrupt
|
|
||||||
* 1 = Enable interrupt
|
|
||||||
*/
|
|
||||||
TC_FifoERRORInterruptEnable = 0x10,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum GlobalControlRegisters
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @brief Global Interrupt Enable
|
|
||||||
*
|
|
||||||
* 0 = Disable Interrupts
|
|
||||||
* 1 = Enable Interrupts
|
|
||||||
*/
|
|
||||||
GC_GlobalInterruptEnable = 0x01,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Cold reset
|
|
||||||
*
|
|
||||||
* 0 = Device is in reset and can not be used
|
|
||||||
* 1 = Resume to operational state
|
|
||||||
*/
|
|
||||||
GC_ColdReset = 0x02,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Warm reset
|
|
||||||
*/
|
|
||||||
GC_WarmReset = 0x04,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Shut down
|
|
||||||
*
|
|
||||||
* 0 = Device is powered
|
|
||||||
* 1 = Shut down
|
|
||||||
*/
|
|
||||||
GC_ShutDown = 0x08,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Channels for PCM Output
|
|
||||||
*
|
|
||||||
* 00 = 2 channels
|
|
||||||
* 01 = 4 channels
|
|
||||||
* 10 = 6 channels
|
|
||||||
* 11 = Reserved
|
|
||||||
*/
|
|
||||||
GC_ChannelsForPCMOutput = 0x30,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief PCM Output mode
|
|
||||||
*
|
|
||||||
* 00 = 16 bit samples
|
|
||||||
* 01 = 20 bit samples
|
|
||||||
*/
|
|
||||||
GC_PCMOutputMode = 0xC0,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct BufferDescriptorList
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @brief Physical Address to sound data in memory
|
|
||||||
* @note Length: dword
|
|
||||||
*/
|
|
||||||
uint32_t Address;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Number of samples in this buffer
|
|
||||||
* @note Length: word
|
|
||||||
*/
|
|
||||||
uint16_t SampleCount;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Flags
|
|
||||||
* @note Length: word
|
|
||||||
*
|
|
||||||
* Bit 15 = Interrupt fired when data from this entry is transferred
|
|
||||||
* Bit 14 = Last entry of buffer, stop playing
|
|
||||||
* Other bits = Reserved
|
|
||||||
*/
|
|
||||||
uint16_t Flags;
|
|
||||||
} __attribute__((packed));
|
|
||||||
|
|
||||||
uint16_t MixerVolume(uint8_t Left, uint8_t Right, bool Mute)
|
|
||||||
{
|
|
||||||
return ((uint16_t)((Right & 0x3F) |
|
|
||||||
((Left & 0x3F) << 0x8) |
|
|
||||||
(Mute & 1 << 0xF)));
|
|
||||||
}
|
|
||||||
|
|
||||||
class AC97Device
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
PCIHeader0 *Header;
|
|
||||||
BufferDescriptorList *DescriptorList = nullptr;
|
|
||||||
|
|
||||||
uint16_t MixerAddress;
|
|
||||||
uint16_t BusMasterAddress;
|
|
||||||
|
|
||||||
AudioEncodingValues Encoding = AE_PCMs16le;
|
|
||||||
char Channels = 2;
|
|
||||||
uint8_t Volume = AV_Maximum;
|
|
||||||
bool Mute = false;
|
|
||||||
int SampleRate = 48000;
|
|
||||||
char SampleSize = 2;
|
|
||||||
|
|
||||||
public:
|
|
||||||
size_t write(uint8_t *Buffer, size_t Size)
|
|
||||||
{
|
|
||||||
if (Buffer == nullptr)
|
|
||||||
{
|
|
||||||
KernelLog("Invalid buffer.");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((Size == 0) || (Size % (SampleSize * Channels)))
|
|
||||||
{
|
|
||||||
KernelLog("Invalid buffer length.");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
int TotalBDLToFill = (int)((Size + PAGE_SIZE - 1) >> 12);
|
|
||||||
|
|
||||||
while (Size > 0)
|
|
||||||
{
|
|
||||||
bool ActiveDMA = !(inw(BusMasterAddress + PCMOUT_Status) & TC_DMAControllerControl);
|
|
||||||
|
|
||||||
if (ActiveDMA)
|
|
||||||
{
|
|
||||||
int RemainingBDL = 0;
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
int CurrentBDL = inb(BusMasterAddress + PCMOUT_BufferDescriptorEntry);
|
|
||||||
int LastBDL = inb(BusMasterAddress + PCMOUT_DescriptorEntries);
|
|
||||||
|
|
||||||
RemainingBDL = LastBDL - CurrentBDL;
|
|
||||||
if (RemainingBDL < 0)
|
|
||||||
RemainingBDL += DescriptorListLength;
|
|
||||||
|
|
||||||
RemainingBDL += 1;
|
|
||||||
|
|
||||||
if (RemainingBDL >= DescriptorListLength - 1)
|
|
||||||
{
|
|
||||||
long SampleCount = DescriptorList[(CurrentBDL + 1) % DescriptorListLength].SampleCount / Channels;
|
|
||||||
if (SampleCount > 0)
|
|
||||||
Sleep(SampleCount * 1000 / SampleRate);
|
|
||||||
}
|
|
||||||
|
|
||||||
} while (RemainingBDL >= DescriptorListLength - 1 &&
|
|
||||||
!(inw(BusMasterAddress + PCMOUT_Status) & TC_DMAControllerControl));
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t CurrentBDL = inb(BusMasterAddress + PCMOUT_BufferDescriptorEntry);
|
|
||||||
uint8_t LastBDL = inb(BusMasterAddress + PCMOUT_DescriptorEntries);
|
|
||||||
uint8_t NextBDL = LastBDL % DescriptorListLength;
|
|
||||||
|
|
||||||
ActiveDMA = !(inw(BusMasterAddress + PCMOUT_Status) & TC_DMAControllerControl);
|
|
||||||
if (ActiveDMA)
|
|
||||||
{
|
|
||||||
NextBDL = (uint8_t)((LastBDL + 1) % DescriptorListLength);
|
|
||||||
if (NextBDL == CurrentBDL)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
size_t Wrote = (PAGE_SIZE > Size) ? size_t(Size)
|
|
||||||
: size_t(PAGE_SIZE);
|
|
||||||
|
|
||||||
if (Wrote == 0)
|
|
||||||
{
|
|
||||||
KernelLog("Wrote 0 bytes.");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy((void *)((uint64_t)DescriptorList[NextBDL].Address), Buffer, Wrote);
|
|
||||||
DescriptorList[NextBDL].Flags = 0;
|
|
||||||
|
|
||||||
Buffer += Wrote;
|
|
||||||
Size -= (unsigned int)Wrote;
|
|
||||||
|
|
||||||
DescriptorList[NextBDL].SampleCount = uint16_t(Wrote / SampleSize);
|
|
||||||
TotalBDLToFill--;
|
|
||||||
NextBDL = (uint8_t)((NextBDL + 1) % DescriptorListLength);
|
|
||||||
} while (TotalBDLToFill-- && NextBDL != CurrentBDL);
|
|
||||||
|
|
||||||
outb(BusMasterAddress + PCMOUT_DescriptorEntries, NextBDL - 1);
|
|
||||||
|
|
||||||
ActiveDMA = !(inw(BusMasterAddress + PCMOUT_Status) & TC_DMAControllerControl);
|
|
||||||
if (!ActiveDMA)
|
|
||||||
{
|
|
||||||
// Start DMA
|
|
||||||
outb(BusMasterAddress + PCMOUT_TransferControl,
|
|
||||||
inb(BusMasterAddress + PCMOUT_TransferControl) | TC_DMAControllerControl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Size;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ioctl(AudioIoctl, void *)
|
|
||||||
{
|
|
||||||
// if (Data->AudioCallback.Adjust._Volume)
|
|
||||||
// {
|
|
||||||
// Volume = (uint8_t)(0x3F - (0x3F * Data->AudioCallback.Adjust.Volume / 100));
|
|
||||||
// outw(BAR.MixerAddress + NAM_MasterVolume, MixerVolume(Volume, Volume, Mute));
|
|
||||||
// // outw(BAR.MixerAddress + NAM_PCMOutVolume, MixerVolume(Volume, Volume, Mute));
|
|
||||||
// }
|
|
||||||
// else if (Data->AudioCallback.Adjust._Encoding)
|
|
||||||
// {
|
|
||||||
// fixme("Encoding changing not supported yet.");
|
|
||||||
// }
|
|
||||||
// else if (Data->AudioCallback.Adjust._SampleRate)
|
|
||||||
// {
|
|
||||||
// switch (Data->AudioCallback.Adjust.SampleRate)
|
|
||||||
// {
|
|
||||||
// case 0:
|
|
||||||
// {
|
|
||||||
// SampleRate = 8000;
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// case 1:
|
|
||||||
// {
|
|
||||||
// SampleRate = 11025;
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// case 2:
|
|
||||||
// {
|
|
||||||
// SampleRate = 16000;
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// case 3:
|
|
||||||
// {
|
|
||||||
// SampleRate = 22050;
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// case 4:
|
|
||||||
// {
|
|
||||||
// SampleRate = 32000;
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// case 5:
|
|
||||||
// {
|
|
||||||
// SampleRate = 44100;
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// case 6:
|
|
||||||
// {
|
|
||||||
// SampleRate = 48000;
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// case 7:
|
|
||||||
// {
|
|
||||||
// SampleRate = 88200;
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// case 8:
|
|
||||||
// {
|
|
||||||
// SampleRate = 96000;
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// default:
|
|
||||||
// {
|
|
||||||
// SampleRate = 16000;
|
|
||||||
// error("Invalid sample rate. Defaulting to 16000.");
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// else if (Data->AudioCallback.Adjust._Channels)
|
|
||||||
// {
|
|
||||||
// switch (Data->AudioCallback.Adjust.Channels)
|
|
||||||
// {
|
|
||||||
// case 0:
|
|
||||||
// {
|
|
||||||
// Channels = 1; // Mono
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// case 1:
|
|
||||||
// {
|
|
||||||
// Channels = 2; // Stereo
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// default:
|
|
||||||
// {
|
|
||||||
// Channels = 2;
|
|
||||||
// error("Invalid channel count. Defaulting to 2.");
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnInterruptReceived(TrapFrame *)
|
|
||||||
{
|
|
||||||
uint16_t Status = inw(MixerAddress + PCMOUT_Status);
|
|
||||||
if (Status & TC_IOCInterruptEnable)
|
|
||||||
{
|
|
||||||
DebugLog("IOC");
|
|
||||||
outw(MixerAddress + PCMOUT_Status, TC_IOCInterruptEnable);
|
|
||||||
uint16_t CurrentBDL = inb(BusMasterAddress + PCMOUT_BufferDescriptorEntry);
|
|
||||||
uint16_t LastBDL = (CurrentBDL + 2) & (DescriptorListLength - 1);
|
|
||||||
outb(BusMasterAddress + PCMOUT_DescriptorEntries, LastBDL);
|
|
||||||
KernelLog("FIXME: CurrentBDL: %d, LastBDL: %d", CurrentBDL, LastBDL);
|
|
||||||
}
|
|
||||||
else if (Status & TC_LastBufferEntryInterruptEnable)
|
|
||||||
{
|
|
||||||
DebugLog("Last buffer entry");
|
|
||||||
// Stop DMA
|
|
||||||
uint8_t TransferControl = inb((uint16_t)(BusMasterAddress + PCMOUT_TransferControl));
|
|
||||||
TransferControl &= ~TC_DMAControllerControl;
|
|
||||||
outb((uint16_t)(BusMasterAddress + PCMOUT_TransferControl), TransferControl);
|
|
||||||
|
|
||||||
outw(MixerAddress + PCMOUT_Status, TC_LastBufferEntryInterruptEnable);
|
|
||||||
}
|
|
||||||
else if (Status & TC_FifoERRORInterruptEnable)
|
|
||||||
{
|
|
||||||
KernelLog("FIFO error");
|
|
||||||
outw(MixerAddress + PCMOUT_Status, TC_FifoERRORInterruptEnable);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DebugLog("Unknown interrupt status %#x", Status);
|
|
||||||
outw(MixerAddress + PCMOUT_Status, 0xFFFF);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Panic()
|
|
||||||
{
|
|
||||||
uint8_t TransferControl = inb((uint16_t)(BusMasterAddress + PCMOUT_TransferControl));
|
|
||||||
TransferControl &= ~(TC_LastBufferEntryInterruptEnable |
|
|
||||||
TC_IOCInterruptEnable |
|
|
||||||
TC_FifoERRORInterruptEnable);
|
|
||||||
outb((uint16_t)(BusMasterAddress + PCMOUT_TransferControl), TransferControl);
|
|
||||||
|
|
||||||
uint32_t GlobalControl = inl((uint16_t)(BusMasterAddress + NABM_GlobalControl));
|
|
||||||
GlobalControl &= ~GC_GlobalInterruptEnable;
|
|
||||||
GlobalControl |= GC_ShutDown;
|
|
||||||
outl((uint16_t)(BusMasterAddress + NABM_GlobalControl), GlobalControl);
|
|
||||||
}
|
|
||||||
|
|
||||||
AC97Device(PCIHeader0 *_Header)
|
|
||||||
: Header(_Header)
|
|
||||||
{
|
|
||||||
/* Native Audio Mixer Base Address */
|
|
||||||
uint32_t PCIBAR0 = Header->BAR0;
|
|
||||||
|
|
||||||
/* Native Audio Bus Master Base Address */
|
|
||||||
uint32_t PCIBAR1 = Header->BAR1;
|
|
||||||
|
|
||||||
// uint8_t Type = PCIBAR0 & 1;
|
|
||||||
MixerAddress = (uint16_t)(PCIBAR0 & (~3));
|
|
||||||
BusMasterAddress = PCIBAR1 & (~15);
|
|
||||||
|
|
||||||
uint16_t OutputPCMTransferControl = BusMasterAddress + PCMOUT_TransferControl;
|
|
||||||
|
|
||||||
/* DescriptorList address MUST be physical. */
|
|
||||||
DescriptorList = (BufferDescriptorList *)AllocateMemory(TO_PAGES(sizeof(BufferDescriptorList) * DescriptorListLength));
|
|
||||||
memset(DescriptorList, 0, sizeof(BufferDescriptorList) * DescriptorListLength);
|
|
||||||
|
|
||||||
uint16_t DLSampleCount = (uint16_t)(PAGE_SIZE / SampleSize);
|
|
||||||
for (int i = 0; i < DescriptorListLength; i++)
|
|
||||||
{
|
|
||||||
DescriptorList[i].Address = (uint32_t)(uintptr_t)AllocateMemory(TO_PAGES(sizeof(uint16_t *)));
|
|
||||||
DescriptorList[i].SampleCount = DLSampleCount;
|
|
||||||
DescriptorList[i].Flags = 0;
|
|
||||||
DebugLog("DescriptorList[%d] = { Address: %#lx, SampleCount: %d, Flags: %#lx }",
|
|
||||||
i,
|
|
||||||
DescriptorList[i].Address,
|
|
||||||
DescriptorList[i].SampleCount,
|
|
||||||
DescriptorList[i].Flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
outw(MixerAddress + NAM_MasterVolume, MixerVolume(Volume, Volume, Mute));
|
|
||||||
outw(MixerAddress + NAM_PCMOutVolume, MixerVolume(Volume, Volume, Mute));
|
|
||||||
|
|
||||||
Volume = 0x3F - (0x3F * /* VOL 50% */ 50 / 100);
|
|
||||||
outw(MixerAddress + NAM_MasterVolume, MixerVolume(Volume, Volume, Mute));
|
|
||||||
|
|
||||||
outb(OutputPCMTransferControl, inb(OutputPCMTransferControl) | TC_TransferReset);
|
|
||||||
while (inb(OutputPCMTransferControl) & TC_TransferReset)
|
|
||||||
;
|
|
||||||
|
|
||||||
uint32_t GlobalControl = inl(BusMasterAddress + NABM_GlobalControl);
|
|
||||||
GlobalControl = (GlobalControl & ~((0x3U) << 0x16)); /* PCM 16-bit mode */
|
|
||||||
GlobalControl = (GlobalControl & ~((0x3U) << 20)); /* 2 channels */
|
|
||||||
GlobalControl |= GC_GlobalInterruptEnable;
|
|
||||||
GlobalControl &= ~GC_ShutDown;
|
|
||||||
|
|
||||||
outl(BusMasterAddress + PCMOUT_BufferDescriptorList,
|
|
||||||
(uint32_t)(uint64_t)DescriptorList);
|
|
||||||
|
|
||||||
outl(BusMasterAddress + NABM_GlobalControl, GlobalControl);
|
|
||||||
|
|
||||||
uint8_t TransferControl = inb(OutputPCMTransferControl);
|
|
||||||
TransferControl |= TC_IOCInterruptEnable |
|
|
||||||
TC_FifoERRORInterruptEnable;
|
|
||||||
outb(OutputPCMTransferControl, TransferControl);
|
|
||||||
|
|
||||||
// Stop DMA
|
|
||||||
outb(OutputPCMTransferControl, inb(OutputPCMTransferControl) & ~TC_DMAControllerControl);
|
|
||||||
}
|
|
||||||
|
|
||||||
~AC97Device()
|
|
||||||
{
|
|
||||||
outw(MixerAddress + NAM_MasterVolume, MixerVolume(AV_Maximum, AV_Maximum, true));
|
|
||||||
outw(MixerAddress + NAM_PCMOutVolume, MixerVolume(AV_Maximum, AV_Maximum, true));
|
|
||||||
|
|
||||||
// Stop DMA
|
|
||||||
outb((uint16_t)(BusMasterAddress + PCMOUT_TransferControl),
|
|
||||||
inb((uint16_t)(BusMasterAddress + PCMOUT_TransferControl)) & ~TC_DMAControllerControl);
|
|
||||||
|
|
||||||
// Disable interrupts
|
|
||||||
uint8_t TransferControl = inb((uint16_t)(BusMasterAddress + PCMOUT_TransferControl));
|
|
||||||
|
|
||||||
TransferControl &= ~(TC_LastBufferEntryInterruptEnable |
|
|
||||||
TC_IOCInterruptEnable |
|
|
||||||
TC_FifoERRORInterruptEnable);
|
|
||||||
outb((uint16_t)(BusMasterAddress + PCMOUT_TransferControl), TransferControl);
|
|
||||||
|
|
||||||
// Disable global control
|
|
||||||
uint32_t GlobalControl = inl((uint16_t)(BusMasterAddress + NABM_GlobalControl));
|
|
||||||
GlobalControl &= ~GC_GlobalInterruptEnable;
|
|
||||||
GlobalControl |= GC_ShutDown;
|
|
||||||
outl((uint16_t)(BusMasterAddress + NABM_GlobalControl), GlobalControl);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
AC97Device *Drivers[4] = {nullptr};
|
|
||||||
dev_t AudioID[4] = {(dev_t)-1};
|
|
||||||
|
|
||||||
#define OIR(x) OIR_##x
|
|
||||||
#define CREATE_OIR(x) \
|
|
||||||
void OIR_##x(TrapFrame *f) { Drivers[x]->OnInterruptReceived(f); }
|
|
||||||
|
|
||||||
CREATE_OIR(0);
|
|
||||||
CREATE_OIR(1);
|
|
||||||
CREATE_OIR(2);
|
|
||||||
CREATE_OIR(3);
|
|
||||||
|
|
||||||
int __fs_Open(struct Inode *, int, mode_t) { return 0; }
|
|
||||||
int __fs_Close(struct Inode *) { return 0; }
|
|
||||||
ssize_t __fs_Read(struct Inode *, void *, size_t, off_t) { return 0; }
|
|
||||||
|
|
||||||
ssize_t __fs_Write(struct Inode *Node, const void *Buffer, size_t Size, off_t)
|
|
||||||
{
|
|
||||||
return Drivers[AudioID[Node->GetMinor()]]->write((uint8_t *)Buffer, Size);
|
|
||||||
}
|
|
||||||
|
|
||||||
int __fs_Ioctl(struct Inode *Node, unsigned long Request, void *Argp)
|
|
||||||
{
|
|
||||||
return Drivers[AudioID[Node->GetMinor()]]->ioctl((AudioIoctl)Request, Argp);
|
|
||||||
}
|
|
||||||
|
|
||||||
const struct InodeOperations AudioOps = {
|
|
||||||
.Lookup = nullptr,
|
|
||||||
.Create = nullptr,
|
|
||||||
.Remove = nullptr,
|
|
||||||
.Rename = nullptr,
|
|
||||||
.Read = __fs_Read,
|
|
||||||
.Write = __fs_Write,
|
|
||||||
.Truncate = nullptr,
|
|
||||||
.Open = __fs_Open,
|
|
||||||
.Close = __fs_Close,
|
|
||||||
.Ioctl = __fs_Ioctl,
|
|
||||||
.ReadDir = nullptr,
|
|
||||||
.MkDir = nullptr,
|
|
||||||
.RmDir = nullptr,
|
|
||||||
.SymLink = nullptr,
|
|
||||||
.ReadLink = nullptr,
|
|
||||||
.Seek = nullptr,
|
|
||||||
.Stat = nullptr,
|
|
||||||
};
|
|
||||||
|
|
||||||
PCIArray *Devices;
|
|
||||||
EXTERNC int cxx_Panic()
|
|
||||||
{
|
|
||||||
PCIArray *ctx = Devices;
|
|
||||||
short Count = 0;
|
|
||||||
while (ctx != nullptr)
|
|
||||||
{
|
|
||||||
if (Drivers[Count] != nullptr)
|
|
||||||
Drivers[Count]->Panic();
|
|
||||||
Count++;
|
|
||||||
ctx = (PCIArray *)ctx->Next;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
EXTERNC int cxx_Probe()
|
|
||||||
{
|
|
||||||
uint16_t VendorIDs[] = {0x8086, PCI_END};
|
|
||||||
uint16_t DeviceIDs[] = {0x2415, PCI_END};
|
|
||||||
Devices = GetPCIDevices(VendorIDs, DeviceIDs);
|
|
||||||
if (Devices == nullptr)
|
|
||||||
{
|
|
||||||
KernelLog("No AC'97 device found.");
|
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
|
|
||||||
PCIArray *ctx = Devices;
|
|
||||||
bool Found = false;
|
|
||||||
size_t Count = 0;
|
|
||||||
while (ctx != nullptr)
|
|
||||||
{
|
|
||||||
if (Count++ > sizeof(Drivers) / sizeof(AC97Device *))
|
|
||||||
break;
|
|
||||||
|
|
||||||
PCIHeader0 *PCIBaseAddress = (PCIHeader0 *)ctx->Device->Header;
|
|
||||||
uint32_t PCIBAR0 = PCIBaseAddress->BAR0;
|
|
||||||
uint8_t Type = PCIBAR0 & 1;
|
|
||||||
if (Type != 1)
|
|
||||||
{
|
|
||||||
KernelLog("Device %x:%x.%d BAR0 is not I/O.",
|
|
||||||
PCIBaseAddress->Header.VendorID,
|
|
||||||
PCIBaseAddress->Header.DeviceID,
|
|
||||||
PCIBaseAddress->Header.ProgIF);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
Found = true;
|
|
||||||
ctx = (PCIArray *)ctx->Next;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Found)
|
|
||||||
{
|
|
||||||
KernelLog("No valid AC'97 device found.");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
EXTERNC int cxx_Initialize()
|
|
||||||
{
|
|
||||||
PCIArray *ctx = Devices;
|
|
||||||
size_t Count = 0;
|
|
||||||
while (ctx != nullptr)
|
|
||||||
{
|
|
||||||
if (Count > sizeof(Drivers) / sizeof(AC97Device *))
|
|
||||||
break;
|
|
||||||
|
|
||||||
PCIHeader0 *PCIBaseAddress = (PCIHeader0 *)ctx->Device->Header;
|
|
||||||
uint32_t PCIBAR0 = PCIBaseAddress->BAR0;
|
|
||||||
uint8_t Type = PCIBAR0 & 1;
|
|
||||||
if (Type != 1)
|
|
||||||
{
|
|
||||||
KernelLog("Device %x:%x.%d BAR0 is not I/O.",
|
|
||||||
PCIBaseAddress->Header.VendorID,
|
|
||||||
PCIBaseAddress->Header.DeviceID,
|
|
||||||
PCIBaseAddress->Header.ProgIF);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
InitializePCI(ctx->Device);
|
|
||||||
|
|
||||||
Drivers[Count] = new AC97Device((PCIHeader0 *)ctx->Device->Header);
|
|
||||||
/* FIXME: bad code */
|
|
||||||
switch (Count)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
RegisterInterruptHandler(iLine(ctx->Device), (void *)OIR(0));
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
RegisterInterruptHandler(iLine(ctx->Device), (void *)OIR(1));
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
RegisterInterruptHandler(iLine(ctx->Device), (void *)OIR(2));
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
RegisterInterruptHandler(iLine(ctx->Device), (void *)OIR(3));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
dev_t ret = RegisterDevice(AUDIO_TYPE_PCM, &AudioOps);
|
|
||||||
AudioID[Count] = ret;
|
|
||||||
Count++;
|
|
||||||
ctx = (PCIArray *)ctx->Next;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
EXTERNC int cxx_Finalize()
|
|
||||||
{
|
|
||||||
PCIArray *ctx = Devices;
|
|
||||||
size_t Count = 0;
|
|
||||||
while (ctx != nullptr)
|
|
||||||
{
|
|
||||||
if (Count++ > sizeof(Drivers) / sizeof(AC97Device *))
|
|
||||||
break;
|
|
||||||
|
|
||||||
PCIHeader0 *PCIBaseAddress = (PCIHeader0 *)ctx->Device->Header;
|
|
||||||
uint32_t PCIBAR0 = PCIBaseAddress->BAR0;
|
|
||||||
uint8_t Type = PCIBAR0 & 1;
|
|
||||||
if (Type != 1)
|
|
||||||
{
|
|
||||||
KernelLog("Device %x:%x.%d BAR0 is not I/O.",
|
|
||||||
PCIBaseAddress->Header.VendorID,
|
|
||||||
PCIBaseAddress->Header.DeviceID,
|
|
||||||
PCIBaseAddress->Header.ProgIF);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
delete Drivers[Count++];
|
|
||||||
ctx->Device->Header->Command |= PCI_COMMAND_INTX_DISABLE;
|
|
||||||
ctx = (PCIArray *)ctx->Next;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < sizeof(AudioID) / sizeof(dev_t); i++)
|
|
||||||
{
|
|
||||||
if (AudioID[i] != (dev_t)-1)
|
|
||||||
UnregisterDevice(AudioID[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,31 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of Fennix Drivers.
|
|
||||||
|
|
||||||
Fennix Drivers is free software: you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU General Public License as
|
|
||||||
published by the Free Software Foundation, either version 3 of
|
|
||||||
the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
Fennix Drivers is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with Fennix Drivers. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <base.h>
|
|
||||||
|
|
||||||
#include "ac97.hpp"
|
|
||||||
|
|
||||||
int DriverEntry() { return cxx_Initialize(); }
|
|
||||||
int DriverFinal() { return cxx_Finalize(); }
|
|
||||||
int DriverPanic() { return cxx_Panic(); }
|
|
||||||
int DriverProbe() { return cxx_Probe(); }
|
|
||||||
|
|
||||||
DriverInfo("ac97",
|
|
||||||
"Audio Codec '97 Driver",
|
|
||||||
"EnderIce2",
|
|
||||||
0, 0, 1,
|
|
||||||
"GPLv3");
|
|
@ -1,35 +0,0 @@
|
|||||||
default:
|
|
||||||
$(error Do not run this Makefile directly!)
|
|
||||||
|
|
||||||
S_SOURCES = $(shell find ./ -type f -name '*.S')
|
|
||||||
C_SOURCES = $(shell find ./ -type f -name '*.c')
|
|
||||||
CXX_SOURCES = $(shell find ./ -type f -name '*.cpp')
|
|
||||||
HEADERS = $(sort $(dir $(wildcard ../../include/*)))
|
|
||||||
OBJ = $(C_SOURCES:.c=.o) $(CXX_SOURCES:.cpp=.o) $(S_SOURCES:.S=.o)
|
|
||||||
STACK_USAGE_OBJ = $(C_SOURCES:.c=.su) $(CXX_SOURCES:.cpp=.su)
|
|
||||||
|
|
||||||
FILENAME = $(notdir $(shell pwd)).drv
|
|
||||||
|
|
||||||
build: $(FILENAME)
|
|
||||||
mv $(FILENAME) $(OUTPUT_DIR)$(FILENAME)
|
|
||||||
|
|
||||||
$(FILENAME): $(OBJ)
|
|
||||||
$(info Linking $@)
|
|
||||||
$(CC) $(DRIVER_LDFLAGS) $(OBJ) $(OUTPUT_DIR)dcrt0.o -L$(OUTPUT_DIR) -lkernel -o $@
|
|
||||||
|
|
||||||
WARNCFLAG = -Wall -Wextra
|
|
||||||
|
|
||||||
%.o: %.c $(HEADERS)
|
|
||||||
$(info Compiling $<)
|
|
||||||
$(CC) $(DRIVER_CFLAGS) $(WARNCFLAG) -std=c17 -c $< -o $@
|
|
||||||
|
|
||||||
%.o: %.cpp $(HEADERS)
|
|
||||||
$(info Compiling $<)
|
|
||||||
$(CXX) $(DRIVER_CFLAGS) $(WARNCFLAG) -std=c++20 -fno-exceptions -fno-rtti -c $< -o $@
|
|
||||||
|
|
||||||
%.o: %.S
|
|
||||||
$(info Compiling $<)
|
|
||||||
$(AS) -o $@ $<
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -f file.map $(OBJ) $(STACK_USAGE_OBJ)
|
|
@ -1,263 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of Fennix Kernel.
|
|
||||||
|
|
||||||
Fennix Kernel is free software: you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU General Public License as
|
|
||||||
published by the Free Software Foundation, either version 3 of
|
|
||||||
the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
Fennix Kernel is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#include <audio.h>
|
|
||||||
#include <regs.h>
|
|
||||||
#include <base.h>
|
|
||||||
#include <pci.h>
|
|
||||||
#include <io.h>
|
|
||||||
#include <fs.h>
|
|
||||||
|
|
||||||
#include "hda.hpp"
|
|
||||||
|
|
||||||
class HDADevice
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
PCIHeader0 *Header;
|
|
||||||
bool Initialized = false;
|
|
||||||
|
|
||||||
ControllerRegisters *CTL;
|
|
||||||
|
|
||||||
uint32_t *CORB;
|
|
||||||
uint64_t *RIRB;
|
|
||||||
|
|
||||||
public:
|
|
||||||
bool IsInitialized() { return Initialized; }
|
|
||||||
|
|
||||||
size_t write(uint8_t *, size_t Size)
|
|
||||||
{
|
|
||||||
return Size;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ioctl(AudioIoctl, void *)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnInterruptReceived(TrapFrame *)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void Panic()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
HDADevice(PCIHeader0 *_Header)
|
|
||||||
: Header(_Header),
|
|
||||||
CORB((uint32_t *)(uintptr_t)AllocateMemory(1)),
|
|
||||||
RIRB((uint64_t *)AllocateMemory(1))
|
|
||||||
{
|
|
||||||
CTL = (ControllerRegisters *)(uintptr_t)Header->BAR0;
|
|
||||||
KernelLog("Unimplemented HDA driver");
|
|
||||||
return;
|
|
||||||
Initialized = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
~HDADevice()
|
|
||||||
{
|
|
||||||
if (!Initialized)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
HDADevice *Drivers[4] = {nullptr};
|
|
||||||
dev_t AudioID[4] = {(dev_t)-1};
|
|
||||||
|
|
||||||
#define OIR(x) OIR_##x
|
|
||||||
#define CREATE_OIR(x) \
|
|
||||||
void OIR_##x(TrapFrame *f) { Drivers[x]->OnInterruptReceived(f); }
|
|
||||||
|
|
||||||
CREATE_OIR(0);
|
|
||||||
CREATE_OIR(1);
|
|
||||||
CREATE_OIR(2);
|
|
||||||
CREATE_OIR(3);
|
|
||||||
|
|
||||||
int __fs_Open(struct Inode *, int, mode_t) { return 0; }
|
|
||||||
int __fs_Close(struct Inode *) { return 0; }
|
|
||||||
ssize_t __fs_Read(struct Inode *, void *, size_t, off_t) { return 0; }
|
|
||||||
|
|
||||||
ssize_t __fs_Write(struct Inode *Node, const void *Buffer, size_t Size, off_t)
|
|
||||||
{
|
|
||||||
return Drivers[AudioID[Node->GetMinor()]]->write((uint8_t *)Buffer, Size);
|
|
||||||
}
|
|
||||||
|
|
||||||
int __fs_Ioctl(struct Inode *Node, unsigned long Request, void *Argp)
|
|
||||||
{
|
|
||||||
return Drivers[AudioID[Node->GetMinor()]]->ioctl((AudioIoctl)Request, Argp);
|
|
||||||
}
|
|
||||||
|
|
||||||
const struct InodeOperations AudioOps = {
|
|
||||||
.Lookup = nullptr,
|
|
||||||
.Create = nullptr,
|
|
||||||
.Remove = nullptr,
|
|
||||||
.Rename = nullptr,
|
|
||||||
.Read = __fs_Read,
|
|
||||||
.Write = __fs_Write,
|
|
||||||
.Truncate = nullptr,
|
|
||||||
.Open = __fs_Open,
|
|
||||||
.Close = __fs_Close,
|
|
||||||
.Ioctl = __fs_Ioctl,
|
|
||||||
.ReadDir = nullptr,
|
|
||||||
.MkDir = nullptr,
|
|
||||||
.RmDir = nullptr,
|
|
||||||
.SymLink = nullptr,
|
|
||||||
.ReadLink = nullptr,
|
|
||||||
.Seek = nullptr,
|
|
||||||
.Stat = nullptr,
|
|
||||||
};
|
|
||||||
|
|
||||||
PCIArray *Devices;
|
|
||||||
EXTERNC int cxx_Panic()
|
|
||||||
{
|
|
||||||
PCIArray *ctx = Devices;
|
|
||||||
short Count = 0;
|
|
||||||
while (ctx != nullptr)
|
|
||||||
{
|
|
||||||
if (Drivers[Count] != nullptr)
|
|
||||||
Drivers[Count]->Panic();
|
|
||||||
Count++;
|
|
||||||
ctx = (PCIArray *)ctx->Next;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
EXTERNC int cxx_Probe()
|
|
||||||
{
|
|
||||||
uint16_t VendorIDs[] = {0x8086, /* Intel */
|
|
||||||
0x15AD, /* VMware */
|
|
||||||
PCI_END};
|
|
||||||
uint16_t DeviceIDs[] = {0x9D71 /* Sunrise Point-LP HD Audio */,
|
|
||||||
0x2668 /* ICH6 */,
|
|
||||||
0x293E /* ICH9 */,
|
|
||||||
PCI_END};
|
|
||||||
Devices = GetPCIDevices(VendorIDs, DeviceIDs);
|
|
||||||
if (Devices == nullptr)
|
|
||||||
{
|
|
||||||
KernelLog("No HDA device found.");
|
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
|
|
||||||
PCIArray *ctx = Devices;
|
|
||||||
bool Found = false;
|
|
||||||
size_t Count = 0;
|
|
||||||
while (ctx != nullptr)
|
|
||||||
{
|
|
||||||
if (Count++ > sizeof(Drivers) / sizeof(HDADevice *))
|
|
||||||
break;
|
|
||||||
|
|
||||||
PCIHeader0 *PCIBaseAddress = (PCIHeader0 *)ctx->Device->Header;
|
|
||||||
uint32_t PCIBAR0 = PCIBaseAddress->BAR0;
|
|
||||||
uint8_t Type = PCIBAR0 & 1;
|
|
||||||
if (Type == 1)
|
|
||||||
{
|
|
||||||
KernelLog("Device %x:%x.%d BAR0 is I/O.",
|
|
||||||
PCIBaseAddress->Header.VendorID,
|
|
||||||
PCIBaseAddress->Header.DeviceID,
|
|
||||||
PCIBaseAddress->Header.ProgIF);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
Found = true;
|
|
||||||
ctx = (PCIArray *)ctx->Next;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Found)
|
|
||||||
{
|
|
||||||
KernelLog("No valid HDA device found.");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
EXTERNC int cxx_Initialize()
|
|
||||||
{
|
|
||||||
PCIArray *ctx = Devices;
|
|
||||||
size_t Count = 0;
|
|
||||||
while (ctx != nullptr)
|
|
||||||
{
|
|
||||||
if (Count > sizeof(Drivers) / sizeof(HDADevice *))
|
|
||||||
break;
|
|
||||||
|
|
||||||
PCIHeader0 *PCIBaseAddress = (PCIHeader0 *)ctx->Device->Header;
|
|
||||||
uint32_t PCIBAR0 = PCIBaseAddress->BAR0;
|
|
||||||
uint8_t Type = PCIBAR0 & 1;
|
|
||||||
if (Type == 1)
|
|
||||||
{
|
|
||||||
KernelLog("Device %x:%x.%d BAR0 is I/O.",
|
|
||||||
PCIBaseAddress->Header.VendorID,
|
|
||||||
PCIBaseAddress->Header.DeviceID,
|
|
||||||
PCIBaseAddress->Header.ProgIF);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
InitializePCI(ctx->Device);
|
|
||||||
|
|
||||||
Drivers[Count] = new HDADevice((PCIHeader0 *)ctx->Device->Header);
|
|
||||||
|
|
||||||
if (Drivers[Count]->IsInitialized())
|
|
||||||
{
|
|
||||||
dev_t ret = RegisterDevice(AUDIO_TYPE_PCM, &AudioOps);
|
|
||||||
AudioID[Count] = ret;
|
|
||||||
Count++;
|
|
||||||
}
|
|
||||||
ctx = (PCIArray *)ctx->Next;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Count == 0)
|
|
||||||
{
|
|
||||||
KernelLog("No valid HDA device found.");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
EXTERNC int cxx_Finalize()
|
|
||||||
{
|
|
||||||
PCIArray *ctx = Devices;
|
|
||||||
size_t Count = 0;
|
|
||||||
while (ctx != nullptr)
|
|
||||||
{
|
|
||||||
if (Count++ > sizeof(Drivers) / sizeof(HDADevice *))
|
|
||||||
break;
|
|
||||||
|
|
||||||
PCIHeader0 *PCIBaseAddress = (PCIHeader0 *)ctx->Device->Header;
|
|
||||||
uint32_t PCIBAR0 = PCIBaseAddress->BAR0;
|
|
||||||
uint8_t Type = PCIBAR0 & 1;
|
|
||||||
if (Type == 1)
|
|
||||||
{
|
|
||||||
KernelLog("Device %x:%x.%d BAR0 is I/O.",
|
|
||||||
PCIBaseAddress->Header.VendorID,
|
|
||||||
PCIBaseAddress->Header.DeviceID,
|
|
||||||
PCIBaseAddress->Header.ProgIF);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
delete Drivers[Count++];
|
|
||||||
ctx = (PCIArray *)ctx->Next;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < sizeof(AudioID) / sizeof(dev_t); i++)
|
|
||||||
{
|
|
||||||
if (AudioID[i] != (dev_t)-1)
|
|
||||||
UnregisterDevice(AudioID[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,31 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of Fennix Drivers.
|
|
||||||
|
|
||||||
Fennix Drivers is free software: you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU General Public License as
|
|
||||||
published by the Free Software Foundation, either version 3 of
|
|
||||||
the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
Fennix Drivers is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with Fennix Drivers. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <base.h>
|
|
||||||
|
|
||||||
#include "hda.hpp"
|
|
||||||
|
|
||||||
int DriverEntry() { return cxx_Initialize(); }
|
|
||||||
int DriverFinal() { return cxx_Finalize(); }
|
|
||||||
int DriverPanic() { return cxx_Panic(); }
|
|
||||||
int DriverProbe() { return cxx_Probe(); }
|
|
||||||
|
|
||||||
DriverInfo("hda",
|
|
||||||
"Intel High Definition Audio Driver",
|
|
||||||
"EnderIce2",
|
|
||||||
0, 0, 1,
|
|
||||||
"GPLv3");
|
|
@ -1,35 +0,0 @@
|
|||||||
default:
|
|
||||||
$(error Do not run this Makefile directly!)
|
|
||||||
|
|
||||||
S_SOURCES = $(shell find ./ -type f -name '*.S')
|
|
||||||
C_SOURCES = $(shell find ./ -type f -name '*.c')
|
|
||||||
CXX_SOURCES = $(shell find ./ -type f -name '*.cpp')
|
|
||||||
HEADERS = $(sort $(dir $(wildcard ../../include/*)))
|
|
||||||
OBJ = $(C_SOURCES:.c=.o) $(CXX_SOURCES:.cpp=.o) $(S_SOURCES:.S=.o)
|
|
||||||
STACK_USAGE_OBJ = $(C_SOURCES:.c=.su) $(CXX_SOURCES:.cpp=.su)
|
|
||||||
|
|
||||||
FILENAME = $(notdir $(shell pwd)).drv
|
|
||||||
|
|
||||||
build: $(FILENAME)
|
|
||||||
mv $(FILENAME) $(OUTPUT_DIR)$(FILENAME)
|
|
||||||
|
|
||||||
$(FILENAME): $(OBJ)
|
|
||||||
$(info Linking $@)
|
|
||||||
$(CC) $(DRIVER_LDFLAGS) $(OBJ) $(OUTPUT_DIR)dcrt0.o -L$(OUTPUT_DIR) -lkernel -o $@
|
|
||||||
|
|
||||||
WARNCFLAG = -Wall -Wextra
|
|
||||||
|
|
||||||
%.o: %.c $(HEADERS)
|
|
||||||
$(info Compiling $<)
|
|
||||||
$(CC) $(DRIVER_CFLAGS) $(WARNCFLAG) -std=c17 -c $< -o $@
|
|
||||||
|
|
||||||
%.o: %.cpp $(HEADERS)
|
|
||||||
$(info Compiling $<)
|
|
||||||
$(CXX) $(DRIVER_CFLAGS) $(WARNCFLAG) -std=c++20 -fno-exceptions -fno-rtti -c $< -o $@
|
|
||||||
|
|
||||||
%.o: %.S
|
|
||||||
$(info Compiling $<)
|
|
||||||
$(AS) -o $@ $<
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -f file.map $(OBJ) $(STACK_USAGE_OBJ)
|
|
@ -1,45 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of Fennix Drivers.
|
|
||||||
|
|
||||||
Fennix Drivers is free software: you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU General Public License as
|
|
||||||
published by the Free Software Foundation, either version 3 of
|
|
||||||
the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
Fennix Drivers is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with Fennix Drivers. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <base.h>
|
|
||||||
|
|
||||||
int DriverEntry()
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int DriverFinal()
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int DriverPanic()
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int DriverProbe()
|
|
||||||
{
|
|
||||||
/* Nothing to do */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
DriverInfo("fat",
|
|
||||||
"File Allocation Table Driver",
|
|
||||||
"EnderIce2",
|
|
||||||
0, 0, 1,
|
|
||||||
"GPLv3");
|
|
@ -103,6 +103,7 @@ typedef union
|
|||||||
uint8_t Raw;
|
uint8_t Raw;
|
||||||
} PS2_OUTPUT_PORT;
|
} PS2_OUTPUT_PORT;
|
||||||
|
|
||||||
|
#ifndef __kernel__
|
||||||
void PIC_EOI(uint8_t IRQ);
|
void PIC_EOI(uint8_t IRQ);
|
||||||
void IRQ_MASK(uint8_t IRQ);
|
void IRQ_MASK(uint8_t IRQ);
|
||||||
void IRQ_UNMASK(uint8_t IRQ);
|
void IRQ_UNMASK(uint8_t IRQ);
|
||||||
@ -114,11 +115,11 @@ uint8_t PS2ReadStatus();
|
|||||||
uint8_t PS2ReadAfterACK();
|
uint8_t PS2ReadAfterACK();
|
||||||
void PS2ClearOutputBuffer();
|
void PS2ClearOutputBuffer();
|
||||||
int PS2ACKTimeout();
|
int PS2ACKTimeout();
|
||||||
|
#endif // !__kernel__
|
||||||
|
|
||||||
#define WaitOutput PS2Wait(DriverID, true)
|
#define WaitOutput PS2Wait(DriverID, true)
|
||||||
#define WaitInput PS2Wait(DriverID, false)
|
#define WaitInput PS2Wait(DriverID, false)
|
||||||
|
|
||||||
|
|
||||||
#define PS2_KBD_CMD_SET_LEDS 0xED
|
#define PS2_KBD_CMD_SET_LEDS 0xED
|
||||||
#define PS2_KBD_CMD_ECHO 0xEE
|
#define PS2_KBD_CMD_ECHO 0xEE
|
||||||
#define PS2_KBD_CMD_SCAN_CODE_SET 0xF0
|
#define PS2_KBD_CMD_SCAN_CODE_SET 0xF0
|
||||||
@ -189,7 +190,6 @@ typedef union
|
|||||||
uint8_t Raw;
|
uint8_t Raw;
|
||||||
} PS2_KBD_TYPEMATIC;
|
} PS2_KBD_TYPEMATIC;
|
||||||
|
|
||||||
|
|
||||||
#define PS2_MOUSE_CMD_SET_SCALING_1_1 0xE6
|
#define PS2_MOUSE_CMD_SET_SCALING_1_1 0xE6
|
||||||
#define PS2_MOUSE_CMD_SET_SCALING_2_1 0xE7
|
#define PS2_MOUSE_CMD_SET_SCALING_2_1 0xE7
|
||||||
#define PS2_MOUSE_CMD_SET_RESOLUTION 0xE8
|
#define PS2_MOUSE_CMD_SET_RESOLUTION 0xE8
|
||||||
|
110
Drivers/include/block.h
Normal file
110
Drivers/include/block.h
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Fennix Kernel.
|
||||||
|
|
||||||
|
Fennix Kernel is free software: you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation, either version 3 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
Fennix Kernel is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __FENNIX_API_BLOCK_H__
|
||||||
|
#define __FENNIX_API_BLOCK_H__
|
||||||
|
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
#if __has_include(<interface/fs.h>)
|
||||||
|
#include <interface/fs.h>
|
||||||
|
#else
|
||||||
|
#include <fs.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct BlockDevice
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @brief Base name of the device.
|
||||||
|
*
|
||||||
|
* This name is used to identify the device in the system. It should be unique
|
||||||
|
* across all block devices. The kernel may append a number to this name to
|
||||||
|
* create a unique device name (e.g., "ahci0", "ahci1").
|
||||||
|
*/
|
||||||
|
const char *Name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Total size of the device in bytes.
|
||||||
|
*
|
||||||
|
* This value represents the total addressable storage capacity of the device.
|
||||||
|
* It is used for bounds checking and partitioning.
|
||||||
|
*/
|
||||||
|
size_t Size;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Size of a single block in bytes.
|
||||||
|
*
|
||||||
|
* All read and write operations are performed in multiples of this block size.
|
||||||
|
* Typical values are 512 or 4096 bytes.
|
||||||
|
*/
|
||||||
|
uint32_t BlockSize;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Number of blocks in the device.
|
||||||
|
*
|
||||||
|
* This value is calculated as Size / BlockSize. It represents the total number
|
||||||
|
* of addressable blocks on the device.
|
||||||
|
*/
|
||||||
|
size_t BlockCount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Pointer to the block device operations structure.
|
||||||
|
*
|
||||||
|
* This structure contains function pointers for various operations that can
|
||||||
|
* be performed on the block device, such as read, write, and ioctl.
|
||||||
|
*
|
||||||
|
* Yea, inode operations are used for block devices too.
|
||||||
|
*/
|
||||||
|
const InodeOperations *Ops;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Opaque pointer to driver-specific or hardware-specific data.
|
||||||
|
*
|
||||||
|
* This field allows the driver to associate private context or state with the
|
||||||
|
* device, such as controller registers or internal buffers.
|
||||||
|
*/
|
||||||
|
void *PrivateData;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifndef __kernel__
|
||||||
|
/**
|
||||||
|
* @brief Registers a block device with the kernel block subsystem.
|
||||||
|
*
|
||||||
|
* This function should be called by block device drivers after initializing
|
||||||
|
* a device. The kernel will take ownership of the device structure and assign
|
||||||
|
* it a unique device ID. The device will then be accessible for filesystem
|
||||||
|
* mounting and I/O operations.
|
||||||
|
*
|
||||||
|
* @param Device Pointer to a fully initialized BlockDevice structure. All required fields must be set and valid for the lifetime of the device.
|
||||||
|
* @return Device ID (dev_t) assigned by the kernel on success, or an error code on failure.
|
||||||
|
*/
|
||||||
|
dev_t RegisterBlockDevice(struct BlockDevice *Device);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Unregisters a block device from the kernel block subsystem.
|
||||||
|
*
|
||||||
|
* This function should be called by drivers when a device is being removed
|
||||||
|
* or is no longer available. The kernel will release any resources associated
|
||||||
|
* with the device and invalidate its device ID.
|
||||||
|
*
|
||||||
|
* @param DeviceID The device ID (dev_t) previously returned by RegisterBlockDevice().
|
||||||
|
* @return 0 on success, or an error code.
|
||||||
|
*/
|
||||||
|
int UnregisterBlockDevice(dev_t DeviceID);
|
||||||
|
#endif // __kernel__
|
||||||
|
|
||||||
|
#endif // __FENNIX_API_BLOCK_H__
|
@ -69,7 +69,10 @@ typedef enum
|
|||||||
BLOCK_TYPE_FLOPPY = DEVICE_TYPE_BLOCK + 128,
|
BLOCK_TYPE_FLOPPY = DEVICE_TYPE_BLOCK + 128,
|
||||||
} DeviceType;
|
} DeviceType;
|
||||||
|
|
||||||
|
#ifndef __kernel__
|
||||||
|
EXTERNC dev_t CreateDeviceFile(const char *name, mode_t mode, const struct InodeOperations *Operations);
|
||||||
EXTERNC dev_t RegisterDevice(DeviceType Type, const struct InodeOperations *Operations);
|
EXTERNC dev_t RegisterDevice(DeviceType Type, const struct InodeOperations *Operations);
|
||||||
EXTERNC int UnregisterDevice(dev_t Device);
|
EXTERNC int UnregisterDevice(dev_t Device);
|
||||||
|
#endif // !__kernel__
|
||||||
|
|
||||||
#endif // !__FENNIX_API_DEVICE_H__
|
#endif // !__FENNIX_API_DEVICE_H__
|
||||||
|
@ -25,14 +25,13 @@
|
|||||||
* Full list:
|
* Full list:
|
||||||
* https://pubs.opengroup.org/onlinepubs/9699919799.2018edition/basedefs/errno.h.html
|
* https://pubs.opengroup.org/onlinepubs/9699919799.2018edition/basedefs/errno.h.html
|
||||||
*/
|
*/
|
||||||
typedef enum
|
|
||||||
{
|
/**
|
||||||
/**
|
|
||||||
* No Error
|
* No Error
|
||||||
*/
|
*/
|
||||||
EOK = 0,
|
#define EOK 0
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Argument list too long. The sum of the number of bytes used by the
|
* Argument list too long. The sum of the number of bytes used by the
|
||||||
* new process image's argument list and environment list is greater
|
* new process image's argument list and environment list is greater
|
||||||
* than the system-imposed limit of {ARG_MAX} bytes.
|
* than the system-imposed limit of {ARG_MAX} bytes.
|
||||||
@ -41,52 +40,52 @@ typedef enum
|
|||||||
* or:
|
* or:
|
||||||
* Argument is greater than the system-imposed maximum.
|
* Argument is greater than the system-imposed maximum.
|
||||||
*/
|
*/
|
||||||
E2BIG = 1,
|
#define E2BIG 1
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Permission denied. An attempt was made to access a file in a way
|
* Permission denied. An attempt was made to access a file in a way
|
||||||
* forbidden by its file access permissions.
|
* forbidden by its file access permissions.
|
||||||
*/
|
*/
|
||||||
EACCES = 2,
|
#define EACCES 2
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Address in use. The specified address is in use.
|
* Address in use. The specified address is in use.
|
||||||
*/
|
*/
|
||||||
EADDRINUSE = 3,
|
#define EADDRINUSE 3
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Address not available. The specified address is not available from
|
* Address not available. The specified address is not available from
|
||||||
* the local system.
|
* the local system.
|
||||||
*/
|
*/
|
||||||
EADDRNOTAVAIL = 4,
|
#define EADDRNOTAVAIL 4
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Address family not supported. The implementation does not support
|
* Address family not supported. The implementation does not support
|
||||||
* the specified address family, or the specified address is not a
|
* the specified address family, or the specified address is not a
|
||||||
* valid address for the address family of the specified socket.
|
* valid address for the address family of the specified socket.
|
||||||
*/
|
*/
|
||||||
EAFNOSUPPORT = 5,
|
#define EAFNOSUPPORT 5
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resource temporarily unavailable. This is a temporary condition
|
* Resource temporarily unavailable. This is a temporary condition
|
||||||
* and later calls to the same routine may complete normally.
|
* and later calls to the same routine may complete normally.
|
||||||
*/
|
*/
|
||||||
EAGAIN = 6,
|
#define EAGAIN 6
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Connection already in progress. A connection request is already in
|
* Connection already in progress. A connection request is already in
|
||||||
* progress for the specified socket.
|
* progress for the specified socket.
|
||||||
*/
|
*/
|
||||||
EALREADY = 7,
|
#define EALREADY 7
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bad file descriptor. A file descriptor argument is out of range,
|
* Bad file descriptor. A file descriptor argument is out of range,
|
||||||
* refers to no open file, or a read (write) request is made to a
|
* refers to no open file, or a read (write) request is made to a
|
||||||
* file that is only open for writing (reading).
|
* file that is only open for writing (reading).
|
||||||
*/
|
*/
|
||||||
EBADF = 8,
|
#define EBADF 8
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bad message. During a read(), getmsg(), getpmsg(), or ioctl()
|
* Bad message. During a read(), getmsg(), getpmsg(), or ioctl()
|
||||||
* I_RECVFD request to a STREAMS device, a message arrived at the
|
* I_RECVFD request to a STREAMS device, a message arrived at the
|
||||||
* head of the STREAM that is inappropriate for the function
|
* head of the STREAM that is inappropriate for the function
|
||||||
@ -99,191 +98,191 @@ typedef enum
|
|||||||
* Control or data information was received instead of a file
|
* Control or data information was received instead of a file
|
||||||
* descriptor when I_RECVFD was specified.
|
* descriptor when I_RECVFD was specified.
|
||||||
*/
|
*/
|
||||||
EBADMSG = 9,
|
#define EBADMSG 9
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resource busy. An attempt was made to make use of a system
|
* Resource busy. An attempt was made to make use of a system
|
||||||
* resource that is not currently available, as it is being
|
* resource that is not currently available, as it is being
|
||||||
* used by another process in a manner that would have
|
* used by another process in a manner that would have
|
||||||
* conflicted with the request being made by this process.
|
* conflicted with the request being made by this process.
|
||||||
*/
|
*/
|
||||||
EBUSY = 10,
|
#define EBUSY 10
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Operation canceled. The associated asynchronous operation was
|
* Operation canceled. The associated asynchronous operation was
|
||||||
* canceled before completion.
|
* canceled before completion.
|
||||||
*/
|
*/
|
||||||
ECANCELED = 11,
|
#define ECANCELED 11
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* No child process. A wait(), waitid(), or waitpid() function was
|
* No child process. A wait(), waitid(), or waitpid() function was
|
||||||
* executed by a process that had no existing or unwaited-for
|
* executed by a process that had no existing or unwaited-for
|
||||||
* child process.
|
* child process.
|
||||||
*/
|
*/
|
||||||
ECHILD = 12,
|
#define ECHILD 12
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Connection aborted. The connection has been aborted.
|
* Connection aborted. The connection has been aborted.
|
||||||
*/
|
*/
|
||||||
ECONNABORTED = 13,
|
#define ECONNABORTED 13
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Connection refused. An attempt to connect to a socket was refused
|
* Connection refused. An attempt to connect to a socket was refused
|
||||||
* because there was no process listening or because the queue of
|
* because there was no process listening or because the queue of
|
||||||
* connection requests was full and the underlying protocol does not
|
* connection requests was full and the underlying protocol does not
|
||||||
* support retransmissions.
|
* support retransmissions.
|
||||||
*/
|
*/
|
||||||
ECONNREFUSED = 14,
|
#define ECONNREFUSED 14
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Connection reset. The connection was forcibly closed by the peer.
|
* Connection reset. The connection was forcibly closed by the peer.
|
||||||
*/
|
*/
|
||||||
ECONNRESET = 15,
|
#define ECONNRESET 15
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resource deadlock would occur. An attempt was made to lock a system
|
* Resource deadlock would occur. An attempt was made to lock a system
|
||||||
* resource that would have resulted in a deadlock situation.
|
* resource that would have resulted in a deadlock situation.
|
||||||
*/
|
*/
|
||||||
EDEADLK = 16,
|
#define EDEADLK 16
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destination address required. No bind address was established.
|
* Destination address required. No bind address was established.
|
||||||
*/
|
*/
|
||||||
EDESTADDRREQ = 17,
|
#define EDESTADDRREQ 17
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Domain error. An input argument is outside the defined domain of the
|
* Domain error. An input argument is outside the defined domain of the
|
||||||
* mathematical function (defined in the ISO C standard).
|
* mathematical function (defined in the ISO C standard).
|
||||||
*/
|
*/
|
||||||
EDOM = 18,
|
#define EDOM 18
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reserved.
|
* Reserved.
|
||||||
*/
|
*/
|
||||||
EDQUOT = 19,
|
#define EDQUOT 19
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* File exists. An existing file was mentioned in an inappropriate
|
* File exists. An existing file was mentioned in an inappropriate
|
||||||
* context; for example, as a new link name in the link() function.
|
* context; for example, as a new link name in the link() function.
|
||||||
*/
|
*/
|
||||||
EEXIST = 20,
|
#define EEXIST 20
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bad address. The system detected an invalid address in attempting
|
* Bad address. The system detected an invalid address in attempting
|
||||||
* to use an argument of a call. The reliable detection of this error
|
* to use an argument of a call. The reliable detection of this error
|
||||||
* cannot be guaranteed, and when not detected may result in the
|
* cannot be guaranteed, and when not detected may result in the
|
||||||
* generation of a signal, indicating an address violation, which is
|
* generation of a signal, indicating an address violation, which is
|
||||||
* sent to the process.
|
* sent to the process.
|
||||||
*/
|
*/
|
||||||
EFAULT = 21,
|
#define EFAULT 21
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* File too large. The size of a file would exceed the maximum file
|
* File too large. The size of a file would exceed the maximum file
|
||||||
* size of an implementation or offset maximum established in the
|
* size of an implementation or offset maximum established in the
|
||||||
* corresponding file description.
|
* corresponding file description.
|
||||||
*/
|
*/
|
||||||
EFBIG = 22,
|
#define EFBIG 22
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Host is unreachable. The destination host cannot be reached
|
* Host is unreachable. The destination host cannot be reached
|
||||||
* (probably because the host is down or a remote router cannot
|
* (probably because the host is down or a remote router cannot
|
||||||
* reach it).
|
* reach it).
|
||||||
*/
|
*/
|
||||||
EHOSTUNREACH = 23,
|
#define EHOSTUNREACH 23
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Identifier removed. Returned during XSI interprocess communication
|
* Identifier removed. Returned during XSI interprocess communication
|
||||||
* if an identifier has been removed from the system.
|
* if an identifier has been removed from the system.
|
||||||
*/
|
*/
|
||||||
EIDRM = 24,
|
#define EIDRM 24
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Illegal byte sequence. A wide-character code has been detected that
|
* Illegal byte sequence. A wide-character code has been detected that
|
||||||
* does not correspond to a valid character, or a byte sequence does
|
* does not correspond to a valid character, or a byte sequence does
|
||||||
* not form a valid wide-character code (defined in the ISO C standard).
|
* not form a valid wide-character code (defined in the ISO C standard).
|
||||||
*/
|
*/
|
||||||
EILSEQ = 25,
|
#define EILSEQ 25
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Operation in progress. This code is used to indicate that an
|
* Operation in progress. This code is used to indicate that an
|
||||||
* asynchronous operation has not yet completed.
|
* asynchronous operation has not yet completed.
|
||||||
* or:
|
* or:
|
||||||
* O_NONBLOCK is set for the socket file descriptor and the connection
|
* O_NONBLOCK is set for the socket file descriptor and the connection
|
||||||
* cannot be immediately established.
|
* cannot be immediately established.
|
||||||
*/
|
*/
|
||||||
EINPROGRESS = 26,
|
#define EINPROGRESS 26
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interrupted function call. An asynchronous signal was caught by the
|
* Interrupted function call. An asynchronous signal was caught by the
|
||||||
* process during the execution of an interruptible function. If the
|
* process during the execution of an interruptible function. If the
|
||||||
* signal handler performs a normal return, the interrupted function
|
* signal handler performs a normal return, the interrupted function
|
||||||
* call may return this condition (see the Base Definitions volume
|
* call may return this condition (see the Base Definitions volume
|
||||||
* of POSIX.1-2017, <signal.h>).
|
* of POSIX.1-2017, <signal.h>).
|
||||||
*/
|
*/
|
||||||
EINTR = 27,
|
#define EINTR 27
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invalid argument. Some invalid argument was supplied; for example,
|
* Invalid argument. Some invalid argument was supplied; for example,
|
||||||
* specifying an undefined signal in a signal() function or a
|
* specifying an undefined signal in a signal() function or a
|
||||||
* kill() function.
|
* kill() function.
|
||||||
*/
|
*/
|
||||||
EINVAL = 28,
|
#define EINVAL 28
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Input/output error. Some physical input or output error has occurred.
|
* Input/output error. Some physical input or output error has occurred.
|
||||||
* This error may be reported on a subsequent operation on the same
|
* This error may be reported on a subsequent operation on the same
|
||||||
* file descriptor. Any other error-causing operation on the same file
|
* file descriptor. Any other error-causing operation on the same file
|
||||||
* descriptor may cause the [EIO] error indication to be lost.
|
* descriptor may cause the [EIO] error indication to be lost.
|
||||||
*/
|
*/
|
||||||
EIO = 29,
|
#define EIO 29
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Socket is connected. The specified socket is already connected.
|
* Socket is connected. The specified socket is already connected.
|
||||||
*/
|
*/
|
||||||
EISCONN = 30,
|
#define EISCONN 30
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is a directory. An attempt was made to open a directory with write
|
* Is a directory. An attempt was made to open a directory with write
|
||||||
* mode specified.
|
* mode specified.
|
||||||
*/
|
*/
|
||||||
EISDIR = 31,
|
#define EISDIR 31
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Symbolic link loop. A loop exists in symbolic links encountered
|
* Symbolic link loop. A loop exists in symbolic links encountered
|
||||||
* during pathname resolution. This error may also be returned if
|
* during pathname resolution. This error may also be returned if
|
||||||
* more than {SYMLOOP_MAX} symbolic links are encountered during
|
* more than {SYMLOOP_MAX} symbolic links are encountered during
|
||||||
* pathname resolution.
|
* pathname resolution.
|
||||||
*/
|
*/
|
||||||
ELOOP = 32,
|
#define ELOOP 32
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* File descriptor value too large or too many open streams. An
|
* File descriptor value too large or too many open streams. An
|
||||||
* attempt was made to open a file descriptor with a value greater
|
* attempt was made to open a file descriptor with a value greater
|
||||||
* than or equal to {OPEN_MAX}, or an attempt was made to open more
|
* than or equal to {OPEN_MAX}, or an attempt was made to open more
|
||||||
* than the maximum number of streams allowed in the process.
|
* than the maximum number of streams allowed in the process.
|
||||||
*/
|
*/
|
||||||
EMFILE = 33,
|
#define EMFILE 33
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Too many links. An attempt was made to have the link count of a
|
* Too many links. An attempt was made to have the link count of a
|
||||||
* single file exceed {LINK_MAX}.
|
* single file exceed {LINK_MAX}.
|
||||||
*/
|
*/
|
||||||
EMLINK = 34,
|
#define EMLINK 34
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Message too large. A message sent on a transport provider was
|
* Message too large. A message sent on a transport provider was
|
||||||
* larger than an internal message buffer or some other network limit.
|
* larger than an internal message buffer or some other network limit.
|
||||||
* or:
|
* or:
|
||||||
* Inappropriate message buffer length.
|
* Inappropriate message buffer length.
|
||||||
*/
|
*/
|
||||||
EMSGSIZE = 35,
|
#define EMSGSIZE 35
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reserved.
|
* Reserved.
|
||||||
*/
|
*/
|
||||||
EMULTIHOP = 36,
|
#define EMULTIHOP 36
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Filename too long. The length of a pathname exceeds {PATH_MAX} and
|
* Filename too long. The length of a pathname exceeds {PATH_MAX} and
|
||||||
* the implementation considers this to be an error, or a pathname
|
* the implementation considers this to be an error, or a pathname
|
||||||
* component is longer than {NAME_MAX}. This error may also occur
|
* component is longer than {NAME_MAX}. This error may also occur
|
||||||
@ -291,267 +290,267 @@ typedef enum
|
|||||||
* symbolic link during pathname resolution, results in a pathname
|
* symbolic link during pathname resolution, results in a pathname
|
||||||
* string the size of which exceeds {PATH_MAX}.
|
* string the size of which exceeds {PATH_MAX}.
|
||||||
*/
|
*/
|
||||||
ENAMETOOLONG = 37,
|
#define ENAMETOOLONG 37
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Network is down. The local network interface used to reach the
|
* Network is down. The local network interface used to reach the
|
||||||
* destination is down.
|
* destination is down.
|
||||||
*/
|
*/
|
||||||
ENETDOWN = 38,
|
#define ENETDOWN 38
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The connection was aborted by the network.
|
* The connection was aborted by the network.
|
||||||
*/
|
*/
|
||||||
ENETRESET = 39,
|
#define ENETRESET 39
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Network unreachable. No route to the network is present.
|
* Network unreachable. No route to the network is present.
|
||||||
*/
|
*/
|
||||||
ENETUNREACH = 40,
|
#define ENETUNREACH 40
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Too many files open in system. Too many files are currently open
|
* Too many files open in system. Too many files are currently open
|
||||||
* in the system. The system has reached its predefined limit for
|
* in the system. The system has reached its predefined limit for
|
||||||
* simultaneously open files and temporarily cannot accept requests
|
* simultaneously open files and temporarily cannot accept requests
|
||||||
* to open another one.
|
* to open another one.
|
||||||
*/
|
*/
|
||||||
ENFILE = 41,
|
#define ENFILE 41
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* No buffer space available. Insufficient buffer resources were
|
* No buffer space available. Insufficient buffer resources were
|
||||||
* available in the system to perform the socket operation.
|
* available in the system to perform the socket operation.
|
||||||
*/
|
*/
|
||||||
ENOBUFS = 42,
|
#define ENOBUFS 42
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* No message available. No message is available on the STREAM head
|
* No message available. No message is available on the STREAM head
|
||||||
* read queue.
|
* read queue.
|
||||||
*/
|
*/
|
||||||
ENODATA = 43,
|
#define ENODATA 43
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* No such device. An attempt was made to apply an inappropriate
|
* No such device. An attempt was made to apply an inappropriate
|
||||||
* function to a device; for example, trying to read a write-only
|
* function to a device; for example, trying to read a write-only
|
||||||
* device such as a printer.
|
* device such as a printer.
|
||||||
*/
|
*/
|
||||||
ENODEV = 44,
|
#define ENODEV 44
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* No such file or directory. A component of a specified pathname
|
* No such file or directory. A component of a specified pathname
|
||||||
* does not exist, or the pathname is an empty string.
|
* does not exist, or the pathname is an empty string.
|
||||||
*/
|
*/
|
||||||
ENOENT = 45,
|
#define ENOENT 45
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executable file format error. A request is made to execute a file
|
* Executable file format error. A request is made to execute a file
|
||||||
* that, although it has appropriate privileges, is not in the
|
* that, although it has appropriate privileges, is not in the
|
||||||
* format required by the implementation for executable files.
|
* format required by the implementation for executable files.
|
||||||
*/
|
*/
|
||||||
ENOEXEC = 46,
|
#define ENOEXEC 46
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* No locks available. A system-imposed limit on the number of
|
* No locks available. A system-imposed limit on the number of
|
||||||
* simultaneous file and record locks has been reached and no more
|
* simultaneous file and record locks has been reached and no more
|
||||||
* are currently available.
|
* are currently available.
|
||||||
*/
|
*/
|
||||||
ENOLCK = 47,
|
#define ENOLCK 47
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reserved.
|
* Reserved.
|
||||||
*/
|
*/
|
||||||
ENOLINK = 48,
|
#define ENOLINK 48
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Not enough space. The new process image requires more memory than
|
* Not enough space. The new process image requires more memory than
|
||||||
* is allowed by the hardware or system-imposed memory management
|
* is allowed by the hardware or system-imposed memory management
|
||||||
* constraints.
|
* constraints.
|
||||||
*/
|
*/
|
||||||
ENOMEM = 49,
|
#define ENOMEM 49
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* No message of the desired type. The message queue does not contain
|
* No message of the desired type. The message queue does not contain
|
||||||
* a message of the required type during XSI interprocess communication.
|
* a message of the required type during XSI interprocess communication.
|
||||||
*/
|
*/
|
||||||
ENOMSG = 50,
|
#define ENOMSG 50
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Protocol not available. The protocol option specified to
|
* Protocol not available. The protocol option specified to
|
||||||
* setsockopt() is not supported by the implementation.
|
* setsockopt() is not supported by the implementation.
|
||||||
*/
|
*/
|
||||||
ENOPROTOOPT = 51,
|
#define ENOPROTOOPT 51
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* No space left on a device. During the write() function on a
|
* No space left on a device. During the write() function on a
|
||||||
* regular file or when extending a directory, there is no free
|
* regular file or when extending a directory, there is no free
|
||||||
* space left on the device.
|
* space left on the device.
|
||||||
*/
|
*/
|
||||||
ENOSPC = 52,
|
#define ENOSPC 52
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* No STREAM resources. Insufficient STREAMS memory resources are
|
* No STREAM resources. Insufficient STREAMS memory resources are
|
||||||
* available to perform a STREAMS-related function. This is a
|
* available to perform a STREAMS-related function. This is a
|
||||||
* temporary condition; it may be recovered from if other
|
* temporary condition; it may be recovered from if other
|
||||||
* processes release resources.
|
* processes release resources.
|
||||||
*/
|
*/
|
||||||
ENOSR = 53,
|
#define ENOSR 53
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Not a STREAM. A STREAM function was attempted on a file descriptor
|
* Not a STREAM. A STREAM function was attempted on a file descriptor
|
||||||
* that was not associated with a STREAMS device.
|
* that was not associated with a STREAMS device.
|
||||||
*/
|
*/
|
||||||
ENOSTR = 54,
|
#define ENOSTR 54
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Functionality not supported. An attempt was made to use optional
|
* Functionality not supported. An attempt was made to use optional
|
||||||
* functionality that is not supported in this implementation.
|
* functionality that is not supported in this implementation.
|
||||||
*/
|
*/
|
||||||
ENOSYS = 55,
|
#define ENOSYS 55
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Socket not connected. The socket is not connected.
|
* Socket not connected. The socket is not connected.
|
||||||
*/
|
*/
|
||||||
ENOTCONN = 56,
|
#define ENOTCONN 56
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Not a directory. A component of the specified pathname exists, but
|
* Not a directory. A component of the specified pathname exists, but
|
||||||
* it is not a directory, when a directory was expected; or an
|
* it is not a directory, when a directory was expected; or an
|
||||||
* attempt was made to create a non-directory file, and the specified
|
* attempt was made to create a non-directory file, and the specified
|
||||||
* pathname contains at least one non- \<slash\> character and ends
|
* pathname contains at least one non- \<slash\> character and ends
|
||||||
* with one or more trailing \<slash\> characters.
|
* with one or more trailing \<slash\> characters.
|
||||||
*/
|
*/
|
||||||
ENOTDIR = 57,
|
#define ENOTDIR 57
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Directory not empty. A directory other than an empty directory
|
* Directory not empty. A directory other than an empty directory
|
||||||
* was supplied when an empty directory was expected.
|
* was supplied when an empty directory was expected.
|
||||||
*/
|
*/
|
||||||
ENOTEMPTY = 58,
|
#define ENOTEMPTY 58
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* State not recoverable. The state protected by a robust mutex
|
* State not recoverable. The state protected by a robust mutex
|
||||||
* is not recoverable.
|
* is not recoverable.
|
||||||
*/
|
*/
|
||||||
ENOTRECOVERABLE = 59,
|
#define ENOTRECOVERABLE 59
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Not a socket. The file descriptor does not refer to a socket.
|
* Not a socket. The file descriptor does not refer to a socket.
|
||||||
*/
|
*/
|
||||||
ENOTSOCK = 60,
|
#define ENOTSOCK 60
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Not supported. The implementation does not support the requested
|
* Not supported. The implementation does not support the requested
|
||||||
* feature or value.
|
* feature or value.
|
||||||
*/
|
*/
|
||||||
ENOTSUP = 61,
|
#define ENOTSUP 61
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inappropriate I/O control operation. A control function has been
|
* Inappropriate I/O control operation. A control function has been
|
||||||
* attempted for a file or special file for which the operation
|
* attempted for a file or special file for which the operation
|
||||||
* is inappropriate.
|
* is inappropriate.
|
||||||
*/
|
*/
|
||||||
ENOTTY = 62,
|
#define ENOTTY 62
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* No such device or address. Input or output on a special file
|
* No such device or address. Input or output on a special file
|
||||||
* refers to a device that does not exist, or makes a request
|
* refers to a device that does not exist, or makes a request
|
||||||
* beyond the capabilities of the device. It may also occur when,
|
* beyond the capabilities of the device. It may also occur when,
|
||||||
* for example, a tape drive is not on-line.
|
* for example, a tape drive is not on-line.
|
||||||
*/
|
*/
|
||||||
ENXIO = 63,
|
#define ENXIO 63
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Operation not supported on socket. The type of socket (address
|
* Operation not supported on socket. The type of socket (address
|
||||||
* family or protocol) does not support the requested operation.
|
* family or protocol) does not support the requested operation.
|
||||||
*/
|
*/
|
||||||
EOPNOTSUPP = 64,
|
#define EOPNOTSUPP 64
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Value too large to be stored in data type. An operation was
|
* Value too large to be stored in data type. An operation was
|
||||||
* attempted which would generate a value that is outside the
|
* attempted which would generate a value that is outside the
|
||||||
* range of values that can be represented in the relevant data
|
* range of values that can be represented in the relevant data
|
||||||
* type or that are allowed for a given data item.
|
* type or that are allowed for a given data item.
|
||||||
*/
|
*/
|
||||||
EOVERFLOW = 65,
|
#define EOVERFLOW 65
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Previous owner died. The owner of a robust mutex terminated
|
* Previous owner died. The owner of a robust mutex terminated
|
||||||
* while holding the mutex lock.
|
* while holding the mutex lock.
|
||||||
*/
|
*/
|
||||||
EOWNERDEAD = 66,
|
#define EOWNERDEAD 66
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Operation not permitted. An attempt was made to perform an
|
* Operation not permitted. An attempt was made to perform an
|
||||||
* operation limited to processes with appropriate privileges or
|
* operation limited to processes with appropriate privileges or
|
||||||
* to the owner of a file or other resource.
|
* to the owner of a file or other resource.
|
||||||
*/
|
*/
|
||||||
EPERM = 67,
|
#define EPERM 67
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Broken pipe. A write was attempted on a socket, pipe, or FIFO
|
* Broken pipe. A write was attempted on a socket, pipe, or FIFO
|
||||||
* for which there is no process to read the data.
|
* for which there is no process to read the data.
|
||||||
*/
|
*/
|
||||||
EPIPE = 68,
|
#define EPIPE 68
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Protocol error. Some protocol error occurred. This error is
|
* Protocol error. Some protocol error occurred. This error is
|
||||||
* device-specific, but is generally not related to a
|
* device-specific, but is generally not related to a
|
||||||
* hardware failure.
|
* hardware failure.
|
||||||
*/
|
*/
|
||||||
EPROTO = 69,
|
#define EPROTO 69
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Protocol not supported. The protocol is not supported by the
|
* Protocol not supported. The protocol is not supported by the
|
||||||
* address family, or the protocol is not supported by
|
* address family, or the protocol is not supported by
|
||||||
* the implementation.
|
* the implementation.
|
||||||
*/
|
*/
|
||||||
EPROTONOSUPPORT = 70,
|
#define EPROTONOSUPPORT 70
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Protocol wrong type for socket. The socket type is not
|
* Protocol wrong type for socket. The socket type is not
|
||||||
* supported by the protocol.
|
* supported by the protocol.
|
||||||
*/
|
*/
|
||||||
EPROTOTYPE = 71,
|
#define EPROTOTYPE 71
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Result too large or too small. The result of the function
|
* Result too large or too small. The result of the function
|
||||||
* is too large (overflow) or too small (underflow) to be
|
* is too large (overflow) or too small (underflow) to be
|
||||||
* represented in the available space.
|
* represented in the available space.
|
||||||
*/
|
*/
|
||||||
ERANGE = 72,
|
#define ERANGE 72
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read-only file system. An attempt was made to modify a file
|
* Read-only file system. An attempt was made to modify a file
|
||||||
* or directory on a file system that is read-only.
|
* or directory on a file system that is read-only.
|
||||||
*/
|
*/
|
||||||
EROFS = 73,
|
#define EROFS 73
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invalid seek. An attempt was made to access the file offset
|
* Invalid seek. An attempt was made to access the file offset
|
||||||
* associated with a pipe or FIFO.
|
* associated with a pipe or FIFO.
|
||||||
*/
|
*/
|
||||||
ESPIPE = 74,
|
#define ESPIPE 74
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* No such process. No process can be found corresponding to that
|
* No such process. No process can be found corresponding to that
|
||||||
* specified by the given process ID.
|
* specified by the given process ID.
|
||||||
*/
|
*/
|
||||||
ESRCH = 75,
|
#define ESRCH 75
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reserved.
|
* Reserved.
|
||||||
*/
|
*/
|
||||||
ESTALE = 76,
|
#define ESTALE 76
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* STREAM ioctl() timeout. The timer set for a STREAMS ioctl() call
|
* STREAM ioctl() timeout. The timer set for a STREAMS ioctl() call
|
||||||
* has expired. The cause of this error is device-specific and could
|
* has expired. The cause of this error is device-specific and could
|
||||||
* indicate either a hardware or software failure, or a timeout
|
* indicate either a hardware or software failure, or a timeout
|
||||||
* value that is too short for the specific operation. The status
|
* value that is too short for the specific operation. The status
|
||||||
* of the ioctl() operation is unspecified.
|
* of the ioctl() operation is unspecified.
|
||||||
*/
|
*/
|
||||||
ETIME = 77,
|
#define ETIME 77
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Connection timed out. The connection to a remote machine has
|
* Connection timed out. The connection to a remote machine has
|
||||||
* timed out.
|
* timed out.
|
||||||
* If the connection timed out during execution of the function that
|
* If the connection timed out during execution of the function that
|
||||||
@ -563,43 +562,30 @@ typedef enum
|
|||||||
* Operation timed out. The time limit associated with the operation
|
* Operation timed out. The time limit associated with the operation
|
||||||
* was exceeded before the operation completed.
|
* was exceeded before the operation completed.
|
||||||
*/
|
*/
|
||||||
ETIMEDOUT = 78,
|
#define ETIMEDOUT 78
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Text file busy. An attempt was made to execute a pure-procedure
|
* Text file busy. An attempt was made to execute a pure-procedure
|
||||||
* program that is currently open for writing, or an attempt has
|
* program that is currently open for writing, or an attempt has
|
||||||
* been made to open for writing a pure-procedure program that
|
* been made to open for writing a pure-procedure program that
|
||||||
* is being executed.
|
* is being executed.
|
||||||
*/
|
*/
|
||||||
ETXTBSY = 79,
|
#define ETXTBSY 79
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Operation would block. An operation on a socket marked as
|
* Operation would block. An operation on a socket marked as
|
||||||
* non-blocking has encountered a situation such as no data available
|
* non-blocking has encountered a situation such as no data available
|
||||||
* that otherwise would have caused the function to suspend execution.
|
* that otherwise would have caused the function to suspend execution.
|
||||||
*/
|
*/
|
||||||
EWOULDBLOCK = 80,
|
#define EWOULDBLOCK 80
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Improper link. A link to a file on another file system was attempted.
|
* Improper link. A link to a file on another file system was attempted.
|
||||||
*/
|
*/
|
||||||
EXDEV = 81,
|
#define EXDEV 81
|
||||||
|
|
||||||
__ERRNO_MAX
|
#ifdef __kernel__
|
||||||
} KernelErrors;
|
#define __ERRNO_MAX 82
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C"
|
|
||||||
{
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int *__errno_location(void) __attribute__((const));
|
|
||||||
char *strerror(int errnum);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define errno (*__errno_location())
|
|
||||||
|
|
||||||
#endif // !__FENNIX_API_ERRNO_H__
|
#endif // !__FENNIX_API_ERRNO_H__
|
||||||
|
109
Drivers/include/fcntl.h
Normal file
109
Drivers/include/fcntl.h
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Fennix Kernel.
|
||||||
|
|
||||||
|
Fennix Kernel is free software: you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation, either version 3 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
Fennix Kernel is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __FENNIX_API_FCNTL_H__
|
||||||
|
#define __FENNIX_API_FCNTL_H__
|
||||||
|
|
||||||
|
#ifdef __kernel__
|
||||||
|
#include <types.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* cmd */
|
||||||
|
#define F_DUPFD 0x1
|
||||||
|
#define F_DUPFD_CLOEXEC 0x101
|
||||||
|
#define F_DUPFD_CLOFORK 0x201
|
||||||
|
#define F_GETFD 0x2
|
||||||
|
#define F_SETFD 0x3
|
||||||
|
#define F_GETFL 0x4
|
||||||
|
#define F_SETFL 0x5
|
||||||
|
#define F_GETLK 0x6
|
||||||
|
#define F_SETLK 0x7
|
||||||
|
#define F_SETLKW 0x8
|
||||||
|
#define F_OFD_GETLK 0x9
|
||||||
|
#define F_OFD_SETLK 0xA
|
||||||
|
#define F_OFD_SETLKW 0xB
|
||||||
|
#define F_GETOWN 0xC
|
||||||
|
#define F_GETOWN_EX 0xD
|
||||||
|
#define F_SETOWN 0xE
|
||||||
|
#define F_SETOWN_EX 0xF
|
||||||
|
|
||||||
|
#define FD_CLOEXEC 0x1
|
||||||
|
#define FD_CLOFORK 0x2
|
||||||
|
|
||||||
|
/* l_type */
|
||||||
|
#define F_RDLCK 0x1
|
||||||
|
#define F_UNLCK 0x2
|
||||||
|
#define F_WRLCK 0x3
|
||||||
|
|
||||||
|
/* type */
|
||||||
|
#define F_OWNER_PID 0
|
||||||
|
#define F_OWNER_PGRP 1
|
||||||
|
|
||||||
|
/* oflag */
|
||||||
|
#define O_CLOEXEC 02000000
|
||||||
|
#define O_CLOFORK 04000000
|
||||||
|
#define O_CREAT 0x8
|
||||||
|
#define O_DIRECTORY 0200000
|
||||||
|
#define O_EXCL 0x20
|
||||||
|
#define O_NOCTTY 0x40
|
||||||
|
#define O_NOFOLLOW 0400000
|
||||||
|
#define O_TRUNC 0x400
|
||||||
|
#define O_TTY_INIT 0x800
|
||||||
|
|
||||||
|
#define O_APPEND 0x4
|
||||||
|
#define O_DSYNC 0x10
|
||||||
|
#define O_NONBLOCK 0x80
|
||||||
|
#define O_RSYNC 0x100
|
||||||
|
#define O_SYNC 0x200
|
||||||
|
|
||||||
|
#define O_ACCMODE 0x3
|
||||||
|
|
||||||
|
#define O_EXEC 0x4
|
||||||
|
#define O_RDONLY 0x1
|
||||||
|
#define O_RDWR 0x3
|
||||||
|
#define O_SEARCH 0x10
|
||||||
|
#define O_WRONLY 0x2
|
||||||
|
|
||||||
|
#define AT_FDCWD
|
||||||
|
#define AT_EACCESS
|
||||||
|
#define AT_SYMLINK_NOFOLLOW
|
||||||
|
#define AT_SYMLINK_FOLLOW
|
||||||
|
#define AT_REMOVEDIR
|
||||||
|
|
||||||
|
#define POSIX_FADV_DONTNEED
|
||||||
|
#define POSIX_FADV_NOREUSE
|
||||||
|
#define POSIX_FADV_NORMAL
|
||||||
|
#define POSIX_FADV_RANDOM
|
||||||
|
#define POSIX_FADV_SEQUENTIAL
|
||||||
|
#define POSIX_FADV_WILLNEED
|
||||||
|
|
||||||
|
typedef struct f_owner_ex
|
||||||
|
{
|
||||||
|
int type; /* Discriminator for pid. */
|
||||||
|
pid_t pid; /* Process ID or process group ID. */
|
||||||
|
} f_owner_ex;
|
||||||
|
|
||||||
|
typedef struct flock
|
||||||
|
{
|
||||||
|
short l_type; /* Type of lock; F_RDLCK, F_WRLCK, F_UNLCK. */
|
||||||
|
short l_whence; /* Flag for starting offset. */
|
||||||
|
off_t l_start; /* Relative offset in bytes. */
|
||||||
|
off_t l_len; /* Size; if 0 then until EOF. */
|
||||||
|
pid_t l_pid; /* For a process-owned file lock, ignored on input or the process ID of the owning process on output; for an OFD-owned file lock, zero on input or (pid_t)-1 on output. */
|
||||||
|
} flock;
|
||||||
|
|
||||||
|
#endif // !__FENNIX_API_FCNTL_H__
|
@ -95,16 +95,6 @@
|
|||||||
/** Other: X */
|
/** Other: X */
|
||||||
#define S_IXOTH 0001
|
#define S_IXOTH 0001
|
||||||
|
|
||||||
#define O_RDONLY 00
|
|
||||||
#define O_WRONLY 01
|
|
||||||
#define O_RDWR 02
|
|
||||||
#define O_CREAT 0100
|
|
||||||
#define O_EXCL 0200
|
|
||||||
#define O_TRUNC 01000
|
|
||||||
#define O_APPEND 02000
|
|
||||||
#define O_NOFOLLOW 0400000
|
|
||||||
#define O_CLOEXEC 02000000
|
|
||||||
|
|
||||||
#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
|
#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
|
||||||
#define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR)
|
#define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR)
|
||||||
#define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK)
|
#define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK)
|
||||||
@ -146,10 +136,10 @@ static_assert(sizeof(blkcnt_t) == 8, "blkcnt_t must be 64 bits");
|
|||||||
#else
|
#else
|
||||||
static_assert(sizeof(dev_t) == 4, "dev_t must be 32 bits");
|
static_assert(sizeof(dev_t) == 4, "dev_t must be 32 bits");
|
||||||
static_assert(sizeof(ino_t) == 4, "ino_t must be 32 bits");
|
static_assert(sizeof(ino_t) == 4, "ino_t must be 32 bits");
|
||||||
static_assert(sizeof(mode_t) == 2, "mode_t must be 16 bits");
|
static_assert(sizeof(mode_t) == 4, "mode_t must be 32 bits");
|
||||||
static_assert(sizeof(nlink_t) == 2, "nlink_t must be 16 bits");
|
static_assert(sizeof(nlink_t) == 4, "nlink_t must be 32 bits");
|
||||||
static_assert(sizeof(uid_t) == 2, "uid_t must be 16 bits");
|
static_assert(sizeof(uid_t) == 4, "uid_t must be 32 bits");
|
||||||
static_assert(sizeof(gid_t) == 2, "gid_t must be 16 bits");
|
static_assert(sizeof(gid_t) == 4, "gid_t must be 32 bits");
|
||||||
static_assert(sizeof(off_t) == 4, "off_t must be 32 bits");
|
static_assert(sizeof(off_t) == 4, "off_t must be 32 bits");
|
||||||
static_assert(sizeof(time_t) == 4, "time_t must be 32 bits");
|
static_assert(sizeof(time_t) == 4, "time_t must be 32 bits");
|
||||||
static_assert(sizeof(blksize_t) == 4, "blksize_t must be 32 bits");
|
static_assert(sizeof(blksize_t) == 4, "blksize_t must be 32 bits");
|
||||||
@ -332,11 +322,29 @@ struct InodeOperations
|
|||||||
int (*Stat)(struct Inode *Node, struct kstat *Stat);
|
int (*Stat)(struct Inode *Node, struct kstat *Stat);
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
#define I_FLAG_ROOT 0x1
|
|
||||||
#define I_FLAG_MOUNTPOINT 0x2
|
|
||||||
#define I_FLAG_CACHE_KEEP 0x4
|
|
||||||
|
|
||||||
struct FileSystemInfo;
|
struct FileSystemInfo;
|
||||||
|
|
||||||
|
struct FileSystemDevice
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @brief Inode
|
||||||
|
*
|
||||||
|
* If the device is a block device, this will be NULL.
|
||||||
|
*/
|
||||||
|
struct Inode *node;
|
||||||
|
struct InodeOperations *ops;
|
||||||
|
} inode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Block Device
|
||||||
|
*
|
||||||
|
* If the device is a block device, this will be non-NULL.
|
||||||
|
*/
|
||||||
|
struct BlockDevice *Block;
|
||||||
|
};
|
||||||
|
|
||||||
struct SuperBlockOperations
|
struct SuperBlockOperations
|
||||||
{
|
{
|
||||||
int (*AllocateInode)(struct FileSystemInfo *Info, struct Inode **Result);
|
int (*AllocateInode)(struct FileSystemInfo *Info, struct Inode **Result);
|
||||||
@ -347,8 +355,8 @@ struct SuperBlockOperations
|
|||||||
*
|
*
|
||||||
* Write all pending changes to the disk.
|
* Write all pending changes to the disk.
|
||||||
*
|
*
|
||||||
* @param Info Inode to synchronize. If NULL, synchronize all inodes.
|
* @param Info Inode to synchronize.
|
||||||
* @param Node Inode to synchronize.
|
* @param Node Inode to synchronize. If NULL, synchronize all inodes.
|
||||||
*
|
*
|
||||||
* @return Zero on success, otherwise an error code.
|
* @return Zero on success, otherwise an error code.
|
||||||
*/
|
*/
|
||||||
@ -364,20 +372,62 @@ struct SuperBlockOperations
|
|||||||
* @return Zero on success, otherwise an error code.
|
* @return Zero on success, otherwise an error code.
|
||||||
*/
|
*/
|
||||||
int (*Destroy)(struct FileSystemInfo *Info);
|
int (*Destroy)(struct FileSystemInfo *Info);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Probe the filesystem.
|
||||||
|
*
|
||||||
|
* Check if the filesystem is supported by the driver.
|
||||||
|
*
|
||||||
|
* @param Device Device to probe.
|
||||||
|
*
|
||||||
|
* @return Zero on success, otherwise an error code.
|
||||||
|
*/
|
||||||
|
int (*Probe)(struct FileSystemDevice *Device);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mount the filesystem.
|
||||||
|
*
|
||||||
|
* Mount the filesystem on the given device.
|
||||||
|
*
|
||||||
|
* @param FS Filesystem to mount.
|
||||||
|
* @param Root Pointer to the root inode.
|
||||||
|
* @param Device Device to mount. This pointer will be undefined after the function returns!
|
||||||
|
*
|
||||||
|
* @return Zero on success, otherwise an error code.
|
||||||
|
*/
|
||||||
|
int (*Mount)(struct FileSystemInfo *FS, struct Inode **Root, struct FileSystemDevice *Device);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unmount the filesystem.
|
||||||
|
*
|
||||||
|
* Unmount the filesystem from the given device.
|
||||||
|
*
|
||||||
|
* @param FS Filesystem to unmount.
|
||||||
|
*
|
||||||
|
* @return Zero on success, otherwise an error code.
|
||||||
|
*/
|
||||||
|
int (*Unmount)(struct FileSystemInfo *FS);
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
struct FileSystemInfo
|
struct FileSystemInfo
|
||||||
{
|
{
|
||||||
const char *Name;
|
const char *Name;
|
||||||
const char *RootName;
|
|
||||||
int Flags;
|
int Flags;
|
||||||
|
int Capabilities;
|
||||||
|
|
||||||
struct SuperBlockOperations SuperOps;
|
struct SuperBlockOperations SuperOps;
|
||||||
struct InodeOperations Ops;
|
struct InodeOperations Ops;
|
||||||
|
|
||||||
void *PrivateData;
|
void *PrivateData;
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
#ifndef __kernel__
|
||||||
|
dev_t RegisterMountPoint(FileSystemInfo *fsi, Inode *Root);
|
||||||
|
int UnregisterMountPoint(dev_t Device);
|
||||||
|
|
||||||
dev_t RegisterFileSystem(struct FileSystemInfo *Info, struct Inode *Root);
|
dev_t RegisterFileSystem(struct FileSystemInfo *Info, struct Inode *Root);
|
||||||
int UnregisterFileSystem(dev_t Device);
|
int UnregisterFileSystem(dev_t Device);
|
||||||
|
#endif // !__kernel__
|
||||||
|
|
||||||
#endif // !__FENNIX_API_FILESYSTEM_H__
|
#endif // !__FENNIX_API_FILESYSTEM_H__
|
||||||
|
@ -239,6 +239,8 @@ typedef struct
|
|||||||
};
|
};
|
||||||
} InputReport;
|
} InputReport;
|
||||||
|
|
||||||
|
#ifndef __kernel__
|
||||||
EXTERNC int ReportInputEvent(InputReport *Report);
|
EXTERNC int ReportInputEvent(InputReport *Report);
|
||||||
|
#endif // !__kernel__
|
||||||
|
|
||||||
#endif // !__FENNIX_API_INPUT_H__
|
#endif // !__FENNIX_API_INPUT_H__
|
||||||
|
@ -75,7 +75,7 @@ extern "C"
|
|||||||
: "dN"(Port), "a"(Data));
|
: "dN"(Port), "a"(Data));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint8_t mmioin8(uint64_t Address)
|
static inline uint8_t mmioin8(uintptr_t Address)
|
||||||
{
|
{
|
||||||
__asm__ volatile("" ::
|
__asm__ volatile("" ::
|
||||||
: "memory");
|
: "memory");
|
||||||
@ -85,7 +85,7 @@ extern "C"
|
|||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint16_t mmioin16(uint64_t Address)
|
static inline uint16_t mmioin16(uintptr_t Address)
|
||||||
{
|
{
|
||||||
__asm__ volatile("" ::
|
__asm__ volatile("" ::
|
||||||
: "memory");
|
: "memory");
|
||||||
@ -95,7 +95,7 @@ extern "C"
|
|||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint32_t mmioin32(uint64_t Address)
|
static inline uint32_t mmioin32(uintptr_t Address)
|
||||||
{
|
{
|
||||||
__asm__ volatile("" ::
|
__asm__ volatile("" ::
|
||||||
: "memory");
|
: "memory");
|
||||||
@ -105,17 +105,17 @@ extern "C"
|
|||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint64_t mmioin64(uint64_t Address)
|
static inline uintptr_t mmioin64(uintptr_t Address)
|
||||||
{
|
{
|
||||||
__asm__ volatile("" ::
|
__asm__ volatile("" ::
|
||||||
: "memory");
|
: "memory");
|
||||||
uint64_t Result = *(volatile uint64_t *)Address;
|
uintptr_t Result = *(volatile uintptr_t *)Address;
|
||||||
__asm__ volatile("" ::
|
__asm__ volatile("" ::
|
||||||
: "memory");
|
: "memory");
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void mmioout8(uint64_t Address, uint8_t Data)
|
static inline void mmioout8(uintptr_t Address, uint8_t Data)
|
||||||
{
|
{
|
||||||
__asm__ volatile("" ::
|
__asm__ volatile("" ::
|
||||||
: "memory");
|
: "memory");
|
||||||
@ -124,7 +124,7 @@ extern "C"
|
|||||||
: "memory");
|
: "memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void mmioout16(uint64_t Address, uint16_t Data)
|
static inline void mmioout16(uintptr_t Address, uint16_t Data)
|
||||||
{
|
{
|
||||||
__asm__ volatile("" ::
|
__asm__ volatile("" ::
|
||||||
: "memory");
|
: "memory");
|
||||||
@ -133,7 +133,7 @@ extern "C"
|
|||||||
: "memory");
|
: "memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void mmioout32(uint64_t Address, uint32_t Data)
|
static inline void mmioout32(uintptr_t Address, uint32_t Data)
|
||||||
{
|
{
|
||||||
__asm__ volatile("" ::
|
__asm__ volatile("" ::
|
||||||
: "memory");
|
: "memory");
|
||||||
@ -142,11 +142,11 @@ extern "C"
|
|||||||
: "memory");
|
: "memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void mmioout64(uint64_t Address, uint64_t Data)
|
static inline void mmioout64(uintptr_t Address, uintptr_t Data)
|
||||||
{
|
{
|
||||||
__asm__ volatile("" ::
|
__asm__ volatile("" ::
|
||||||
: "memory");
|
: "memory");
|
||||||
*(volatile uint64_t *)Address = Data;
|
*(volatile uintptr_t *)Address = Data;
|
||||||
__asm__ volatile("" ::
|
__asm__ volatile("" ::
|
||||||
: "memory");
|
: "memory");
|
||||||
}
|
}
|
||||||
@ -175,10 +175,10 @@ extern "C"
|
|||||||
: "memory");
|
: "memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void mmoutq(void *Address, uint64_t Value)
|
static inline void mmoutq(void *Address, uintptr_t Value)
|
||||||
{
|
{
|
||||||
__asm__ volatile("mov %1, %0"
|
__asm__ volatile("mov %1, %0"
|
||||||
: "=m"((*(uint64_t *)(Address)))
|
: "=m"((*(uintptr_t *)(Address)))
|
||||||
: "r"(Value)
|
: "r"(Value)
|
||||||
: "memory");
|
: "memory");
|
||||||
}
|
}
|
||||||
@ -213,12 +213,12 @@ extern "C"
|
|||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint64_t mminq(void *Address)
|
static inline uintptr_t mminq(void *Address)
|
||||||
{
|
{
|
||||||
uint64_t Result;
|
uintptr_t Result;
|
||||||
__asm__ volatile("mov %1, %0"
|
__asm__ volatile("mov %1, %0"
|
||||||
: "=r"(Result)
|
: "=r"(Result)
|
||||||
: "m"((*(uint64_t *)(Address)))
|
: "m"((*(uintptr_t *)(Address)))
|
||||||
: "memory");
|
: "memory");
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
@ -171,11 +171,13 @@ extern "C"
|
|||||||
{
|
{
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef __kernel__
|
||||||
PCIArray *GetPCIDevices(uint16_t Vendors[], uint16_t Devices[]);
|
PCIArray *GetPCIDevices(uint16_t Vendors[], uint16_t Devices[]);
|
||||||
void InitializePCI(PCIDevice *Device);
|
void InitializePCI(PCIDevice *Device);
|
||||||
uint32_t GetBAR(uint8_t Index, PCIDevice *Device);
|
uint32_t GetBAR(uint8_t Index, PCIDevice *Device);
|
||||||
uint8_t iLine(PCIDevice *Device);
|
uint8_t iLine(PCIDevice *Device);
|
||||||
uint8_t iPin(PCIDevice *Device);
|
uint8_t iPin(PCIDevice *Device);
|
||||||
|
#endif // !__kernel__
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -15,13 +15,44 @@
|
|||||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __FENNIX_API_SYSCALLS_LIST_H__
|
#ifndef __FENNIX_API_SYSTEM_CALLS_LIST_H__
|
||||||
#define __FENNIX_API_SYSCALLS_LIST_H__
|
#define __FENNIX_API_SYSTEM_CALLS_LIST_H__
|
||||||
|
|
||||||
|
#if __has_include(<interface/fcntl.h>)
|
||||||
|
#include <interface/fcntl.h>
|
||||||
|
#else
|
||||||
|
#include <fcntl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __fennix__
|
||||||
|
#error "__fennix__ not defined"
|
||||||
|
#endif
|
||||||
|
|
||||||
#pragma region Syscall Wrappers
|
#pragma region Syscall Wrappers
|
||||||
|
|
||||||
#define scarg __UINTPTR_TYPE__
|
#define scarg __UINTPTR_TYPE__
|
||||||
|
|
||||||
|
#ifdef __arm__
|
||||||
|
#ifdef __thumb__
|
||||||
|
#define __thumb_r7
|
||||||
|
#define __arm_call(...)
|
||||||
|
#warning "arm thumb code not implemented"
|
||||||
|
#else /* __thumb__ */
|
||||||
|
#define __thumb_r7 __asm__("r7")
|
||||||
|
#define __arm_call(...) \
|
||||||
|
__asm__ __volatile__("svc 0" \
|
||||||
|
: "=r"(r0) \
|
||||||
|
: __VA_ARGS__ \
|
||||||
|
: "memory")
|
||||||
|
#endif /* __thumb__ */
|
||||||
|
|
||||||
|
#ifdef __thumb2__
|
||||||
|
#define __r7_operand "rI"(r7)
|
||||||
|
#else /* __thumb2__ */
|
||||||
|
#define __r7_operand "r"(r7)
|
||||||
|
#endif /* __thumb2__ */
|
||||||
|
#endif /* __arm__ */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Syscall wrapper with 0 arguments
|
* @brief Syscall wrapper with 0 arguments
|
||||||
*
|
*
|
||||||
@ -33,10 +64,30 @@
|
|||||||
static inline scarg syscall0(scarg syscall)
|
static inline scarg syscall0(scarg syscall)
|
||||||
{
|
{
|
||||||
scarg ret;
|
scarg ret;
|
||||||
|
#if defined(__amd64__)
|
||||||
__asm__ __volatile__("syscall"
|
__asm__ __volatile__("syscall"
|
||||||
: "=a"(ret)
|
: "=a"(ret)
|
||||||
: "a"(syscall)
|
: "a"(syscall)
|
||||||
: "rcx", "r11", "memory");
|
: "rcx", "r11", "memory");
|
||||||
|
#elif defined(__i386__)
|
||||||
|
__asm__ __volatile__("int $0x30"
|
||||||
|
: "=a"(ret)
|
||||||
|
: "a"(syscall)
|
||||||
|
: "memory");
|
||||||
|
#elif defined(__arm__)
|
||||||
|
register scarg r7 __thumb_r7 = syscall;
|
||||||
|
register scarg r0 __asm__("r0");
|
||||||
|
__arm_call(__r7_operand);
|
||||||
|
#elif defined(__aarch64__)
|
||||||
|
register scarg x8 __asm__("x8") = syscall;
|
||||||
|
register scarg x0 __asm__("x0");
|
||||||
|
__asm__ __volatile__("svc 0"
|
||||||
|
: "=r"(x0)
|
||||||
|
: "r"(x8)
|
||||||
|
: "memory", "cc");
|
||||||
|
#else
|
||||||
|
#error "Unsupported architecture"
|
||||||
|
#endif
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,10 +103,30 @@ static inline scarg syscall0(scarg syscall)
|
|||||||
static inline scarg syscall1(scarg syscall, scarg arg1)
|
static inline scarg syscall1(scarg syscall, scarg arg1)
|
||||||
{
|
{
|
||||||
scarg ret;
|
scarg ret;
|
||||||
|
#if defined(__amd64__)
|
||||||
__asm__ __volatile__("syscall"
|
__asm__ __volatile__("syscall"
|
||||||
: "=a"(ret)
|
: "=a"(ret)
|
||||||
: "a"(syscall), "D"(arg1)
|
: "a"(syscall), "D"(arg1)
|
||||||
: "rcx", "r11", "memory");
|
: "rcx", "r11", "memory");
|
||||||
|
#elif defined(__i386__)
|
||||||
|
__asm__ __volatile__("int $0x30"
|
||||||
|
: "=a"(ret)
|
||||||
|
: "a"(syscall), "b"(arg1)
|
||||||
|
: "memory");
|
||||||
|
#elif defined(__arm__)
|
||||||
|
register scarg r7 __thumb_r7 = syscall;
|
||||||
|
register scarg r0 __asm__("r0") = arg1;
|
||||||
|
__arm_call(__r7_operand, "0"(r0));
|
||||||
|
#elif defined(__aarch64__)
|
||||||
|
register scarg x8 __asm__("x8") = syscall;
|
||||||
|
register scarg x0 __asm__("x0") = arg1;
|
||||||
|
__asm__ __volatile__("svc 0"
|
||||||
|
: "=r"(ret)
|
||||||
|
: "r"(x8), "0"(x0)
|
||||||
|
: "memory", "cc");
|
||||||
|
#else
|
||||||
|
#error "Unsupported architecture"
|
||||||
|
#endif
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,10 +143,32 @@ static inline scarg syscall1(scarg syscall, scarg arg1)
|
|||||||
static inline scarg syscall2(scarg syscall, scarg arg1, scarg arg2)
|
static inline scarg syscall2(scarg syscall, scarg arg1, scarg arg2)
|
||||||
{
|
{
|
||||||
scarg ret;
|
scarg ret;
|
||||||
|
#if defined(__amd64__)
|
||||||
__asm__ __volatile__("syscall"
|
__asm__ __volatile__("syscall"
|
||||||
: "=a"(ret)
|
: "=a"(ret)
|
||||||
: "a"(syscall), "D"(arg1), "S"(arg2)
|
: "a"(syscall), "D"(arg1), "S"(arg2)
|
||||||
: "rcx", "r11", "memory");
|
: "rcx", "r11", "memory");
|
||||||
|
#elif defined(__i386__)
|
||||||
|
__asm__ __volatile__("int $0x30"
|
||||||
|
: "=a"(ret)
|
||||||
|
: "a"(syscall), "b"(arg1), "c"(arg2)
|
||||||
|
: "memory");
|
||||||
|
#elif defined(__arm__)
|
||||||
|
register scarg r7 __thumb_r7 = syscall;
|
||||||
|
register scarg r0 __asm__("r0") = arg1;
|
||||||
|
register scarg r1 __asm__("r1") = arg2;
|
||||||
|
__arm_call(__r7_operand, "0"(r0), "r"(r1));
|
||||||
|
#elif defined(__aarch64__)
|
||||||
|
register scarg x8 __asm__("x8") = syscall;
|
||||||
|
register scarg x0 __asm__("x0") = arg1;
|
||||||
|
register scarg x1 __asm__("x1") = arg2;
|
||||||
|
__asm__ __volatile__("svc 0"
|
||||||
|
: "=r"(ret)
|
||||||
|
: "r"(x8), "0"(x0), "r"(x1)
|
||||||
|
: "memory", "cc");
|
||||||
|
#else
|
||||||
|
#error "Unsupported architecture"
|
||||||
|
#endif
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,10 +186,34 @@ static inline scarg syscall2(scarg syscall, scarg arg1, scarg arg2)
|
|||||||
static inline scarg syscall3(scarg syscall, scarg arg1, scarg arg2, scarg arg3)
|
static inline scarg syscall3(scarg syscall, scarg arg1, scarg arg2, scarg arg3)
|
||||||
{
|
{
|
||||||
scarg ret;
|
scarg ret;
|
||||||
|
#if defined(__amd64__)
|
||||||
__asm__ __volatile__("syscall"
|
__asm__ __volatile__("syscall"
|
||||||
: "=a"(ret)
|
: "=a"(ret)
|
||||||
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3)
|
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3)
|
||||||
: "rcx", "r11", "memory");
|
: "rcx", "r11", "memory");
|
||||||
|
#elif defined(__i386__)
|
||||||
|
__asm__ __volatile__("int $0x30"
|
||||||
|
: "=a"(ret)
|
||||||
|
: "a"(syscall), "b"(arg1), "c"(arg2), "d"(arg3)
|
||||||
|
: "memory");
|
||||||
|
#elif defined(__arm__)
|
||||||
|
register scarg r7 __thumb_r7 = syscall;
|
||||||
|
register scarg r0 __asm__("r0") = arg1;
|
||||||
|
register scarg r1 __asm__("r1") = arg2;
|
||||||
|
register scarg r2 __asm__("r2") = arg3;
|
||||||
|
__arm_call(__r7_operand, "0"(r0), "r"(r1), "r"(r2));
|
||||||
|
#elif defined(__aarch64__)
|
||||||
|
register scarg x8 __asm__("x8") = syscall;
|
||||||
|
register scarg x0 __asm__("x0") = arg1;
|
||||||
|
register scarg x1 __asm__("x1") = arg2;
|
||||||
|
register scarg x2 __asm__("x2") = arg3;
|
||||||
|
__asm__ __volatile__("svc 0"
|
||||||
|
: "=r"(ret)
|
||||||
|
: "r"(x8), "0"(x0), "r"(x1), "r"(x2)
|
||||||
|
: "memory", "cc");
|
||||||
|
#else
|
||||||
|
#error "Unsupported architecture"
|
||||||
|
#endif
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,11 +232,37 @@ static inline scarg syscall3(scarg syscall, scarg arg1, scarg arg2, scarg arg3)
|
|||||||
static inline scarg syscall4(scarg syscall, scarg arg1, scarg arg2, scarg arg3, scarg arg4)
|
static inline scarg syscall4(scarg syscall, scarg arg1, scarg arg2, scarg arg3, scarg arg4)
|
||||||
{
|
{
|
||||||
scarg ret;
|
scarg ret;
|
||||||
|
#if defined(__amd64__)
|
||||||
register scarg r10 __asm__("r10") = arg4;
|
register scarg r10 __asm__("r10") = arg4;
|
||||||
__asm__ __volatile__("syscall"
|
__asm__ __volatile__("syscall"
|
||||||
: "=a"(ret)
|
: "=a"(ret)
|
||||||
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10)
|
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10)
|
||||||
: "rcx", "r11", "memory");
|
: "rcx", "r11", "memory");
|
||||||
|
#elif defined(__i386__)
|
||||||
|
__asm__ __volatile__("int $0x30"
|
||||||
|
: "=a"(ret)
|
||||||
|
: "a"(syscall), "b"(arg1), "c"(arg2), "d"(arg3), "S"(arg4)
|
||||||
|
: "memory");
|
||||||
|
#elif defined(__arm__)
|
||||||
|
register scarg r7 __thumb_r7 = syscall;
|
||||||
|
register scarg r0 __asm__("r0") = arg1;
|
||||||
|
register scarg r1 __asm__("r1") = arg2;
|
||||||
|
register scarg r2 __asm__("r2") = arg3;
|
||||||
|
register scarg r3 __asm__("r3") = arg4;
|
||||||
|
__arm_call(__r7_operand, "0"(r0), "r"(r1), "r"(r2), "r"(r3));
|
||||||
|
#elif defined(__aarch64__)
|
||||||
|
register scarg x8 __asm__("x8") = syscall;
|
||||||
|
register scarg x0 __asm__("x0") = arg1;
|
||||||
|
register scarg x1 __asm__("x1") = arg2;
|
||||||
|
register scarg x2 __asm__("x2") = arg3;
|
||||||
|
register scarg x3 __asm__("x3") = arg4;
|
||||||
|
__asm__ __volatile__("svc 0"
|
||||||
|
: "=r"(ret)
|
||||||
|
: "r"(x8), "0"(x0), "r"(x1), "r"(x2), "r"(x3)
|
||||||
|
: "memory", "cc");
|
||||||
|
#else
|
||||||
|
#error "Unsupported architecture"
|
||||||
|
#endif
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,12 +282,40 @@ static inline scarg syscall4(scarg syscall, scarg arg1, scarg arg2, scarg arg3,
|
|||||||
static inline scarg syscall5(scarg syscall, scarg arg1, scarg arg2, scarg arg3, scarg arg4, scarg arg5)
|
static inline scarg syscall5(scarg syscall, scarg arg1, scarg arg2, scarg arg3, scarg arg4, scarg arg5)
|
||||||
{
|
{
|
||||||
scarg ret;
|
scarg ret;
|
||||||
|
#if defined(__amd64__)
|
||||||
register scarg r10 __asm__("r10") = arg4;
|
register scarg r10 __asm__("r10") = arg4;
|
||||||
register scarg r8 __asm__("r8") = arg5;
|
register scarg r8 __asm__("r8") = arg5;
|
||||||
__asm__ __volatile__("syscall"
|
__asm__ __volatile__("syscall"
|
||||||
: "=a"(ret)
|
: "=a"(ret)
|
||||||
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10), "r"(r8)
|
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10), "r"(r8)
|
||||||
: "rcx", "r11", "memory");
|
: "rcx", "r11", "memory");
|
||||||
|
#elif defined(__i386__)
|
||||||
|
__asm__ __volatile__("int $0x30"
|
||||||
|
: "=a"(ret)
|
||||||
|
: "a"(syscall), "b"(arg1), "c"(arg2), "d"(arg3), "S"(arg4), "D"(arg5)
|
||||||
|
: "memory");
|
||||||
|
#elif defined(__arm__)
|
||||||
|
register scarg r7 __thumb_r7 = syscall;
|
||||||
|
register scarg r0 __asm__("r0") = arg1;
|
||||||
|
register scarg r1 __asm__("r1") = arg2;
|
||||||
|
register scarg r2 __asm__("r2") = arg3;
|
||||||
|
register scarg r3 __asm__("r3") = arg4;
|
||||||
|
register scarg r4 __asm__("r4") = arg5;
|
||||||
|
__arm_call(__r7_operand, "0"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4));
|
||||||
|
#elif defined(__aarch64__)
|
||||||
|
register scarg x8 __asm__("x8") = syscall;
|
||||||
|
register scarg x0 __asm__("x0") = arg1;
|
||||||
|
register scarg x1 __asm__("x1") = arg2;
|
||||||
|
register scarg x2 __asm__("x2") = arg3;
|
||||||
|
register scarg x3 __asm__("x3") = arg4;
|
||||||
|
register scarg x4 __asm__("x4") = arg5;
|
||||||
|
__asm__ __volatile__("svc 0"
|
||||||
|
: "=r"(ret)
|
||||||
|
: "r"(x8), "0"(x0), "r"(x1), "r"(x2), "r"(x3), "r"(x4)
|
||||||
|
: "memory", "cc");
|
||||||
|
#else
|
||||||
|
#error "Unsupported architecture"
|
||||||
|
#endif
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -165,6 +336,7 @@ static inline scarg syscall5(scarg syscall, scarg arg1, scarg arg2, scarg arg3,
|
|||||||
static inline scarg syscall6(scarg syscall, scarg arg1, scarg arg2, scarg arg3, scarg arg4, scarg arg5, scarg arg6)
|
static inline scarg syscall6(scarg syscall, scarg arg1, scarg arg2, scarg arg3, scarg arg4, scarg arg5, scarg arg6)
|
||||||
{
|
{
|
||||||
scarg ret;
|
scarg ret;
|
||||||
|
#if defined(__amd64__)
|
||||||
register scarg r10 __asm__("r10") = arg4;
|
register scarg r10 __asm__("r10") = arg4;
|
||||||
register scarg r8 __asm__("r8") = arg5;
|
register scarg r8 __asm__("r8") = arg5;
|
||||||
register scarg r9 __asm__("r9") = arg6;
|
register scarg r9 __asm__("r9") = arg6;
|
||||||
@ -172,6 +344,35 @@ static inline scarg syscall6(scarg syscall, scarg arg1, scarg arg2, scarg arg3,
|
|||||||
: "=a"(ret)
|
: "=a"(ret)
|
||||||
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10), "r"(r8), "r"(r9)
|
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10), "r"(r8), "r"(r9)
|
||||||
: "rcx", "r11", "memory");
|
: "rcx", "r11", "memory");
|
||||||
|
#elif defined(__i386__)
|
||||||
|
__asm__ __volatile__("int $0x30"
|
||||||
|
: "=a"(ret)
|
||||||
|
: "a"(syscall), "b"(arg1), "c"(arg2), "d"(arg3), "S"(arg4), "D"(arg5), "g"(arg6)
|
||||||
|
: "memory");
|
||||||
|
#elif defined(__arm__)
|
||||||
|
register scarg r7 __thumb_r7 = syscall;
|
||||||
|
register scarg r0 __asm__("r0") = arg1;
|
||||||
|
register scarg r1 __asm__("r1") = arg2;
|
||||||
|
register scarg r2 __asm__("r2") = arg3;
|
||||||
|
register scarg r3 __asm__("r3") = arg4;
|
||||||
|
register scarg r4 __asm__("r4") = arg5;
|
||||||
|
register scarg r5 __asm__("r5") = arg6;
|
||||||
|
__arm_call(__r7_operand, "0"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4), "r"(r5));
|
||||||
|
#elif defined(__aarch64__)
|
||||||
|
register scarg x8 __asm__("x8") = syscall;
|
||||||
|
register scarg x0 __asm__("x0") = arg1;
|
||||||
|
register scarg x1 __asm__("x1") = arg2;
|
||||||
|
register scarg x2 __asm__("x2") = arg3;
|
||||||
|
register scarg x3 __asm__("x3") = arg4;
|
||||||
|
register scarg x4 __asm__("x4") = arg5;
|
||||||
|
register scarg x5 __asm__("x5") = arg6;
|
||||||
|
__asm__ __volatile__("svc 0"
|
||||||
|
: "=r"(ret)
|
||||||
|
: "r"(x8), "0"(x0), "r"(x1), "r"(x2), "r"(x3), "r"(x4), "r"(x5)
|
||||||
|
: "memory", "cc");
|
||||||
|
#else
|
||||||
|
#error "Unsupported architecture"
|
||||||
|
#endif
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -202,18 +403,18 @@ typedef enum
|
|||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
__SYS_O_RDONLY = 0x1,
|
__SYS_O_RDONLY = O_RDONLY,
|
||||||
__SYS_O_WRONLY = 0x2,
|
__SYS_O_WRONLY = O_WRONLY,
|
||||||
__SYS_O_RDWR = 0x3,
|
__SYS_O_RDWR = O_RDWR,
|
||||||
__SYS_O_APPEND = 0x4,
|
__SYS_O_APPEND = O_APPEND,
|
||||||
__SYS_O_CREAT = 0x8,
|
__SYS_O_CREAT = O_CREAT,
|
||||||
__SYS_O_DSYNC = 0x10,
|
__SYS_O_DSYNC = O_DSYNC,
|
||||||
__SYS_O_EXCL = 0x20,
|
__SYS_O_EXCL = O_EXCL,
|
||||||
__SYS_O_NOCTTY = 0x40,
|
__SYS_O_NOCTTY = O_NOCTTY,
|
||||||
__SYS_O_NONBLOCK = 0x80,
|
__SYS_O_NONBLOCK = O_NONBLOCK,
|
||||||
__SYS_O_RSYNC = 0x100,
|
__SYS_O_RSYNC = O_RSYNC,
|
||||||
__SYS_O_SYNC = 0x200,
|
__SYS_O_SYNC = O_SYNC,
|
||||||
__SYS_O_TRUNC = 0x400
|
__SYS_O_TRUNC = O_TRUNC
|
||||||
} syscall_open_flags_t;
|
} syscall_open_flags_t;
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
@ -411,6 +612,36 @@ static_assert((int)__SYS_SIG_IGN == (int)___SYS_SIG_IGN, "SIG_IGN values do not
|
|||||||
typedef int __SYS_clockid_t;
|
typedef int __SYS_clockid_t;
|
||||||
typedef unsigned int __SYS_socklen_t;
|
typedef unsigned int __SYS_socklen_t;
|
||||||
|
|
||||||
|
typedef struct FramebufferScreenInfo
|
||||||
|
{
|
||||||
|
__UINT32_TYPE__ Width;
|
||||||
|
__UINT32_TYPE__ Height;
|
||||||
|
__UINT32_TYPE__ Pitch;
|
||||||
|
__UINT32_TYPE__ Bpp;
|
||||||
|
__UINT32_TYPE__ Size;
|
||||||
|
} FramebufferScreenInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get framebuffer screen info
|
||||||
|
*
|
||||||
|
* @code
|
||||||
|
* struct FramebufferScreenInfo info;
|
||||||
|
* int ioctl(fd, FBIOGET_SCREEN_INFO, &info);
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* @param fd File descriptor of the framebuffer device
|
||||||
|
* @param info Pointer to the framebuffer screen info structure
|
||||||
|
*/
|
||||||
|
#define FBIOGET_SCREEN_INFO 0xf0
|
||||||
|
|
||||||
|
struct kutsname
|
||||||
|
{
|
||||||
|
char sysname[65];
|
||||||
|
char release[65];
|
||||||
|
char version[65];
|
||||||
|
char machine[65];
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief List of syscalls
|
* @brief List of syscalls
|
||||||
*
|
*
|
||||||
@ -443,6 +674,8 @@ typedef enum
|
|||||||
*/
|
*/
|
||||||
SYS_API_VERSION = 0,
|
SYS_API_VERSION = 0,
|
||||||
|
|
||||||
|
SYS_DEBUG_REPORT = 1,
|
||||||
|
|
||||||
/* I/O */
|
/* I/O */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -599,6 +832,25 @@ typedef enum
|
|||||||
* - #EINVAL if the request is invalid
|
* - #EINVAL if the request is invalid
|
||||||
*/
|
*/
|
||||||
SYS_IOCTL,
|
SYS_IOCTL,
|
||||||
|
/**
|
||||||
|
* @brief Function control
|
||||||
|
*
|
||||||
|
* @code
|
||||||
|
* int fcntl(int fd, int cmd, void *arg);
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* @details Manipulates the underlying parameters of a device.
|
||||||
|
*
|
||||||
|
* @param fd File descriptor referring to the device
|
||||||
|
* @param cmd Device-specific request code
|
||||||
|
* @param arg Argument for the request
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - #EOK on success
|
||||||
|
* - #EBADF if `fd` is not valid
|
||||||
|
* - #EINVAL if the request is invalid
|
||||||
|
*/
|
||||||
|
SYS_FCNTL,
|
||||||
|
|
||||||
/* File Status */
|
/* File Status */
|
||||||
|
|
||||||
@ -1388,6 +1640,22 @@ typedef enum
|
|||||||
* - #EACCES if permission is denied
|
* - #EACCES if permission is denied
|
||||||
*/
|
*/
|
||||||
SYS_RENAME,
|
SYS_RENAME,
|
||||||
|
/**
|
||||||
|
* @brief Get unix name information
|
||||||
|
*
|
||||||
|
* @code
|
||||||
|
* int uname(struct kutsname *buf);
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* @details Retrieves information about the operating system.
|
||||||
|
*
|
||||||
|
* @param buf Pointer to `kutsname` structure to store information
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - #EOK on success
|
||||||
|
* - #EFAULT if `buf` is outside accessible address space
|
||||||
|
*/
|
||||||
|
SYS_UNAME,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Max number of syscalls
|
* @brief Max number of syscalls
|
||||||
@ -1431,6 +1699,9 @@ typedef enum
|
|||||||
/** @copydoc SYS_IOCTL */
|
/** @copydoc SYS_IOCTL */
|
||||||
#define call_ioctl(fd, request, argp) syscall3(SYS_IOCTL, (scarg)fd, (scarg)request, (scarg)argp)
|
#define call_ioctl(fd, request, argp) syscall3(SYS_IOCTL, (scarg)fd, (scarg)request, (scarg)argp)
|
||||||
|
|
||||||
|
/** @copydoc SYS_FCNTL */
|
||||||
|
#define call_fcntl(fd, cmd, arg) syscall3(SYS_FCNTL, (scarg)fd, (scarg)cmd, (scarg)arg)
|
||||||
|
|
||||||
/* File Status */
|
/* File Status */
|
||||||
|
|
||||||
/** @copydoc SYS_STAT */
|
/** @copydoc SYS_STAT */
|
||||||
@ -1538,7 +1809,7 @@ typedef enum
|
|||||||
/* Time */
|
/* Time */
|
||||||
|
|
||||||
/** @copydoc SYS_TIME */
|
/** @copydoc SYS_TIME */
|
||||||
#define call_time(t) syscall1(SYS_TIME, t)
|
#define call_time(t) syscall1(SYS_TIME, (scarg)t)
|
||||||
|
|
||||||
/** @copydoc SYS_CLOCK_GETTIME */
|
/** @copydoc SYS_CLOCK_GETTIME */
|
||||||
#define call_clock_gettime(clockid, tp) syscall2(SYS_CLOCK_GETTIME, (scarg)clockid, (scarg)tp)
|
#define call_clock_gettime(clockid, tp) syscall2(SYS_CLOCK_GETTIME, (scarg)clockid, (scarg)tp)
|
||||||
@ -1569,4 +1840,7 @@ typedef enum
|
|||||||
/** @copydoc SYS_RENAME */
|
/** @copydoc SYS_RENAME */
|
||||||
#define call_rename(oldpath, newpath) syscall2(SYS_RENAME, (scarg)oldpath, (scarg)newpath)
|
#define call_rename(oldpath, newpath) syscall2(SYS_RENAME, (scarg)oldpath, (scarg)newpath)
|
||||||
|
|
||||||
#endif // !__FENNIX_API_SYSCALLS_LIST_H__
|
/** @copydoc SYS_UNAME */
|
||||||
|
#define call_uname(buf) syscall1(SYS_UNAME, (scarg)buf)
|
||||||
|
|
||||||
|
#endif // !__FENNIX_API_SYSTEM_CALLS_LIST_H__
|
||||||
|
@ -71,7 +71,7 @@ typedef uint32_t uid_t;
|
|||||||
typedef uint32_t gid_t;
|
typedef uint32_t gid_t;
|
||||||
typedef int64_t clock_t;
|
typedef int64_t clock_t;
|
||||||
typedef int32_t pid_t;
|
typedef int32_t pid_t;
|
||||||
#elif defined(__LP32__)
|
#else
|
||||||
typedef int32_t off_t;
|
typedef int32_t off_t;
|
||||||
typedef long long off64_t;
|
typedef long long off64_t;
|
||||||
typedef __INT32_TYPE__ mode_t;
|
typedef __INT32_TYPE__ mode_t;
|
||||||
|
@ -1,35 +0,0 @@
|
|||||||
default:
|
|
||||||
$(error Do not run this Makefile directly!)
|
|
||||||
|
|
||||||
S_SOURCES = $(shell find ./ -type f -name '*.S')
|
|
||||||
C_SOURCES = $(shell find ./ -type f -name '*.c')
|
|
||||||
CXX_SOURCES = $(shell find ./ -type f -name '*.cpp')
|
|
||||||
HEADERS = $(sort $(dir $(wildcard ../../include/*)))
|
|
||||||
OBJ = $(C_SOURCES:.c=.o) $(CXX_SOURCES:.cpp=.o) $(S_SOURCES:.S=.o)
|
|
||||||
STACK_USAGE_OBJ = $(C_SOURCES:.c=.su) $(CXX_SOURCES:.cpp=.su)
|
|
||||||
|
|
||||||
FILENAME = $(notdir $(shell pwd)).drv
|
|
||||||
|
|
||||||
build: $(FILENAME)
|
|
||||||
mv $(FILENAME) $(OUTPUT_DIR)$(FILENAME)
|
|
||||||
|
|
||||||
$(FILENAME): $(OBJ)
|
|
||||||
$(info Linking $@)
|
|
||||||
$(CC) $(DRIVER_LDFLAGS) $(OBJ) $(OUTPUT_DIR)dcrt0.o -L$(OUTPUT_DIR) -lkernel -o $@
|
|
||||||
|
|
||||||
WARNCFLAG = -Wall -Wextra
|
|
||||||
|
|
||||||
%.o: %.c $(HEADERS)
|
|
||||||
$(info Compiling $<)
|
|
||||||
$(CC) $(DRIVER_CFLAGS) $(WARNCFLAG) -std=c17 -c $< -o $@
|
|
||||||
|
|
||||||
%.o: %.cpp $(HEADERS)
|
|
||||||
$(info Compiling $<)
|
|
||||||
$(CXX) $(DRIVER_CFLAGS) $(WARNCFLAG) -std=c++20 -fno-exceptions -fno-rtti -c $< -o $@
|
|
||||||
|
|
||||||
%.o: %.S
|
|
||||||
$(info Compiling $<)
|
|
||||||
$(AS) -o $@ $<
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -f file.map $(OBJ) $(STACK_USAGE_OBJ)
|
|
@ -1,39 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of Fennix Drivers.
|
|
||||||
|
|
||||||
Fennix Drivers is free software: you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU General Public License as
|
|
||||||
published by the Free Software Foundation, either version 3 of
|
|
||||||
the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
Fennix Drivers is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with Fennix Drivers. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __FENNIX_DRIVER_AIP_H__
|
|
||||||
#define __FENNIX_DRIVER_AIP_H__
|
|
||||||
|
|
||||||
#include <types.h>
|
|
||||||
#include <aip.h>
|
|
||||||
#include <regs.h>
|
|
||||||
|
|
||||||
extern uint8_t Device1ID[];
|
|
||||||
extern uint8_t Device2ID[];
|
|
||||||
|
|
||||||
void PS2KbdInterruptHandler(TrapFrame *);
|
|
||||||
int InitializeKeyboard();
|
|
||||||
int FinalizeKeyboard();
|
|
||||||
int DetectPS2Keyboard();
|
|
||||||
|
|
||||||
void PS2MouseInterruptHandler(TrapFrame *);
|
|
||||||
int InitializeMouse();
|
|
||||||
int FinalizeMouse();
|
|
||||||
int DetectPS2Mouse();
|
|
||||||
int DetectUART();
|
|
||||||
|
|
||||||
#endif // !__FENNIX_DRIVER_AIP_H__
|
|
@ -1,235 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of Fennix Drivers.
|
|
||||||
|
|
||||||
Fennix Drivers is free software: you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU General Public License as
|
|
||||||
published by the Free Software Foundation, either version 3 of
|
|
||||||
the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
Fennix Drivers is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with Fennix Drivers. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "aip.h"
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#include <base.h>
|
|
||||||
|
|
||||||
bool IsKeyboard(uint8_t ID)
|
|
||||||
{
|
|
||||||
/* Common keyboard IDs */
|
|
||||||
return ID == 0xAB || ID == 0xAC || ID == 0x5D ||
|
|
||||||
ID == 0x2B || ID == 0x47 || ID == 0x60;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsMouse(uint8_t ID)
|
|
||||||
{
|
|
||||||
/* Common mouse IDs */
|
|
||||||
return ID == 0x00 || ID == 0x03 || ID == 0x04;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *GetPS2DeviceName(uint8_t ID, uint8_t SubID)
|
|
||||||
{
|
|
||||||
switch (ID)
|
|
||||||
{
|
|
||||||
case 0x00:
|
|
||||||
return "Standard PS/2 Mouse";
|
|
||||||
case 0x03:
|
|
||||||
return "Mouse with scroll wheel";
|
|
||||||
case 0x04:
|
|
||||||
return "Mouse 5 buttons";
|
|
||||||
case 0xAB:
|
|
||||||
{
|
|
||||||
switch (SubID)
|
|
||||||
{
|
|
||||||
case 0x83: /* Normal */
|
|
||||||
case 0x41: /* Translated */
|
|
||||||
case 0xC1: /* Normal + Translated */
|
|
||||||
return "Standard PS/2 Keyboard";
|
|
||||||
case 0x84:
|
|
||||||
case 0x54:
|
|
||||||
return "IBM Thinkpad/Spacesaver Keyboard";
|
|
||||||
case 0x85:
|
|
||||||
return "NCD N-97/122-Key Host Connect(ed) Keyboard";
|
|
||||||
case 0x86:
|
|
||||||
return "122-Key Keyboard";
|
|
||||||
case 0x90:
|
|
||||||
return "Japanese \"G\" Keyboard";
|
|
||||||
case 0x91:
|
|
||||||
return "Japanese \"P\" Keyboard";
|
|
||||||
case 0x92:
|
|
||||||
return "Japanese \"A\" Keyboard";
|
|
||||||
default:
|
|
||||||
return "Unknown PS/2 Keyboard";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case 0xAC:
|
|
||||||
{
|
|
||||||
switch (SubID)
|
|
||||||
{
|
|
||||||
case 0xA1:
|
|
||||||
return "NCD Sun Keyboard";
|
|
||||||
default:
|
|
||||||
return "Unknown NCD Sun Keyboard";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case 0x5D:
|
|
||||||
case 0x2B:
|
|
||||||
return "Trust Keyboard";
|
|
||||||
case 0x47:
|
|
||||||
case 0x60:
|
|
||||||
return "NMB SGI Keyboard";
|
|
||||||
default:
|
|
||||||
return "Unknown PS/2 Device";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t Device1ID[2] = {0x00, 0x00};
|
|
||||||
uint8_t Device2ID[2] = {0x00, 0x00};
|
|
||||||
bool DualChannel = false;
|
|
||||||
|
|
||||||
int DriverEntry()
|
|
||||||
{
|
|
||||||
PS2WriteCommand(PS2_CMD_DISABLE_PORT_1);
|
|
||||||
PS2WriteCommand(PS2_CMD_DISABLE_PORT_2);
|
|
||||||
PS2ClearOutputBuffer();
|
|
||||||
|
|
||||||
PS2WriteCommand(PS2_CMD_READ_CONFIG);
|
|
||||||
PS2_CONFIGURATION cfg = {.Raw = PS2ReadData()};
|
|
||||||
|
|
||||||
DualChannel = cfg.Port2Clock;
|
|
||||||
if (DualChannel)
|
|
||||||
KernelLog("Dual channel PS/2 controller detected");
|
|
||||||
cfg.Port1Interrupt = 1;
|
|
||||||
cfg.Port2Interrupt = 1;
|
|
||||||
cfg.Port1Translation = 1;
|
|
||||||
|
|
||||||
PS2WriteCommand(PS2_CMD_WRITE_CONFIG);
|
|
||||||
PS2WriteData(cfg.Raw);
|
|
||||||
|
|
||||||
PS2WriteCommand(PS2_CMD_TEST_CONTROLLER);
|
|
||||||
uint8_t test = PS2ReadData();
|
|
||||||
if (test != PS2_TEST_PASSED)
|
|
||||||
{
|
|
||||||
KernelLog("PS/2 controller self test failed (%#x)", test);
|
|
||||||
return -EFAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
PS2WriteCommand(PS2_CMD_WRITE_CONFIG);
|
|
||||||
PS2WriteData(cfg.Raw);
|
|
||||||
|
|
||||||
// bool port2avail = false;
|
|
||||||
// if (DualChannel)
|
|
||||||
// {
|
|
||||||
// PS2WriteCommand(PS2_CMD_ENABLE_PORT_1);
|
|
||||||
// PS2WriteCommand(PS2_CMD_READ_CONFIG);
|
|
||||||
// cfg.Raw = PS2ReadData();
|
|
||||||
// port2avail = cfg.Port2Clock;
|
|
||||||
// PS2WriteCommand(PS2_CMD_DISABLE_PORT_1);
|
|
||||||
// }
|
|
||||||
|
|
||||||
PS2WriteCommand(PS2_CMD_TEST_PORT_1);
|
|
||||||
test = PS2ReadData();
|
|
||||||
if (test != 0x00)
|
|
||||||
{
|
|
||||||
KernelLog("PS/2 Port 1 self test failed (%#x)", test);
|
|
||||||
return -EFAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (DualChannel)
|
|
||||||
{
|
|
||||||
PS2WriteCommand(PS2_CMD_TEST_PORT_2);
|
|
||||||
test = PS2ReadData();
|
|
||||||
if (test != 0x00)
|
|
||||||
{
|
|
||||||
KernelLog("PS/2 Port 2 self test failed (%#x)", test);
|
|
||||||
return -EFAULT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PS2WriteCommand(PS2_CMD_ENABLE_PORT_1);
|
|
||||||
if (DualChannel)
|
|
||||||
PS2WriteCommand(PS2_CMD_ENABLE_PORT_2);
|
|
||||||
|
|
||||||
int errK = InitializeKeyboard();
|
|
||||||
|
|
||||||
int errM = 0;
|
|
||||||
if (DualChannel)
|
|
||||||
errM = InitializeMouse();
|
|
||||||
|
|
||||||
/** A device may fail, but if the other one works,
|
|
||||||
* we can still use it.
|
|
||||||
*/
|
|
||||||
if (errK != 0 && errM != 0)
|
|
||||||
return -ENODEV;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int DriverFinal()
|
|
||||||
{
|
|
||||||
FinalizeKeyboard();
|
|
||||||
FinalizeMouse();
|
|
||||||
PS2WriteCommand(PS2_CMD_DISABLE_PORT_1);
|
|
||||||
PS2WriteCommand(PS2_CMD_DISABLE_PORT_2);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int DriverPanic()
|
|
||||||
{
|
|
||||||
PS2WriteCommand(PS2_CMD_DISABLE_PORT_1);
|
|
||||||
PS2WriteCommand(PS2_CMD_DISABLE_PORT_2);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void __intStub() {}
|
|
||||||
int DriverProbe()
|
|
||||||
{
|
|
||||||
RegisterInterruptHandler(1, __intStub);
|
|
||||||
RegisterInterruptHandler(12, __intStub);
|
|
||||||
|
|
||||||
int kbd = DetectPS2Keyboard();
|
|
||||||
int mouse = DetectPS2Mouse();
|
|
||||||
int uart = DetectUART();
|
|
||||||
|
|
||||||
UnregisterAllInterruptHandlers(__intStub);
|
|
||||||
|
|
||||||
if (kbd != 0 && mouse != 0 && uart != 0)
|
|
||||||
return -ENODEV;
|
|
||||||
|
|
||||||
if (kbd == 0)
|
|
||||||
{
|
|
||||||
if (!IsKeyboard(Device1ID[0]))
|
|
||||||
{
|
|
||||||
KernelLog("PS/2 Port 1 is not a keyboard");
|
|
||||||
// return -EINVAL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mouse == 0)
|
|
||||||
{
|
|
||||||
if (!IsMouse(Device2ID[0]))
|
|
||||||
{
|
|
||||||
KernelLog("PS/2 Port 2 is not a mouse");
|
|
||||||
// return -EINVAL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
KernelPrint("PS/2 Port 1: %s (0x%X 0x%X)",
|
|
||||||
GetPS2DeviceName(Device1ID[0], Device1ID[1]),
|
|
||||||
Device1ID[0], Device1ID[1]);
|
|
||||||
KernelPrint("PS/2 Port 2: %s (0x%X 0x%X)",
|
|
||||||
GetPS2DeviceName(Device2ID[0], Device2ID[1]),
|
|
||||||
Device2ID[0], Device2ID[1]);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
DriverInfo("aip",
|
|
||||||
"Advanced Integrated Peripheral Driver",
|
|
||||||
"EnderIce2",
|
|
||||||
0, 0, 1,
|
|
||||||
"GPLv3");
|
|
@ -1,244 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of Fennix Drivers.
|
|
||||||
|
|
||||||
Fennix Drivers is free software: you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU General Public License as
|
|
||||||
published by the Free Software Foundation, either version 3 of
|
|
||||||
the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
Fennix Drivers is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with Fennix Drivers. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "aip.h"
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#include <base.h>
|
|
||||||
#include <fs.h>
|
|
||||||
#include <input.h>
|
|
||||||
|
|
||||||
dev_t MouseDevID = -1;
|
|
||||||
bool PacketReady = false;
|
|
||||||
bool FourPackets = false;
|
|
||||||
bool MouseButton45 = false;
|
|
||||||
uint8_t Cycle = 0;
|
|
||||||
PS2_MOUSE_PACKET Packet = {0};
|
|
||||||
|
|
||||||
InputReport mir = {0};
|
|
||||||
void PS2MouseInterruptHandler(TrapFrame *)
|
|
||||||
{
|
|
||||||
uint8_t data = PS2ReadData();
|
|
||||||
if (data == PS2_MOUSE_RESP_ACK ||
|
|
||||||
data == PS2_MOUSE_RESP_RESEND)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!PacketReady)
|
|
||||||
{
|
|
||||||
switch (Cycle)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
{
|
|
||||||
if ((data & 0b00001000 /* Always 1 */) == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
Packet.Base.Raw = data;
|
|
||||||
Cycle++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 1:
|
|
||||||
{
|
|
||||||
Packet.XMovement = data;
|
|
||||||
Cycle++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 2:
|
|
||||||
{
|
|
||||||
Packet.YMovement = data;
|
|
||||||
if (FourPackets)
|
|
||||||
Cycle++;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Cycle = 0;
|
|
||||||
PacketReady = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 3:
|
|
||||||
{
|
|
||||||
Packet.ZMovement.Raw = data;
|
|
||||||
Cycle = 0;
|
|
||||||
PacketReady = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* https://stackoverflow.com/a/3208376/9352057 */
|
|
||||||
#define BYTE_TO_BINARY_PATTERN "%c%c%c%c%c%c%c%c"
|
|
||||||
#define BYTE_TO_BINARY(byte) \
|
|
||||||
((byte) & 0x80 ? '1' : '0'), \
|
|
||||||
((byte) & 0x40 ? '1' : '0'), \
|
|
||||||
((byte) & 0x20 ? '1' : '0'), \
|
|
||||||
((byte) & 0x10 ? '1' : '0'), \
|
|
||||||
((byte) & 0x08 ? '1' : '0'), \
|
|
||||||
((byte) & 0x04 ? '1' : '0'), \
|
|
||||||
((byte) & 0x02 ? '1' : '0'), \
|
|
||||||
((byte) & 0x01 ? '1' : '0')
|
|
||||||
|
|
||||||
DebugLog("PS/2 Mouse Packet: [" BYTE_TO_BINARY_PATTERN ":" BYTE_TO_BINARY_PATTERN ":" BYTE_TO_BINARY_PATTERN ":" BYTE_TO_BINARY_PATTERN "] LB:%d RB:%d MB:%d A1:%d XS:%d YS:%d XO:%d YO:%d | X:%03d Y:%03d | Z:%d B4:%d B5:%d A0:%d A0:%d",
|
|
||||||
BYTE_TO_BINARY(Packet.Base.Raw),
|
|
||||||
BYTE_TO_BINARY(Packet.XMovement),
|
|
||||||
BYTE_TO_BINARY(Packet.YMovement),
|
|
||||||
BYTE_TO_BINARY(Packet.ZMovement.Raw),
|
|
||||||
Packet.Base.LeftButton, Packet.Base.RightButton, Packet.Base.MiddleButton,
|
|
||||||
Packet.Base.Always1,
|
|
||||||
Packet.Base.XSign, Packet.Base.YSign,
|
|
||||||
Packet.Base.XOverflow, Packet.Base.YOverflow,
|
|
||||||
Packet.XMovement, Packet.YMovement,
|
|
||||||
Packet.ZMovement.Z, Packet.ZMovement.Button4, Packet.ZMovement.Button5,
|
|
||||||
Packet.ZMovement.Always0, Packet.ZMovement.Always0_2);
|
|
||||||
|
|
||||||
int X, Y;
|
|
||||||
X = Packet.XMovement - (Packet.Base.XSign ? 256 : 0);
|
|
||||||
Y = Packet.YMovement - (Packet.Base.YSign ? 256 : 0);
|
|
||||||
|
|
||||||
if (Packet.Base.XOverflow)
|
|
||||||
X = 0;
|
|
||||||
|
|
||||||
if (Packet.Base.YOverflow)
|
|
||||||
Y = 0;
|
|
||||||
|
|
||||||
mir.Type = INPUT_TYPE_MOUSE;
|
|
||||||
mir.Device = MouseDevID;
|
|
||||||
mir.Mouse.LeftButton = Packet.Base.LeftButton;
|
|
||||||
mir.Mouse.RightButton = Packet.Base.RightButton;
|
|
||||||
mir.Mouse.MiddleButton = Packet.Base.MiddleButton;
|
|
||||||
mir.Mouse.Button4 = Packet.ZMovement.Button4;
|
|
||||||
mir.Mouse.Button5 = Packet.ZMovement.Button5;
|
|
||||||
mir.Mouse.X = X;
|
|
||||||
mir.Mouse.Y = -Y;
|
|
||||||
mir.Mouse.Z = Packet.ZMovement.Z;
|
|
||||||
ReportInputEvent(&mir);
|
|
||||||
PacketReady = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MouseSampleRate(uint8_t SampleRate)
|
|
||||||
{
|
|
||||||
PS2WriteCommand(PS2_CMD_WRITE_NEXT_BYTE_TO_PS2_PORT_2_INPUT);
|
|
||||||
PS2WriteData(PS2_MOUSE_CMD_SET_SAMPLE_RATE);
|
|
||||||
PS2ReadData();
|
|
||||||
|
|
||||||
PS2WriteCommand(PS2_CMD_WRITE_NEXT_BYTE_TO_PS2_PORT_2_INPUT);
|
|
||||||
PS2WriteData(SampleRate);
|
|
||||||
PS2ReadData();
|
|
||||||
}
|
|
||||||
|
|
||||||
int __fs_ms_Ioctl(struct Inode *, unsigned long, void *)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const struct InodeOperations MouseOps = {
|
|
||||||
.Ioctl = __fs_ms_Ioctl,
|
|
||||||
};
|
|
||||||
|
|
||||||
int InitializeMouse()
|
|
||||||
{
|
|
||||||
PS2WriteData(PS2_CMD_WRITE_NEXT_BYTE_TO_PS2_PORT_2_INPUT);
|
|
||||||
PS2WriteData(PS2_MOUSE_CMD_RESET);
|
|
||||||
uint8_t test = PS2ReadData();
|
|
||||||
if (test != PS2_MOUSE_RESP_TEST_PASSED &&
|
|
||||||
test != PS2_MOUSE_RESP_ACK)
|
|
||||||
{
|
|
||||||
KernelLog("PS/2 mouse reset failed! (%#x)", test);
|
|
||||||
return -EFAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
RegisterInterruptHandler(12, PS2MouseInterruptHandler);
|
|
||||||
|
|
||||||
MouseDevID = RegisterDevice(INPUT_TYPE_MOUSE, &MouseOps);
|
|
||||||
|
|
||||||
PS2WriteCommand(PS2_CMD_WRITE_NEXT_BYTE_TO_PS2_PORT_2_INPUT);
|
|
||||||
PS2WriteData(PS2_MOUSE_CMD_SET_DEFAULTS);
|
|
||||||
PS2ReadData();
|
|
||||||
|
|
||||||
PS2WriteCommand(PS2_CMD_WRITE_NEXT_BYTE_TO_PS2_PORT_2_INPUT);
|
|
||||||
PS2WriteData(PS2_MOUSE_CMD_ENABLE_DATA_REPORTING);
|
|
||||||
|
|
||||||
MouseSampleRate(200);
|
|
||||||
MouseSampleRate(100);
|
|
||||||
MouseSampleRate(80);
|
|
||||||
|
|
||||||
PS2WriteCommand(PS2_CMD_WRITE_NEXT_BYTE_TO_PS2_PORT_2_INPUT);
|
|
||||||
PS2WriteData(PS2_MOUSE_CMD_READ_ID);
|
|
||||||
uint8_t Device2ID = PS2ReadData();
|
|
||||||
KernelLog("PS/2 Mouse ID: %#x", Device2ID);
|
|
||||||
|
|
||||||
MouseSampleRate(200);
|
|
||||||
MouseSampleRate(200);
|
|
||||||
MouseSampleRate(80);
|
|
||||||
|
|
||||||
PS2WriteCommand(PS2_CMD_WRITE_NEXT_BYTE_TO_PS2_PORT_2_INPUT);
|
|
||||||
PS2WriteData(PS2_MOUSE_CMD_READ_ID);
|
|
||||||
Device2ID = PS2ReadData();
|
|
||||||
KernelLog("PS/2 Mouse ID: %#x", Device2ID);
|
|
||||||
|
|
||||||
if (Device2ID >= 3 && Device2ID <= 4)
|
|
||||||
FourPackets = true;
|
|
||||||
if (Device2ID == 4)
|
|
||||||
MouseButton45 = true;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int FinalizeMouse()
|
|
||||||
{
|
|
||||||
PS2WriteCommand(PS2_CMD_WRITE_NEXT_BYTE_TO_PS2_PORT_2_INPUT);
|
|
||||||
PS2WriteData(PS2_MOUSE_CMD_DISABLE_DATA_REPORTING);
|
|
||||||
|
|
||||||
UnregisterDevice(MouseDevID);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int DetectPS2Mouse()
|
|
||||||
{
|
|
||||||
PS2WriteCommand(PS2_CMD_WRITE_NEXT_BYTE_TO_PS2_PORT_2_INPUT);
|
|
||||||
PS2WriteData(PS2_MOUSE_CMD_DISABLE_DATA_REPORTING);
|
|
||||||
if (PS2ACKTimeout() != 0)
|
|
||||||
KernelLog("PS/2 mouse failed to disable data reporting!");
|
|
||||||
|
|
||||||
PS2WriteCommand(PS2_CMD_WRITE_NEXT_BYTE_TO_PS2_PORT_2_INPUT);
|
|
||||||
PS2WriteData(PS2_MOUSE_CMD_READ_ID);
|
|
||||||
if (PS2ACKTimeout() != 0)
|
|
||||||
KernelLog("PS/2 mouse failed to read ID!");
|
|
||||||
|
|
||||||
uint8_t recByte;
|
|
||||||
int timeout = 1000000;
|
|
||||||
while (timeout--)
|
|
||||||
{
|
|
||||||
recByte = PS2ReadData();
|
|
||||||
if (recByte != PS2_ACK)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Device2ID[0] = recByte;
|
|
||||||
|
|
||||||
timeout = 1000000;
|
|
||||||
while (timeout--)
|
|
||||||
{
|
|
||||||
recByte = PS2ReadData();
|
|
||||||
if (recByte != PS2_ACK)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Device2ID[1] = recByte;
|
|
||||||
|
|
||||||
KernelLog("PS2 Mouse Device: 0x%X 0x%X", Device2ID[0], Device2ID[1]);
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,646 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of Fennix Drivers.
|
|
||||||
|
|
||||||
Fennix Drivers is free software: you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU General Public License as
|
|
||||||
published by the Free Software Foundation, either version 3 of
|
|
||||||
the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
Fennix Drivers is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with Fennix Drivers. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "aip.h"
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#include <base.h>
|
|
||||||
#include <fs.h>
|
|
||||||
#include <input.h>
|
|
||||||
#include <io.h>
|
|
||||||
|
|
||||||
#define SERIAL_ENABLE_DLAB 0x80
|
|
||||||
#define SERIAL_BUFFER_EMPTY 0x20
|
|
||||||
|
|
||||||
enum Ports
|
|
||||||
{
|
|
||||||
COM1 = 0x3F8,
|
|
||||||
COM2 = 0x2F8,
|
|
||||||
COM3 = 0x3E8,
|
|
||||||
COM4 = 0x2E8,
|
|
||||||
COM5 = 0x5F8,
|
|
||||||
COM6 = 0x4F8,
|
|
||||||
COM7 = 0x5E8,
|
|
||||||
COM8 = 0x4E8,
|
|
||||||
|
|
||||||
LPT1 = 0x378,
|
|
||||||
LPT2 = 0x278,
|
|
||||||
LPT3 = 0x3BC
|
|
||||||
};
|
|
||||||
|
|
||||||
enum SerialSpeed
|
|
||||||
{
|
|
||||||
RATE_50_HI = 0x09,
|
|
||||||
RATE_50_LO = 0x00,
|
|
||||||
|
|
||||||
RATE_300_HI = 0x01,
|
|
||||||
RATE_300_LO = 0x80,
|
|
||||||
|
|
||||||
RATE_600_HI = 0x00,
|
|
||||||
RATE_600_LO = 0xC0,
|
|
||||||
|
|
||||||
RATE_2400_HI = 0x00,
|
|
||||||
RATE_2400_LO = 0x30,
|
|
||||||
|
|
||||||
RATE_4800_HI = 0x00,
|
|
||||||
RATE_4800_LO = 0x18,
|
|
||||||
|
|
||||||
RATE_9600_HI = 0x00,
|
|
||||||
RATE_9600_LO = 0x0C,
|
|
||||||
|
|
||||||
RATE_19200_HI = 0x00,
|
|
||||||
RATE_19200_LO = 0x06,
|
|
||||||
|
|
||||||
RATE_38400_HI = 0x00,
|
|
||||||
RATE_38400_LO = 0x03,
|
|
||||||
|
|
||||||
RATE_57600_HI = 0x00,
|
|
||||||
RATE_57600_LO = 0x02,
|
|
||||||
|
|
||||||
RATE_115200_HI = 0x00,
|
|
||||||
RATE_115200_LO = 0x01
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
. Table of Registers .
|
|
||||||
/---------------------------------------------------------------------\
|
|
||||||
| Base Address | DLAB | R/W | Abr | Register Name |
|
|
||||||
|---------------------------------------------------------------------|
|
|
||||||
| +0 | =0 | W | - | Transmitter Holding Buffer |
|
|
||||||
| | =0 | R | - | Receiver Buffer |
|
|
||||||
| | =1 | R/W | - | Divisor Latch Low Byte |
|
|
||||||
| +1 | =0 | R/W | IER | Interrupt Enable Register |
|
|
||||||
| | =1 | R/W | - | Divisor Latch High Byte |
|
|
||||||
| +2 | - | R | IIR | Interrupt Identification Register |
|
|
||||||
| | - | W | FCR | FIFO Control Register |
|
|
||||||
| +3 | - | R/W | LCR | Line Control Register |
|
|
||||||
| +4 | - | R/W | MCR | Modem Control Register |
|
|
||||||
| +5 | - | R | LSR | Line Status Register |
|
|
||||||
| +6 | - | R | MSR | Modem Status Register |
|
|
||||||
| +7 | - | R/W | - | Scratch Register |
|
|
||||||
\---------------------------------------------------------------------/
|
|
||||||
|
|
||||||
Source:
|
|
||||||
Interfacing the Serial / RS232 Port V5.0
|
|
||||||
Table 5 : Table of Registers
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** Interrupt Enable Register */
|
|
||||||
typedef union
|
|
||||||
{
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
/* Enable Received Data Available Interrupt */
|
|
||||||
uint8_t InterruptOnReceive : 1;
|
|
||||||
|
|
||||||
/* Enable Transmitter Holding Register Empty Interrupt */
|
|
||||||
uint8_t InterruptOnTransmitter : 1;
|
|
||||||
|
|
||||||
/* Enable Receiver Line Status Interrupt */
|
|
||||||
uint8_t LineStatusInterrupt : 1;
|
|
||||||
|
|
||||||
/* Enable Modem Status Interrupt */
|
|
||||||
uint8_t ModemStatusInterrupt : 1;
|
|
||||||
|
|
||||||
/* Enables Sleep Mode (16750) */
|
|
||||||
uint8_t SleepMode : 1;
|
|
||||||
|
|
||||||
/* Enables Low Power Mode (16750) */
|
|
||||||
uint8_t LowPowerMode : 1;
|
|
||||||
|
|
||||||
/* Reserved */
|
|
||||||
uint8_t __reserved : 2;
|
|
||||||
};
|
|
||||||
uint8_t raw;
|
|
||||||
} IER;
|
|
||||||
|
|
||||||
/** Interrupt Identification Register */
|
|
||||||
typedef union
|
|
||||||
{
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
/* Interrupt pending */
|
|
||||||
uint8_t InterruptPending : 1;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Interrupt Status
|
|
||||||
*
|
|
||||||
* 00b = Modem Status Interrupt
|
|
||||||
* 01b = Transmitter Holding Register Empty Interrupt
|
|
||||||
* 10b = Received Data Available Interrupt
|
|
||||||
* 11b = Receiver Line Status Interrupt
|
|
||||||
*/
|
|
||||||
uint8_t InterruptStatus : 2;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 16550 Time-out Interrupt Pending
|
|
||||||
*
|
|
||||||
* @note Reserved on 8250, 16450
|
|
||||||
*/
|
|
||||||
uint8_t TimeOutIP : 1;
|
|
||||||
|
|
||||||
/** Reserved */
|
|
||||||
uint8_t __reserved : 1;
|
|
||||||
|
|
||||||
/** 64 Byte Fifo Enabled (16750 only) */
|
|
||||||
uint8_t FIFO64 : 1;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enable FIFO
|
|
||||||
*
|
|
||||||
* 00b = No FIFO
|
|
||||||
* 01b = FIFO Enabled but Unusable
|
|
||||||
* 11b = FIFO Enabled
|
|
||||||
*/
|
|
||||||
uint8_t FIFO : 2;
|
|
||||||
};
|
|
||||||
uint8_t raw;
|
|
||||||
} IIR;
|
|
||||||
|
|
||||||
/** First In / First Out Control Register */
|
|
||||||
typedef union
|
|
||||||
{
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
/** Enable FIFO's */
|
|
||||||
uint8_t FIFO : 1;
|
|
||||||
|
|
||||||
/** Clear Receive FIFO */
|
|
||||||
uint8_t ClearRX : 1;
|
|
||||||
|
|
||||||
/** Clear Transmit FIFO */
|
|
||||||
uint8_t ClearTX : 1;
|
|
||||||
|
|
||||||
/** DMA Mode Select.
|
|
||||||
*
|
|
||||||
* Change status of RXRDY & TXRDY pins from mode 1 to mode 2.
|
|
||||||
*/
|
|
||||||
uint8_t DMAMode : 1;
|
|
||||||
|
|
||||||
/** Reserved */
|
|
||||||
uint8_t __reserved : 1;
|
|
||||||
|
|
||||||
/** Enable 64 Byte FIFO (16750 only) */
|
|
||||||
uint8_t FIFO64 : 1;
|
|
||||||
|
|
||||||
/** Interrupt Trigger Level
|
|
||||||
*
|
|
||||||
* 00b = 1 Byte
|
|
||||||
* 01b = 4 Bytes
|
|
||||||
* 10b = 8 Bytes
|
|
||||||
* 11b = 14 Bytes
|
|
||||||
*/
|
|
||||||
uint8_t TriggerLevel : 2;
|
|
||||||
};
|
|
||||||
uint8_t raw;
|
|
||||||
} FCR;
|
|
||||||
|
|
||||||
/** Line Control Register */
|
|
||||||
typedef union
|
|
||||||
{
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
/** Word Length
|
|
||||||
*
|
|
||||||
* 00b = 5 bits
|
|
||||||
* 01b = 6 bits
|
|
||||||
* 10b = 7 bits
|
|
||||||
* 11b = 8 bits
|
|
||||||
*/
|
|
||||||
uint8_t WordLength : 2;
|
|
||||||
|
|
||||||
/** Length of Stop Bit
|
|
||||||
*
|
|
||||||
* 0b = One Stop Bit
|
|
||||||
* 1b = 2 Stop bits for words of length 6,7 or 8 bits or 1.5 Stop Bits for Word lengths of 5 bits.
|
|
||||||
*/
|
|
||||||
uint8_t StopBit : 1;
|
|
||||||
|
|
||||||
/** Parity Select
|
|
||||||
*
|
|
||||||
* 0b = No Parity
|
|
||||||
* 001b = Odd Parity
|
|
||||||
* 011b = Even Parity
|
|
||||||
* 101b = High Parity (Sticky)
|
|
||||||
* 111b = Low Parity (Sticky)
|
|
||||||
*/
|
|
||||||
uint8_t Parity : 3;
|
|
||||||
|
|
||||||
/** Set Break Enable */
|
|
||||||
uint8_t SetBreak : 1;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Divisor Latch Access
|
|
||||||
*
|
|
||||||
* 0b = Access to Receiver buffer, Transmitter buffer & Interrupt Enable Register
|
|
||||||
* 1b = Divisor Latch Access Bit
|
|
||||||
*/
|
|
||||||
uint8_t DLAB : 1;
|
|
||||||
};
|
|
||||||
uint8_t raw;
|
|
||||||
} LCR;
|
|
||||||
|
|
||||||
/** Modem Control Register */
|
|
||||||
typedef union
|
|
||||||
{
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
/** Force Data Terminal Ready */
|
|
||||||
uint8_t DataTerminalReady : 1;
|
|
||||||
|
|
||||||
/** Force Request to Send */
|
|
||||||
uint8_t RequestToSend : 1;
|
|
||||||
|
|
||||||
/** Auxiliary Output 1 */
|
|
||||||
uint8_t Out1 : 1;
|
|
||||||
|
|
||||||
/** Auxiliary Output 2 */
|
|
||||||
uint8_t Out2 : 1;
|
|
||||||
|
|
||||||
/** Loopback Mode */
|
|
||||||
uint8_t Loopback : 1;
|
|
||||||
|
|
||||||
/** Autoflow Control Enabled (16750 only) */
|
|
||||||
uint8_t Autoflow : 1;
|
|
||||||
|
|
||||||
/** Reserved */
|
|
||||||
uint8_t __reserved : 2;
|
|
||||||
};
|
|
||||||
uint8_t raw;
|
|
||||||
} MCR;
|
|
||||||
|
|
||||||
/** Line Status Register */
|
|
||||||
typedef union
|
|
||||||
{
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
/** Data Ready */
|
|
||||||
uint8_t DataReady : 1;
|
|
||||||
|
|
||||||
/** Overrun Error */
|
|
||||||
uint8_t OverrunError : 1;
|
|
||||||
|
|
||||||
/** Parity Error */
|
|
||||||
uint8_t ParityError : 1;
|
|
||||||
|
|
||||||
/** Framing Error */
|
|
||||||
uint8_t FramingError : 1;
|
|
||||||
|
|
||||||
/** Break Interrupt */
|
|
||||||
uint8_t BreakInterrupt : 1;
|
|
||||||
|
|
||||||
/** Empty Transmitter Holding Register */
|
|
||||||
uint8_t EmptyTransmitterHolding : 1;
|
|
||||||
|
|
||||||
/** Empty Data Holding Registers */
|
|
||||||
uint8_t EmptyDataHolding : 1;
|
|
||||||
|
|
||||||
/** Error in Received FIFO */
|
|
||||||
uint8_t ErrorReceivedFIFO : 1;
|
|
||||||
};
|
|
||||||
uint8_t raw;
|
|
||||||
} LSR;
|
|
||||||
|
|
||||||
/** Modem Status Register */
|
|
||||||
typedef union
|
|
||||||
{
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
/** Delta Clear to Send */
|
|
||||||
uint8_t DeltaClearToSend : 1;
|
|
||||||
|
|
||||||
/** Delta Data Set Ready */
|
|
||||||
uint8_t DeltaDataSetReady : 1;
|
|
||||||
|
|
||||||
/** Trailing Edge Ring Indicator */
|
|
||||||
uint8_t TrailingEdgeRingIndicator : 1;
|
|
||||||
|
|
||||||
/** Delta Data Carrier Detect */
|
|
||||||
uint8_t DeltaDataCarrierDetect : 1;
|
|
||||||
|
|
||||||
/** Clear To Send */
|
|
||||||
uint8_t ClearToSend : 1;
|
|
||||||
|
|
||||||
/** Data Set Ready */
|
|
||||||
uint8_t DataSetReady : 1;
|
|
||||||
|
|
||||||
/** Ring Indicator */
|
|
||||||
uint8_t RingIndicator : 1;
|
|
||||||
|
|
||||||
/** Carrier Detect */
|
|
||||||
uint8_t CarrierDetect : 1;
|
|
||||||
};
|
|
||||||
uint8_t raw;
|
|
||||||
} MSR;
|
|
||||||
|
|
||||||
union UARTs
|
|
||||||
{
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
uint8_t com1 : 1;
|
|
||||||
uint8_t com2 : 1;
|
|
||||||
uint8_t com3 : 1;
|
|
||||||
uint8_t com4 : 1;
|
|
||||||
uint8_t com5 : 1;
|
|
||||||
uint8_t com6 : 1;
|
|
||||||
uint8_t com7 : 1;
|
|
||||||
uint8_t com8 : 1;
|
|
||||||
|
|
||||||
uint8_t lpt1 : 1;
|
|
||||||
uint8_t lpt2 : 1;
|
|
||||||
uint8_t lpt3 : 1;
|
|
||||||
|
|
||||||
uint8_t __reserved : 5;
|
|
||||||
};
|
|
||||||
uint16_t raw;
|
|
||||||
} uart;
|
|
||||||
|
|
||||||
bool IsDataReady(uint16_t Port)
|
|
||||||
{
|
|
||||||
LSR lsr;
|
|
||||||
lsr.raw = inb(Port + 5);
|
|
||||||
return lsr.DataReady;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsTransmitEmpty(uint16_t Port)
|
|
||||||
{
|
|
||||||
LSR lsr;
|
|
||||||
lsr.raw = inb(Port + 5);
|
|
||||||
return lsr.EmptyTransmitterHolding;
|
|
||||||
}
|
|
||||||
|
|
||||||
char ReadSerial(uint16_t Port)
|
|
||||||
{
|
|
||||||
while (!IsDataReady(Port))
|
|
||||||
Yield();
|
|
||||||
return inb(Port);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WriteSerial(uint16_t Port, char Character)
|
|
||||||
{
|
|
||||||
while (!IsTransmitEmpty(Port))
|
|
||||||
Yield();
|
|
||||||
outb(Port, Character);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ReportSerialReceived(uint8_t Data)
|
|
||||||
{
|
|
||||||
DebugLog("%c", Data);
|
|
||||||
}
|
|
||||||
|
|
||||||
void UartCOM24(TrapFrame *)
|
|
||||||
{
|
|
||||||
LSR lsr2, lsr4;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
lsr2.raw = inb(COM2 + 5);
|
|
||||||
if (lsr2.DataReady)
|
|
||||||
ReportSerialReceived(inb(COM2));
|
|
||||||
lsr4.raw = inb(COM4 + 5);
|
|
||||||
if (lsr4.DataReady)
|
|
||||||
ReportSerialReceived(inb(COM4));
|
|
||||||
} while (lsr2.DataReady || lsr4.DataReady);
|
|
||||||
}
|
|
||||||
|
|
||||||
void UartCOM13(TrapFrame *)
|
|
||||||
{
|
|
||||||
LSR lsr1, lsr3;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
lsr1.raw = inb(COM1 + 5);
|
|
||||||
if (lsr1.DataReady)
|
|
||||||
ReportSerialReceived(inb(COM1));
|
|
||||||
lsr3.raw = inb(COM3 + 5);
|
|
||||||
if (lsr3.DataReady)
|
|
||||||
ReportSerialReceived(inb(COM3));
|
|
||||||
} while (lsr1.DataReady || lsr3.DataReady);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool InitializePort(uint16_t Port)
|
|
||||||
{
|
|
||||||
ECS;
|
|
||||||
LCR lcr = {0};
|
|
||||||
IER ier = {0};
|
|
||||||
FCR fcr = {0};
|
|
||||||
MCR mcr = {0};
|
|
||||||
|
|
||||||
outb(Port + 3, lcr.raw);
|
|
||||||
outb(Port + 1, ier.raw);
|
|
||||||
|
|
||||||
lcr.DLAB = 1;
|
|
||||||
outb(Port + 3, lcr.raw);
|
|
||||||
|
|
||||||
outb(Port + 0, RATE_115200_LO);
|
|
||||||
outb(Port + 1, RATE_115200_HI);
|
|
||||||
|
|
||||||
lcr.DLAB = 0;
|
|
||||||
lcr.WordLength = 0b11;
|
|
||||||
outb(Port + 3, lcr.raw);
|
|
||||||
|
|
||||||
fcr.FIFO = 1;
|
|
||||||
fcr.ClearRX = 1;
|
|
||||||
fcr.ClearTX = 1;
|
|
||||||
fcr.TriggerLevel = 0b11;
|
|
||||||
outb(Port + 2, fcr.raw);
|
|
||||||
|
|
||||||
mcr.DataTerminalReady = 1;
|
|
||||||
mcr.RequestToSend = 1;
|
|
||||||
mcr.Out2 = 1;
|
|
||||||
mcr.Loopback = 1;
|
|
||||||
outb(Port + 4, mcr.raw);
|
|
||||||
|
|
||||||
/* Test the serial port */
|
|
||||||
outb(Port + 0, 0x48);
|
|
||||||
uint8_t result = inb(Port + 0);
|
|
||||||
if (result != 0x48)
|
|
||||||
{
|
|
||||||
/* FIXME: DETECT BAUD RATE
|
|
||||||
Do multiple test to check if the output is garbage.
|
|
||||||
If so, reduce the baud rate until it works. */
|
|
||||||
|
|
||||||
LCS;
|
|
||||||
KernelPrint("Port %#X test failed!", Port);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set normal operation mode */
|
|
||||||
mcr.DataTerminalReady = 1;
|
|
||||||
mcr.RequestToSend = 1;
|
|
||||||
mcr.Out1 = 1;
|
|
||||||
mcr.Out2 = 1;
|
|
||||||
mcr.Loopback = 0;
|
|
||||||
outb(Port + 4, mcr.raw);
|
|
||||||
|
|
||||||
/* Enable interrupts on receive */
|
|
||||||
ier.InterruptOnReceive = 1;
|
|
||||||
outb(Port + 1, ier.raw);
|
|
||||||
RegisterInterruptHandler(3, UartCOM24);
|
|
||||||
RegisterInterruptHandler(4, UartCOM13);
|
|
||||||
|
|
||||||
LCS;
|
|
||||||
KernelPrint("Port %#X initialized", Port);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
int DetectUART()
|
|
||||||
{
|
|
||||||
uart.com1 = inb(COM1) != 0xFF ? true : false;
|
|
||||||
uart.com2 = inb(COM2) != 0xFF ? true : false;
|
|
||||||
uart.com3 = inb(COM3) != 0xFF ? true : false;
|
|
||||||
uart.com4 = inb(COM4) != 0xFF ? true : false;
|
|
||||||
uart.com5 = inb(COM5) != 0xFF ? true : false;
|
|
||||||
uart.com6 = inb(COM6) != 0xFF ? true : false;
|
|
||||||
uart.com7 = inb(COM7) != 0xFF ? true : false;
|
|
||||||
uart.com8 = inb(COM8) != 0xFF ? true : false;
|
|
||||||
|
|
||||||
uart.lpt1 = inb(LPT1) != 0xFF ? true : false;
|
|
||||||
uart.lpt2 = inb(LPT2) != 0xFF ? true : false;
|
|
||||||
uart.lpt3 = inb(LPT3) != 0xFF ? true : false;
|
|
||||||
|
|
||||||
if (uart.com1 == true)
|
|
||||||
if (InitializePort(COM1) == false)
|
|
||||||
uart.com1 = false;
|
|
||||||
|
|
||||||
if (uart.com2 == true)
|
|
||||||
if (InitializePort(COM2) == false)
|
|
||||||
uart.com1 = false;
|
|
||||||
|
|
||||||
if (uart.com3 == true)
|
|
||||||
if (InitializePort(COM3) == false)
|
|
||||||
uart.com1 = false;
|
|
||||||
|
|
||||||
if (uart.com4 == true)
|
|
||||||
if (InitializePort(COM4) == false)
|
|
||||||
uart.com1 = false;
|
|
||||||
|
|
||||||
if (uart.com5 == true)
|
|
||||||
if (InitializePort(COM5) == false)
|
|
||||||
uart.com1 = false;
|
|
||||||
|
|
||||||
if (uart.com6 == true)
|
|
||||||
if (InitializePort(COM6) == false)
|
|
||||||
uart.com1 = false;
|
|
||||||
|
|
||||||
if (uart.com7 == true)
|
|
||||||
if (InitializePort(COM7) == false)
|
|
||||||
uart.com1 = false;
|
|
||||||
|
|
||||||
if (uart.com8 == true)
|
|
||||||
if (InitializePort(COM8) == false)
|
|
||||||
uart.com1 = false;
|
|
||||||
|
|
||||||
if (uart.lpt1 == true)
|
|
||||||
KernelPrint("LPT1 is present");
|
|
||||||
|
|
||||||
if (uart.lpt2 == true)
|
|
||||||
KernelPrint("LPT2 is present");
|
|
||||||
|
|
||||||
if (uart.lpt3 == true)
|
|
||||||
KernelPrint("LPT3 is present");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// static int once = 0;
|
|
||||||
// static uint8_t com4 = 0xFF;
|
|
||||||
// if (!once++)
|
|
||||||
// com4 = inb(0x2E8);
|
|
||||||
// if (com4 == 0xFF)
|
|
||||||
// CPU::Halt(true);
|
|
||||||
// char UserInputBuffer[256]{'\0'};
|
|
||||||
// int BackSpaceLimit = 0;
|
|
||||||
// while (true)
|
|
||||||
// {
|
|
||||||
// while ((inb(0x2E8 + 5) & 1) == 0)
|
|
||||||
// CPU::Pause();
|
|
||||||
// char key = inb(0x2E8);
|
|
||||||
// // debug("key: %d", key);
|
|
||||||
// if (key == '\x7f') /* Backspace (DEL) */
|
|
||||||
// {
|
|
||||||
// if (BackSpaceLimit <= 0)
|
|
||||||
// continue;
|
|
||||||
// char keyBuf[5] = {'\b', '\x1b', '[', 'K', '\0'};
|
|
||||||
// ExPrint(keyBuf);
|
|
||||||
// backspace(UserInputBuffer);
|
|
||||||
// BackSpaceLimit--;
|
|
||||||
// continue;
|
|
||||||
// }
|
|
||||||
// else if (key == '\x0d') /* Enter (CR) */
|
|
||||||
// {
|
|
||||||
// UserInput(UserInputBuffer);
|
|
||||||
// BackSpaceLimit = 0;
|
|
||||||
// UserInputBuffer[0] = '\0';
|
|
||||||
// continue;
|
|
||||||
// }
|
|
||||||
// else if (key == '\x1b') /* Escape */
|
|
||||||
// {
|
|
||||||
// char tmp[16]{'\0'};
|
|
||||||
// append(tmp, key);
|
|
||||||
// while ((inb(0x2E8 + 5) & 1) == 0)
|
|
||||||
// CPU::Pause();
|
|
||||||
// char key = inb(0x2E8);
|
|
||||||
// append(tmp, key);
|
|
||||||
// if (key == '[')
|
|
||||||
// {
|
|
||||||
// // 27 91
|
|
||||||
// // < 68
|
|
||||||
// // > 67
|
|
||||||
// // down 66
|
|
||||||
// // up 65
|
|
||||||
// while ((inb(0x2E8 + 5) & 1) == 0)
|
|
||||||
// CPU::Pause();
|
|
||||||
// key = inb(0x2E8);
|
|
||||||
// append(tmp, key);
|
|
||||||
// switch (key)
|
|
||||||
// {
|
|
||||||
// case 'A':
|
|
||||||
// key = KEY_D_UP;
|
|
||||||
// break;
|
|
||||||
// case 'B':
|
|
||||||
// key = KEY_D_DOWN;
|
|
||||||
// break;
|
|
||||||
// case 'C':
|
|
||||||
// key = KEY_D_RIGHT;
|
|
||||||
// break;
|
|
||||||
// case 'D':
|
|
||||||
// key = KEY_D_LEFT;
|
|
||||||
// break;
|
|
||||||
// default:
|
|
||||||
// {
|
|
||||||
// for (size_t i = 0; i < strlen(tmp); i++)
|
|
||||||
// {
|
|
||||||
// if ((int)sizeof(UserInputBuffer) <= BackSpaceLimit)
|
|
||||||
// continue;
|
|
||||||
// append(UserInputBuffer, tmp[i]);
|
|
||||||
// BackSpaceLimit++;
|
|
||||||
// char keyBuf[2] = {(char)tmp[i], '\0'};
|
|
||||||
// ExPrint(keyBuf);
|
|
||||||
// }
|
|
||||||
// continue;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// ArrowInput(key);
|
|
||||||
// continue;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if ((int)sizeof(UserInputBuffer) <= BackSpaceLimit)
|
|
||||||
// continue;
|
|
||||||
// append(UserInputBuffer, key);
|
|
||||||
// BackSpaceLimit++;
|
|
||||||
// char keyBuf[2] = {(char)key, '\0'};
|
|
||||||
// ExPrint(keyBuf);
|
|
||||||
// }
|
|
@ -36,7 +36,15 @@ CFLAGS += -pipe -fno-builtin -fPIC
|
|||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
CRT_CFLAGS := -fPIC -fPIE -pie -mno-red-zone -std=c++20 -I$(INCLUDE_DIR)
|
CRT_CFLAGS := -fPIC -fPIE -pie -std=c++20 -I$(INCLUDE_DIR)
|
||||||
|
|
||||||
|
ifeq ($(OSARCH), amd64)
|
||||||
|
CRT_CFLAGS += -mno-red-zone
|
||||||
|
else ifeq ($(OSARCH), i386)
|
||||||
|
CRT_CFLAGS += -mno-red-zone
|
||||||
|
else ifeq ($(OSARCH), aarch64)
|
||||||
|
CRT_CFLAGS +=
|
||||||
|
endif
|
||||||
|
|
||||||
ifeq ($(DEBUG), 1)
|
ifeq ($(DEBUG), 1)
|
||||||
CFLAGS += -DDEBUG -ggdb3 -O0 -fdiagnostics-color=always -fstack-usage
|
CFLAGS += -DDEBUG -ggdb3 -O0 -fdiagnostics-color=always -fstack-usage
|
||||||
|
@ -73,7 +73,11 @@ DefineFunction(void, KernelPrint, const char *format, ...)
|
|||||||
{
|
{
|
||||||
__builtin_va_list args;
|
__builtin_va_list args;
|
||||||
__builtin_va_start(args, format);
|
__builtin_va_start(args, format);
|
||||||
|
#if defined(__amd64__) || defined(__i386__)
|
||||||
__KernelPrint(DriverID, (long)format, (long)args);
|
__KernelPrint(DriverID, (long)format, (long)args);
|
||||||
|
#elif defined(__aarch64__)
|
||||||
|
__KernelPrint(DriverID, (long)format, (long)__builtin_va_arg(args, void *));
|
||||||
|
#endif
|
||||||
__builtin_va_end(args);
|
__builtin_va_end(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,7 +85,11 @@ DefineFunction(void, KernelLog, const char *format, ...)
|
|||||||
{
|
{
|
||||||
__builtin_va_list args;
|
__builtin_va_list args;
|
||||||
__builtin_va_start(args, format);
|
__builtin_va_start(args, format);
|
||||||
|
#if defined(__amd64__) || defined(__i386__)
|
||||||
__KernelLog(DriverID, (long)format, (long)args);
|
__KernelLog(DriverID, (long)format, (long)args);
|
||||||
|
#elif defined(__aarch64__)
|
||||||
|
__KernelLog(DriverID, (long)format, (long)__builtin_va_arg(args, void *));
|
||||||
|
#endif
|
||||||
__builtin_va_end(args);
|
__builtin_va_end(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,35 +0,0 @@
|
|||||||
default:
|
|
||||||
$(error Do not run this Makefile directly!)
|
|
||||||
|
|
||||||
S_SOURCES = $(shell find ./ -type f -name '*.S')
|
|
||||||
C_SOURCES = $(shell find ./ -type f -name '*.c')
|
|
||||||
CXX_SOURCES = $(shell find ./ -type f -name '*.cpp')
|
|
||||||
HEADERS = $(sort $(dir $(wildcard ../../include/*)))
|
|
||||||
OBJ = $(C_SOURCES:.c=.o) $(CXX_SOURCES:.cpp=.o) $(S_SOURCES:.S=.o)
|
|
||||||
STACK_USAGE_OBJ = $(C_SOURCES:.c=.su) $(CXX_SOURCES:.cpp=.su)
|
|
||||||
|
|
||||||
FILENAME = $(notdir $(shell pwd)).drv
|
|
||||||
|
|
||||||
build: $(FILENAME)
|
|
||||||
mv $(FILENAME) $(OUTPUT_DIR)$(FILENAME)
|
|
||||||
|
|
||||||
$(FILENAME): $(OBJ)
|
|
||||||
$(info Linking $@)
|
|
||||||
$(CC) $(DRIVER_LDFLAGS) $(OBJ) $(OUTPUT_DIR)dcrt0.o -L$(OUTPUT_DIR) -lkernel -o $@
|
|
||||||
|
|
||||||
WARNCFLAG = -Wall -Wextra
|
|
||||||
|
|
||||||
%.o: %.c $(HEADERS)
|
|
||||||
$(info Compiling $<)
|
|
||||||
$(CC) $(DRIVER_CFLAGS) $(WARNCFLAG) -std=c17 -c $< -o $@
|
|
||||||
|
|
||||||
%.o: %.cpp $(HEADERS)
|
|
||||||
$(info Compiling $<)
|
|
||||||
$(CXX) $(DRIVER_CFLAGS) $(WARNCFLAG) -std=c++20 -fno-exceptions -fno-rtti -c $< -o $@
|
|
||||||
|
|
||||||
%.o: %.S
|
|
||||||
$(info Compiling $<)
|
|
||||||
$(AS) -o $@ $<
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -f file.map $(OBJ) $(STACK_USAGE_OBJ)
|
|
@ -1,878 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of Fennix Drivers.
|
|
||||||
|
|
||||||
Fennix Drivers is free software: you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU General Public License as
|
|
||||||
published by the Free Software Foundation, either version 3 of
|
|
||||||
the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
Fennix Drivers is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with Fennix Drivers. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <driver.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <fs.h>
|
|
||||||
#include <input.h>
|
|
||||||
#include <regs.h>
|
|
||||||
#include <base.h>
|
|
||||||
#include <aip.h>
|
|
||||||
#include <io.h>
|
|
||||||
|
|
||||||
enum RPCMessages
|
|
||||||
{
|
|
||||||
MSG_OPEN,
|
|
||||||
MSG_SENDSIZE,
|
|
||||||
MSG_SENDPAYLOAD,
|
|
||||||
MSG_RECVSIZE,
|
|
||||||
MSG_RECVPAYLOAD,
|
|
||||||
MSG_RECVSTATUS,
|
|
||||||
MSG_CLOSE,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum RPCStatus
|
|
||||||
{
|
|
||||||
STATUS_SUCCESS = 0x1,
|
|
||||||
STATUS_DORECV = 0x2,
|
|
||||||
STATUS_CPT = 0x10,
|
|
||||||
STATUS_HB = 0x80,
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
union
|
|
||||||
{
|
|
||||||
uint32_t ax;
|
|
||||||
uint32_t magic;
|
|
||||||
};
|
|
||||||
union
|
|
||||||
{
|
|
||||||
uint32_t bx;
|
|
||||||
size_t size;
|
|
||||||
};
|
|
||||||
union
|
|
||||||
{
|
|
||||||
uint32_t cx;
|
|
||||||
uint16_t command;
|
|
||||||
};
|
|
||||||
union
|
|
||||||
{
|
|
||||||
uint32_t dx;
|
|
||||||
uint16_t port;
|
|
||||||
};
|
|
||||||
uint32_t si;
|
|
||||||
uint32_t di;
|
|
||||||
} VMwareCommand;
|
|
||||||
|
|
||||||
#define VMWARE_MAGIC 0x564D5868
|
|
||||||
|
|
||||||
#define VMWARE_PORT 0x5658
|
|
||||||
#define VMWARE_PORTHB 0x5659
|
|
||||||
|
|
||||||
#define VMWARE_HYPERVISOR_HB 0x00000000
|
|
||||||
#define VMWARE_HYPERVISOR_OUT 0x00000001
|
|
||||||
|
|
||||||
#define CMD_GETVERSION 0xA
|
|
||||||
#define CMD_MESSAGE 0x1E
|
|
||||||
#define CMD_ABSPOINTER_DATA 0x27
|
|
||||||
#define CMD_ABSPOINTER_STATUS 0x28
|
|
||||||
#define CMD_ABSPOINTER_COMMAND 0x29
|
|
||||||
|
|
||||||
#define ABSPOINTER_ENABLE 0x45414552
|
|
||||||
#define ABSPOINTER_RELATIVE 0xF5
|
|
||||||
#define ABSPOINTER_ABSOLUTE 0x53424152
|
|
||||||
|
|
||||||
#define MESSAGE_RPCI 0x49435052
|
|
||||||
#define MESSAGE_TCLO 0x4f4c4354
|
|
||||||
|
|
||||||
#define FLAG_COOKIE 0x80000000
|
|
||||||
|
|
||||||
#define ToMsg(x) ((x) << 16 | CMD_MESSAGE)
|
|
||||||
#define HighWord(x) ((x & 0xFFFF0000) >> 16)
|
|
||||||
|
|
||||||
#define MESSAGE_HB_MSG 0
|
|
||||||
|
|
||||||
#define MESSAGE_OPEN_CHANNEL ToMsg(MSG_OPEN)
|
|
||||||
#define MESSAGE_CLOSE_CHANNEL ToMsg(MSG_CLOSE)
|
|
||||||
|
|
||||||
#define MESSAGE_SEND_SIZE ToMsg(MSG_SENDSIZE)
|
|
||||||
#define MESSAGE_SEND_PAYLOAD ToMsg(MSG_SENDPAYLOAD)
|
|
||||||
|
|
||||||
#define MESSAGE_RECV_SIZE ToMsg(MSG_RECVSIZE)
|
|
||||||
#define MESSAGE_RECV_PAYLOAD ToMsg(MSG_RECVPAYLOAD)
|
|
||||||
#define MESSAGE_RECV_STATUS ToMsg(MSG_RECVSTATUS)
|
|
||||||
|
|
||||||
#define VM_PORT(cmd, in_ebx, isi, idi, \
|
|
||||||
flags, magic, \
|
|
||||||
ax, bx, cx, dx, si, di) \
|
|
||||||
__asm__ __volatile__("movw $0x5658, %%dx\n" \
|
|
||||||
"inl %%dx, %%eax\n" \
|
|
||||||
: "=a"(ax), \
|
|
||||||
"=b"(bx), \
|
|
||||||
"=c"(cx), \
|
|
||||||
"=d"(dx), \
|
|
||||||
"=S"(si), \
|
|
||||||
"=D"(di) \
|
|
||||||
: "a"(magic), \
|
|
||||||
"b"(in_ebx), \
|
|
||||||
"c"(cmd), \
|
|
||||||
"d"(flags), \
|
|
||||||
"S"(isi), \
|
|
||||||
"D"(idi) : "memory")
|
|
||||||
|
|
||||||
#define VM_PORT_HB_OUT(cmd, in_ecx, isi, idi, \
|
|
||||||
flags, magic, bp, \
|
|
||||||
ax, bx, cx, dx, si, di) \
|
|
||||||
__asm__ __volatile__("push %%rbp\n" \
|
|
||||||
"mov %12, %%rbp\n" \
|
|
||||||
"movw $0x5659, %%dx\n" \
|
|
||||||
"rep outsb\n" \
|
|
||||||
"pop %%rbp\n" \
|
|
||||||
: "=a"(ax), \
|
|
||||||
"=b"(bx), \
|
|
||||||
"=c"(cx), \
|
|
||||||
"=d"(dx), \
|
|
||||||
"=S"(si), \
|
|
||||||
"=D"(di) \
|
|
||||||
: "a"(magic), \
|
|
||||||
"b"(cmd), \
|
|
||||||
"c"(in_ecx), \
|
|
||||||
"d"(flags), \
|
|
||||||
"S"(isi), \
|
|
||||||
"D"(idi), \
|
|
||||||
"r"(bp) : "memory", "cc")
|
|
||||||
|
|
||||||
#define VM_PORT_HB_IN(cmd, in_ecx, isi, idi, \
|
|
||||||
flags, magic, bp, \
|
|
||||||
ax, bx, cx, dx, si, di) \
|
|
||||||
__asm__ __volatile__("push %%rbp\n" \
|
|
||||||
"mov %12, %%rbp\n" \
|
|
||||||
"movw $0x5659, %%dx\n" \
|
|
||||||
"rep insb\n" \
|
|
||||||
"pop %%rbp\n" \
|
|
||||||
: "=a"(ax), \
|
|
||||||
"=b"(bx), \
|
|
||||||
"=c"(cx), \
|
|
||||||
"=d"(dx), \
|
|
||||||
"=S"(si), \
|
|
||||||
"=D"(di) \
|
|
||||||
: "a"(magic), \
|
|
||||||
"b"(cmd), \
|
|
||||||
"c"(in_ecx), \
|
|
||||||
"d"(flags), \
|
|
||||||
"S"(isi), \
|
|
||||||
"D"(idi), \
|
|
||||||
"r"(bp) : "memory", "cc")
|
|
||||||
|
|
||||||
/* TODO:
|
|
||||||
- use vmcall or vmmcall instead of "out" and "in" if available
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
int TCLOChannel;
|
|
||||||
uint16_t ChannelID;
|
|
||||||
uint32_t CookieHigh;
|
|
||||||
uint32_t CookieLow;
|
|
||||||
} ToolboxContext;
|
|
||||||
|
|
||||||
dev_t MouseDevID = -1;
|
|
||||||
|
|
||||||
int __strcmp(const char *l, const char *r)
|
|
||||||
{
|
|
||||||
for (; *l == *r && *l; l++, r++)
|
|
||||||
;
|
|
||||||
|
|
||||||
return *(unsigned char *)l - *(unsigned char *)r;
|
|
||||||
}
|
|
||||||
|
|
||||||
void __cpuid(uint32_t Function,
|
|
||||||
uint32_t *eax, uint32_t *ebx,
|
|
||||||
uint32_t *ecx, uint32_t *edx)
|
|
||||||
{
|
|
||||||
asmv("cpuid"
|
|
||||||
: "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx)
|
|
||||||
: "a"(Function));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool __CheckHypervisorBit()
|
|
||||||
{
|
|
||||||
uint32_t eax, ebx, ecx, edx;
|
|
||||||
__cpuid(0x1, &eax, &ebx, &ecx, &edx);
|
|
||||||
if (!(ecx & (1 << 31)))
|
|
||||||
return false; /* Hypervisor not detected */
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool __VMwareBackdoorHypervisors()
|
|
||||||
{
|
|
||||||
const char hv[13] = {0};
|
|
||||||
uint32_t eax, ebx, ecx, edx;
|
|
||||||
__cpuid(0x40000000, &eax, &ebx, &ecx, &edx);
|
|
||||||
|
|
||||||
*(uint32_t *)hv = ebx;
|
|
||||||
*(uint32_t *)(hv + 4) = ecx;
|
|
||||||
*(uint32_t *)(hv + 8) = edx;
|
|
||||||
|
|
||||||
if (__strcmp(hv, "VMwareVMware") != 0 &&
|
|
||||||
__strcmp(hv, "KVMKVMKVM") != 0 &&
|
|
||||||
__strcmp(hv, "TCGTCGTCGTCG") != 0)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsVMwareBackdoorAvailable()
|
|
||||||
{
|
|
||||||
if (!__CheckHypervisorBit())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!__VMwareBackdoorHypervisors())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
union
|
|
||||||
{
|
|
||||||
uint32_t ax;
|
|
||||||
uint32_t magic;
|
|
||||||
};
|
|
||||||
union
|
|
||||||
{
|
|
||||||
uint32_t bx;
|
|
||||||
size_t size;
|
|
||||||
};
|
|
||||||
union
|
|
||||||
{
|
|
||||||
uint32_t cx;
|
|
||||||
uint16_t command;
|
|
||||||
};
|
|
||||||
union
|
|
||||||
{
|
|
||||||
uint32_t dx;
|
|
||||||
uint16_t port;
|
|
||||||
};
|
|
||||||
uint32_t si;
|
|
||||||
uint32_t di;
|
|
||||||
} cmd;
|
|
||||||
|
|
||||||
cmd.si = cmd.di = 0;
|
|
||||||
cmd.bx = ~0x564D5868;
|
|
||||||
cmd.command = 0xA;
|
|
||||||
cmd.magic = 0x564D5868;
|
|
||||||
cmd.port = 0x5658;
|
|
||||||
|
|
||||||
asmv("in %%dx, %0"
|
|
||||||
: "+a"(cmd.ax), "+b"(cmd.bx),
|
|
||||||
"+c"(cmd.cx), "+d"(cmd.dx),
|
|
||||||
"+S"(cmd.si), "+D"(cmd.di));
|
|
||||||
|
|
||||||
if (cmd.bx != 0x564D5868 ||
|
|
||||||
cmd.ax == 0xFFFFFFFF)
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int OpenMessageChannel(ToolboxContext *ctx, uint32_t Protocol)
|
|
||||||
{
|
|
||||||
uintptr_t ax, bx, cx, dx, si = 0, di = 0;
|
|
||||||
|
|
||||||
VM_PORT(MESSAGE_OPEN_CHANNEL,
|
|
||||||
(Protocol | FLAG_COOKIE), si, di,
|
|
||||||
0, VMWARE_MAGIC,
|
|
||||||
ax, bx, cx, dx, si, di);
|
|
||||||
|
|
||||||
if ((HighWord(cx) & STATUS_SUCCESS) == 0)
|
|
||||||
{
|
|
||||||
KernelLog("Failed to open message channel %#lx", Protocol);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
DebugLog("Opened message channel %d (Protocol: %#lx)",
|
|
||||||
HighWord(dx), Protocol);
|
|
||||||
ctx->ChannelID = (uint16_t)HighWord(dx);
|
|
||||||
ctx->CookieHigh = si;
|
|
||||||
ctx->CookieLow = di;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void MessageClose(ToolboxContext *ctx)
|
|
||||||
{
|
|
||||||
uintptr_t ax, bx, cx, dx,
|
|
||||||
si = ctx->CookieHigh,
|
|
||||||
di = ctx->CookieLow;
|
|
||||||
|
|
||||||
VM_PORT(MESSAGE_CLOSE_CHANNEL,
|
|
||||||
0, si, di,
|
|
||||||
ctx->ChannelID << 16,
|
|
||||||
VMWARE_MAGIC,
|
|
||||||
ax, bx, cx, dx, si, di);
|
|
||||||
|
|
||||||
DebugLog("Closed message channel %d", ctx->ChannelID);
|
|
||||||
}
|
|
||||||
|
|
||||||
static uintptr_t MessageSendHB(ToolboxContext *ctx,
|
|
||||||
const char *Message)
|
|
||||||
{
|
|
||||||
uintptr_t ax, bx, cx, dx,
|
|
||||||
si = (uintptr_t)Message,
|
|
||||||
di = ctx->CookieLow,
|
|
||||||
bp = ctx->CookieHigh;
|
|
||||||
|
|
||||||
uint32_t ChannelID = ctx->ChannelID << 16;
|
|
||||||
size_t Size = StringLength(Message);
|
|
||||||
|
|
||||||
VM_PORT_HB_OUT((STATUS_SUCCESS << 16) | MESSAGE_HB_MSG,
|
|
||||||
Size, si, di,
|
|
||||||
VMWARE_HYPERVISOR_HB | ChannelID | VMWARE_HYPERVISOR_OUT,
|
|
||||||
VMWARE_MAGIC, bp,
|
|
||||||
ax, bx, cx, dx, si, di);
|
|
||||||
|
|
||||||
return bx;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uintptr_t MessageSendLB(ToolboxContext *ctx,
|
|
||||||
const char *Message)
|
|
||||||
{
|
|
||||||
uintptr_t ax, bx,
|
|
||||||
cx = STATUS_SUCCESS << 16,
|
|
||||||
dx, si, di;
|
|
||||||
|
|
||||||
size_t Size = StringLength(Message);
|
|
||||||
while (Size &&
|
|
||||||
(HighWord(cx) & STATUS_SUCCESS))
|
|
||||||
{
|
|
||||||
uint32_t TotalBytes = MIN((uint32_t)Size, (uint32_t)4);
|
|
||||||
uint32_t Word = 0;
|
|
||||||
MemoryCopy(&Word, Message, TotalBytes);
|
|
||||||
Message += TotalBytes;
|
|
||||||
|
|
||||||
si = ctx->CookieHigh;
|
|
||||||
di = ctx->CookieLow;
|
|
||||||
|
|
||||||
VM_PORT(MESSAGE_SEND_PAYLOAD,
|
|
||||||
Word, si, di,
|
|
||||||
ctx->ChannelID << 16,
|
|
||||||
VMWARE_MAGIC,
|
|
||||||
ax, bx, cx, dx, si, di);
|
|
||||||
}
|
|
||||||
|
|
||||||
return cx;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uintptr_t MessageReceiveHB(ToolboxContext *ctx,
|
|
||||||
char *Buffer,
|
|
||||||
size_t BufferSize)
|
|
||||||
{
|
|
||||||
uintptr_t ax, bx, cx, dx,
|
|
||||||
si = ctx->CookieHigh,
|
|
||||||
di = (uintptr_t)Buffer,
|
|
||||||
bp = ctx->CookieLow;
|
|
||||||
|
|
||||||
uint32_t ChannelID = ctx->ChannelID << 16;
|
|
||||||
|
|
||||||
VM_PORT_HB_IN((STATUS_SUCCESS << 16) | MESSAGE_HB_MSG,
|
|
||||||
BufferSize, si, di,
|
|
||||||
VMWARE_HYPERVISOR_HB | ChannelID | VMWARE_HYPERVISOR_OUT,
|
|
||||||
VMWARE_MAGIC, bp,
|
|
||||||
ax, bx, cx, dx, si, di);
|
|
||||||
|
|
||||||
return bx;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uintptr_t MessageReceiveLB(ToolboxContext *ctx,
|
|
||||||
char *Buffer,
|
|
||||||
size_t BufferSize)
|
|
||||||
{
|
|
||||||
uintptr_t ax, bx,
|
|
||||||
cx = STATUS_SUCCESS << 16,
|
|
||||||
dx, si, di;
|
|
||||||
|
|
||||||
while (BufferSize)
|
|
||||||
{
|
|
||||||
uint32_t TotalBytes = MIN((uint32_t)BufferSize, (uint32_t)4);
|
|
||||||
|
|
||||||
si = ctx->CookieHigh;
|
|
||||||
di = ctx->CookieLow;
|
|
||||||
|
|
||||||
VM_PORT(MESSAGE_RECV_PAYLOAD,
|
|
||||||
STATUS_SUCCESS, si, di,
|
|
||||||
ctx->ChannelID << 16,
|
|
||||||
VMWARE_MAGIC,
|
|
||||||
ax, bx, cx, dx, si, di);
|
|
||||||
|
|
||||||
if ((HighWord(cx) & STATUS_SUCCESS) == 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
MemoryCopy(Buffer, &bx, TotalBytes);
|
|
||||||
Buffer += TotalBytes;
|
|
||||||
BufferSize -= TotalBytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
return cx;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int MessageSend(ToolboxContext *ctx,
|
|
||||||
const char *Message)
|
|
||||||
{
|
|
||||||
uintptr_t ax, bx, cx, dx, si, di;
|
|
||||||
size_t Size = StringLength(Message);
|
|
||||||
int Retries = 0;
|
|
||||||
|
|
||||||
while (Retries < 2)
|
|
||||||
{
|
|
||||||
Retries++;
|
|
||||||
si = ctx->CookieHigh;
|
|
||||||
di = ctx->CookieLow;
|
|
||||||
|
|
||||||
VM_PORT(MESSAGE_SEND_SIZE,
|
|
||||||
Size, si, di,
|
|
||||||
ctx->ChannelID << 16,
|
|
||||||
VMWARE_MAGIC,
|
|
||||||
ax, bx, cx, dx, si, di);
|
|
||||||
|
|
||||||
if ((HighWord(cx) & STATUS_SUCCESS) == 0)
|
|
||||||
{
|
|
||||||
KernelLog("Failed to send message size for \"%s\": %d",
|
|
||||||
Message, cx);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool HighBand = (HighWord(cx) & STATUS_HB) != 0;
|
|
||||||
if (HighBand)
|
|
||||||
bx = MessageSendHB(ctx, Message);
|
|
||||||
else
|
|
||||||
bx = MessageSendLB(ctx, Message);
|
|
||||||
|
|
||||||
int status = HighWord(bx);
|
|
||||||
|
|
||||||
if ((status & STATUS_SUCCESS) != 0)
|
|
||||||
{
|
|
||||||
DebugLog("Message \"%s\" sent", Message);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else if ((status & STATUS_CPT) == 0)
|
|
||||||
{
|
|
||||||
KernelLog("Checkpoint occurred for message \"%s\"", Message);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
KernelLog("Failed to send message \"%s\": %#lx", Message, bx);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int MessageReceive(ToolboxContext *ctx,
|
|
||||||
char **Buffer,
|
|
||||||
size_t *BufferSize)
|
|
||||||
{
|
|
||||||
uintptr_t ax, bx, cx, dx, si, di;
|
|
||||||
int Retries = 0;
|
|
||||||
|
|
||||||
*Buffer = NULL;
|
|
||||||
*BufferSize = 0;
|
|
||||||
|
|
||||||
char *ReplyBuf = NULL;
|
|
||||||
size_t ReplyBufPages = 0;
|
|
||||||
size_t ReplySize = 0;
|
|
||||||
while (Retries < 2)
|
|
||||||
{
|
|
||||||
Retries++;
|
|
||||||
si = ctx->CookieHigh;
|
|
||||||
di = ctx->CookieLow;
|
|
||||||
|
|
||||||
VM_PORT(MESSAGE_RECV_SIZE,
|
|
||||||
0, si, di,
|
|
||||||
ctx->ChannelID << 16,
|
|
||||||
VMWARE_MAGIC,
|
|
||||||
ax, bx, cx, dx, si, di);
|
|
||||||
|
|
||||||
if ((HighWord(cx) & STATUS_SUCCESS) == 0)
|
|
||||||
{
|
|
||||||
KernelLog("Failed to receive message size: %d", cx);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
else if ((HighWord(cx) & STATUS_DORECV) == 0)
|
|
||||||
{
|
|
||||||
DebugLog("No message to receive");
|
|
||||||
return -EAGAIN;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReplySize = bx;
|
|
||||||
|
|
||||||
if (ReplyBuf != NULL)
|
|
||||||
FreeMemory(ReplyBuf, ReplyBufPages);
|
|
||||||
ReplyBufPages = ReplySize / 0x1000 + 1;
|
|
||||||
ReplyBuf = AllocateMemory(ReplyBufPages);
|
|
||||||
|
|
||||||
bool HighBand = (HighWord(cx) & STATUS_HB) != 0;
|
|
||||||
if (HighBand)
|
|
||||||
bx = MessageReceiveHB(ctx, ReplyBuf, ReplySize);
|
|
||||||
else
|
|
||||||
bx = MessageReceiveLB(ctx, ReplyBuf, ReplySize);
|
|
||||||
|
|
||||||
if ((HighWord(bx) & STATUS_SUCCESS) == 0)
|
|
||||||
{
|
|
||||||
if ((HighWord(bx) & STATUS_CPT) == 0)
|
|
||||||
{
|
|
||||||
KernelLog("Checkpoint occurred for message payload");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
KernelLog("Failed to receive message payload: %d", HighWord(bx));
|
|
||||||
FreeMemory(ReplyBuf, ReplyBufPages);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReplyBuf[ReplySize] = '\0';
|
|
||||||
|
|
||||||
si = ctx->CookieHigh;
|
|
||||||
di = ctx->CookieLow;
|
|
||||||
|
|
||||||
VM_PORT(MESSAGE_RECV_STATUS,
|
|
||||||
STATUS_SUCCESS, si, di,
|
|
||||||
ctx->ChannelID << 16,
|
|
||||||
VMWARE_MAGIC,
|
|
||||||
ax, bx, cx, dx, si, di);
|
|
||||||
|
|
||||||
if ((HighWord(cx) & STATUS_SUCCESS) == 0)
|
|
||||||
{
|
|
||||||
if ((HighWord(cx) & STATUS_CPT) == 0)
|
|
||||||
{
|
|
||||||
KernelLog("Retrying message receive");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
KernelLog("Failed to receive message status: %d", HighWord(cx));
|
|
||||||
FreeMemory(ReplyBuf, ReplyBufPages);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ReplyBuf == NULL)
|
|
||||||
{
|
|
||||||
KernelLog("Failed to receive message");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
*Buffer = ReplyBuf;
|
|
||||||
*BufferSize = ReplySize;
|
|
||||||
DebugLog("Received message \"%s\"", ReplyBuf);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int SendRPCI(ToolboxContext *, const char *Request)
|
|
||||||
{
|
|
||||||
ToolboxContext rpci_ctx = {0};
|
|
||||||
int status = OpenMessageChannel(&rpci_ctx, MESSAGE_RPCI);
|
|
||||||
if (status < 0)
|
|
||||||
{
|
|
||||||
KernelLog("Failed to open RPCI channel: %d", status);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
status = MessageSend(&rpci_ctx, Request);
|
|
||||||
if (status < 0)
|
|
||||||
{
|
|
||||||
KernelLog("Failed to send RPCI request: %d", status);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
MessageClose(&rpci_ctx);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int MsgEqual(const char *haystack, const char *needle)
|
|
||||||
{
|
|
||||||
return strstr(haystack, needle) == haystack;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int DisplayGetSize(ToolboxContext *ctx)
|
|
||||||
{
|
|
||||||
if (ctx->TCLOChannel != -1)
|
|
||||||
MessageClose(ctx);
|
|
||||||
OpenMessageChannel(ctx, MESSAGE_TCLO);
|
|
||||||
|
|
||||||
char EmptyBuffer[256] = {'\0'};
|
|
||||||
MessageSend(ctx, EmptyBuffer);
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
/* FIXME: buf memory leak */
|
|
||||||
char *buf;
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
int status = MessageReceive(ctx, &buf, &len);
|
|
||||||
if (status == -EAGAIN)
|
|
||||||
{
|
|
||||||
Sleep(1000);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else if (status < 0)
|
|
||||||
{
|
|
||||||
KernelLog("Failed to receive message");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
buf[StringLength(buf)] = '\0';
|
|
||||||
if (MsgEqual(buf, "reset"))
|
|
||||||
{
|
|
||||||
if (MessageSend(ctx, "OK ATR toolbox") < 0)
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else if (MsgEqual(buf, "ping"))
|
|
||||||
{
|
|
||||||
if (MessageSend(ctx, "OK ") < 0)
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else if (MsgEqual(buf, "Capabilities_Register"))
|
|
||||||
{
|
|
||||||
SendRPCI(ctx, "tools.capability.resolution_set 1");
|
|
||||||
SendRPCI(ctx, "tools.capability.resolution_server toolbox 1");
|
|
||||||
SendRPCI(ctx, "tools.capability.display_topology_set 1");
|
|
||||||
SendRPCI(ctx, "tools.capability.color_depth_set 1");
|
|
||||||
SendRPCI(ctx, "tools.capability.resolution_min 0 0");
|
|
||||||
SendRPCI(ctx, "tools.capability.unity 1");
|
|
||||||
|
|
||||||
if (MessageSend(ctx, "OK ") < 0)
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else if (MsgEqual(buf, "Resolution_Set"))
|
|
||||||
{
|
|
||||||
DebugLog("%s", buf);
|
|
||||||
if (MessageSend(ctx, "OK ") < 0)
|
|
||||||
return 1;
|
|
||||||
MessageClose(ctx);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (MessageSend(ctx, "ERROR Unknown command") < 0)
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pid_t dst_id = -1;
|
|
||||||
pid_t dst_pid = -1;
|
|
||||||
ToolboxContext *tb_ctx = NULL;
|
|
||||||
void DisplayScaleThread()
|
|
||||||
{
|
|
||||||
/* sizeof ToolboxContext */
|
|
||||||
tb_ctx = AllocateMemory(1);
|
|
||||||
Sleep(2000);
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
if (DisplayGetSize(tb_ctx) != 0)
|
|
||||||
KernelLog("Failed to scale display");
|
|
||||||
Sleep(1000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CommandSend(VMwareCommand *cmd)
|
|
||||||
{
|
|
||||||
cmd->magic = VMWARE_MAGIC;
|
|
||||||
cmd->port = VMWARE_PORT;
|
|
||||||
asm volatile("in %%dx, %0"
|
|
||||||
: "+a"(cmd->ax), "+b"(cmd->bx),
|
|
||||||
"+c"(cmd->cx), "+d"(cmd->dx),
|
|
||||||
"+S"(cmd->si), "+D"(cmd->di));
|
|
||||||
}
|
|
||||||
|
|
||||||
void Absolute()
|
|
||||||
{
|
|
||||||
VMwareCommand cmd = {0};
|
|
||||||
|
|
||||||
/* Enable */
|
|
||||||
cmd.bx = ABSPOINTER_ENABLE;
|
|
||||||
cmd.command = CMD_ABSPOINTER_COMMAND;
|
|
||||||
CommandSend(&cmd);
|
|
||||||
|
|
||||||
/* Status */
|
|
||||||
cmd.bx = 0;
|
|
||||||
cmd.command = CMD_ABSPOINTER_STATUS;
|
|
||||||
CommandSend(&cmd);
|
|
||||||
|
|
||||||
/* Read data (1) */
|
|
||||||
cmd.bx = 1;
|
|
||||||
cmd.command = CMD_ABSPOINTER_DATA;
|
|
||||||
CommandSend(&cmd);
|
|
||||||
|
|
||||||
/* Enable absolute */
|
|
||||||
cmd.bx = ABSPOINTER_ABSOLUTE;
|
|
||||||
cmd.command = CMD_ABSPOINTER_COMMAND;
|
|
||||||
CommandSend(&cmd);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Relative()
|
|
||||||
{
|
|
||||||
VMwareCommand cmd = {0};
|
|
||||||
cmd.bx = ABSPOINTER_RELATIVE;
|
|
||||||
cmd.command = CMD_ABSPOINTER_COMMAND;
|
|
||||||
CommandSend(&cmd);
|
|
||||||
}
|
|
||||||
|
|
||||||
InputReport ir = {0};
|
|
||||||
void InterruptHandler(TrapFrame *)
|
|
||||||
{
|
|
||||||
uint8_t Data = inb(0x60);
|
|
||||||
(void)Data;
|
|
||||||
|
|
||||||
VMwareCommand cmd = {0};
|
|
||||||
cmd.bx = 0;
|
|
||||||
cmd.command = CMD_ABSPOINTER_STATUS;
|
|
||||||
CommandSend(&cmd);
|
|
||||||
|
|
||||||
if (cmd.ax == 0xFFFF0000)
|
|
||||||
{
|
|
||||||
KernelLog("VMware mouse is not connected?");
|
|
||||||
Relative();
|
|
||||||
Absolute();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((cmd.ax & 0xFFFF) < 4)
|
|
||||||
return;
|
|
||||||
|
|
||||||
cmd.bx = 4;
|
|
||||||
cmd.command = CMD_ABSPOINTER_DATA;
|
|
||||||
CommandSend(&cmd);
|
|
||||||
|
|
||||||
int Buttons = (cmd.ax & 0xFFFF);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* How should I handle this?
|
|
||||||
* (cmd.[bx,cx] * Width) / 0xFFFF
|
|
||||||
* Maybe TODO: Width and Height API?
|
|
||||||
*/
|
|
||||||
uintptr_t AbsoluteX = cmd.bx;
|
|
||||||
uintptr_t AbsoluteY = cmd.cx;
|
|
||||||
|
|
||||||
ir.Type = INPUT_TYPE_MOUSE;
|
|
||||||
ir.Device = MouseDevID;
|
|
||||||
ir.Mouse.X = AbsoluteX;
|
|
||||||
ir.Mouse.Y = AbsoluteY;
|
|
||||||
ir.Mouse.Z = (int8_t)cmd.dx;
|
|
||||||
ir.Mouse.Absolute = 1;
|
|
||||||
ir.Mouse.LeftButton = Buttons & 0x20;
|
|
||||||
ir.Mouse.RightButton = Buttons & 0x10;
|
|
||||||
ir.Mouse.MiddleButton = Buttons & 0x08;
|
|
||||||
// ir.Mouse.Button4 = 0x0;
|
|
||||||
// ir.Mouse.Button5 = 0x0;
|
|
||||||
// ir.Mouse.Button6 = 0x0;
|
|
||||||
// ir.Mouse.Button7 = 0x0;
|
|
||||||
// ir.Mouse.Button8 = 0x0;
|
|
||||||
ReportInputEvent(&ir);
|
|
||||||
}
|
|
||||||
|
|
||||||
int __fs_Ioctl(struct Inode *, unsigned long Request, void *)
|
|
||||||
{
|
|
||||||
switch (Request)
|
|
||||||
{
|
|
||||||
case 0x1:
|
|
||||||
Relative();
|
|
||||||
break;
|
|
||||||
case 0x2:
|
|
||||||
Absolute();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const struct InodeOperations MouseOps = {
|
|
||||||
.Ioctl = __fs_Ioctl,
|
|
||||||
};
|
|
||||||
|
|
||||||
bool ToolboxSupported = false;
|
|
||||||
int DriverEntry()
|
|
||||||
{
|
|
||||||
ToolboxContext tb_ctx = {0};
|
|
||||||
/* Test if it's supported */
|
|
||||||
int status = OpenMessageChannel(&tb_ctx, MESSAGE_TCLO);
|
|
||||||
if (status == 0)
|
|
||||||
{
|
|
||||||
ToolboxSupported = true;
|
|
||||||
MessageClose(&tb_ctx);
|
|
||||||
dst_id = CreateKernelThread(0, "VMware Display Scale",
|
|
||||||
(void *)DisplayScaleThread, NULL);
|
|
||||||
dst_pid = GetCurrentProcess();
|
|
||||||
}
|
|
||||||
|
|
||||||
PS2WriteCommand(PS2_CMD_ENABLE_PORT_2);
|
|
||||||
PS2WriteCommand(PS2_CMD_READ_CONFIG);
|
|
||||||
PS2_CONFIGURATION config = {.Raw = PS2ReadData()};
|
|
||||||
config.Port2Interrupt = 1;
|
|
||||||
PS2WriteCommand(PS2_CMD_WRITE_CONFIG);
|
|
||||||
PS2WriteData(config.Raw);
|
|
||||||
|
|
||||||
PS2WriteCommand(PS2_CMD_WRITE_NEXT_BYTE_TO_PS2_PORT_2_INPUT);
|
|
||||||
PS2WriteData(PS2_MOUSE_CMD_SET_DEFAULTS);
|
|
||||||
PS2ReadData();
|
|
||||||
|
|
||||||
PS2WriteCommand(PS2_CMD_WRITE_NEXT_BYTE_TO_PS2_PORT_2_INPUT);
|
|
||||||
PS2WriteData(PS2_MOUSE_CMD_ENABLE_DATA_REPORTING);
|
|
||||||
PS2ReadData();
|
|
||||||
Absolute();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If we have another driver using the PS/2 mouse, we need to
|
|
||||||
* override its interrupt handler.
|
|
||||||
*/
|
|
||||||
OverrideInterruptHandler(12, InterruptHandler);
|
|
||||||
|
|
||||||
MouseDevID = RegisterDevice(INPUT_TYPE_MOUSE, &MouseOps);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int DriverFinal()
|
|
||||||
{
|
|
||||||
PS2WriteCommand(PS2_CMD_WRITE_NEXT_BYTE_TO_PS2_PORT_2_INPUT);
|
|
||||||
PS2WriteData(PS2_MOUSE_CMD_DISABLE_DATA_REPORTING);
|
|
||||||
|
|
||||||
Relative();
|
|
||||||
|
|
||||||
UnregisterDevice(MouseDevID);
|
|
||||||
|
|
||||||
if (ToolboxSupported)
|
|
||||||
{
|
|
||||||
KillThread(dst_id, dst_pid, 0);
|
|
||||||
if (tb_ctx->TCLOChannel != -1)
|
|
||||||
MessageClose(tb_ctx);
|
|
||||||
FreeMemory(tb_ctx, 1);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int DriverPanic()
|
|
||||||
{
|
|
||||||
Relative();
|
|
||||||
PS2WriteCommand(PS2_CMD_WRITE_NEXT_BYTE_TO_PS2_PORT_2_INPUT);
|
|
||||||
PS2WriteData(PS2_MOUSE_CMD_DISABLE_DATA_REPORTING);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int DriverProbe()
|
|
||||||
{
|
|
||||||
if (!IsVMwareBackdoorAvailable())
|
|
||||||
return -ENODEV;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
DriverInfo("vmware",
|
|
||||||
"VMware Tools Driver",
|
|
||||||
"EnderIce2",
|
|
||||||
0, 0, 1,
|
|
||||||
"GPLv3");
|
|
@ -1,35 +0,0 @@
|
|||||||
default:
|
|
||||||
$(error Do not run this Makefile directly!)
|
|
||||||
|
|
||||||
S_SOURCES = $(shell find ./ -type f -name '*.S')
|
|
||||||
C_SOURCES = $(shell find ./ -type f -name '*.c')
|
|
||||||
CXX_SOURCES = $(shell find ./ -type f -name '*.cpp')
|
|
||||||
HEADERS = $(sort $(dir $(wildcard ../../include/*)))
|
|
||||||
OBJ = $(C_SOURCES:.c=.o) $(CXX_SOURCES:.cpp=.o) $(S_SOURCES:.S=.o)
|
|
||||||
STACK_USAGE_OBJ = $(C_SOURCES:.c=.su) $(CXX_SOURCES:.cpp=.su)
|
|
||||||
|
|
||||||
FILENAME = $(notdir $(shell pwd)).drv
|
|
||||||
|
|
||||||
build: $(FILENAME)
|
|
||||||
mv $(FILENAME) $(OUTPUT_DIR)$(FILENAME)
|
|
||||||
|
|
||||||
$(FILENAME): $(OBJ)
|
|
||||||
$(info Linking $@)
|
|
||||||
$(CC) $(DRIVER_LDFLAGS) $(OBJ) $(OUTPUT_DIR)dcrt0.o -L$(OUTPUT_DIR) -lkernel -o $@
|
|
||||||
|
|
||||||
WARNCFLAG = -Wall -Wextra
|
|
||||||
|
|
||||||
%.o: %.c $(HEADERS)
|
|
||||||
$(info Compiling $<)
|
|
||||||
$(CC) $(DRIVER_CFLAGS) $(WARNCFLAG) -std=c17 -c $< -o $@
|
|
||||||
|
|
||||||
%.o: %.cpp $(HEADERS)
|
|
||||||
$(info Compiling $<)
|
|
||||||
$(CXX) $(DRIVER_CFLAGS) $(WARNCFLAG) -std=c++20 -fno-exceptions -fno-rtti -c $< -o $@
|
|
||||||
|
|
||||||
%.o: %.S
|
|
||||||
$(info Compiling $<)
|
|
||||||
$(AS) -o $@ $<
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -f file.map $(OBJ) $(STACK_USAGE_OBJ)
|
|
@ -1,512 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of Fennix Kernel.
|
|
||||||
|
|
||||||
Fennix Kernel is free software: you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU General Public License as
|
|
||||||
published by the Free Software Foundation, either version 3 of
|
|
||||||
the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
Fennix Kernel is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <netools.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <regs.h>
|
|
||||||
#include <base.h>
|
|
||||||
#include <pci.h>
|
|
||||||
#include <network.h>
|
|
||||||
#include <io.h>
|
|
||||||
|
|
||||||
#include "e1000.hpp"
|
|
||||||
|
|
||||||
class E1000Device
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
PCIHeader0 *Header;
|
|
||||||
uint16_t DeviceID;
|
|
||||||
bool Initialized = false;
|
|
||||||
|
|
||||||
bool EEPROMAvailable;
|
|
||||||
|
|
||||||
struct BARData
|
|
||||||
{
|
|
||||||
uint8_t Type;
|
|
||||||
uint16_t IOBase;
|
|
||||||
uint64_t MemoryBase;
|
|
||||||
} BAR;
|
|
||||||
|
|
||||||
#define E1000_NUM_RX_DESC 32
|
|
||||||
#define E1000_NUM_TX_DESC 8
|
|
||||||
RXDescriptor *RX[E1000_NUM_RX_DESC];
|
|
||||||
TXDescriptor *TX[E1000_NUM_TX_DESC];
|
|
||||||
|
|
||||||
uint16_t RXCurrent;
|
|
||||||
uint16_t TXCurrent;
|
|
||||||
|
|
||||||
const int BaseBufferSize = 8192;
|
|
||||||
const int AdditionalBytes = 16;
|
|
||||||
|
|
||||||
uint32_t CurrentPacket;
|
|
||||||
|
|
||||||
void WriteCMD(uint16_t Address, uint32_t Value)
|
|
||||||
{
|
|
||||||
if (BAR.Type == 0)
|
|
||||||
mmoutl((void *)(BAR.MemoryBase + Address), Value);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
outl(BAR.IOBase, Address);
|
|
||||||
outl(BAR.IOBase + 4, Value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t ReadCMD(uint16_t Address)
|
|
||||||
{
|
|
||||||
if (BAR.Type == 0)
|
|
||||||
return mminl((void *)(BAR.MemoryBase + Address));
|
|
||||||
else
|
|
||||||
{
|
|
||||||
outl(BAR.IOBase, Address);
|
|
||||||
return inl(BAR.IOBase + 0x4);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t ReadEEPROM(uint8_t Address)
|
|
||||||
{
|
|
||||||
uint16_t Data = 0;
|
|
||||||
uint32_t temp = 0;
|
|
||||||
if (EEPROMAvailable)
|
|
||||||
{
|
|
||||||
WriteCMD(REG::EEPROM, (1) | ((uint32_t)(Address) << 8));
|
|
||||||
while (!((temp = ReadCMD(REG::EEPROM)) & (1 << 4)))
|
|
||||||
;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
WriteCMD(REG::EEPROM, (1) | ((uint32_t)(Address) << 2));
|
|
||||||
while (!((temp = ReadCMD(REG::EEPROM)) & (1 << 1)))
|
|
||||||
;
|
|
||||||
}
|
|
||||||
Data = (uint16_t)((temp >> 16) & 0xFFFF);
|
|
||||||
return Data;
|
|
||||||
}
|
|
||||||
|
|
||||||
void InitializeRX()
|
|
||||||
{
|
|
||||||
DebugLog("Initializing RX...");
|
|
||||||
uintptr_t Ptr = (uintptr_t)AllocateMemory(TO_PAGES(sizeof(RXDescriptor) *
|
|
||||||
E1000_NUM_RX_DESC +
|
|
||||||
AdditionalBytes));
|
|
||||||
|
|
||||||
for (int i = 0; i < E1000_NUM_RX_DESC; i++)
|
|
||||||
{
|
|
||||||
RX[i] = (RXDescriptor *)(Ptr + i * 16);
|
|
||||||
RX[i]->Address = (uint64_t)AllocateMemory(TO_PAGES(BaseBufferSize + AdditionalBytes));
|
|
||||||
RX[i]->Status = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma GCC diagnostic ignored "-Wshift-count-overflow"
|
|
||||||
|
|
||||||
WriteCMD(REG::TXDESCLO, (uint32_t)(Ptr >> 32));
|
|
||||||
WriteCMD(REG::TXDESCHI, (uint32_t)(Ptr & 0xFFFFFFFF));
|
|
||||||
|
|
||||||
WriteCMD(REG::RXDESCLO, (uint32_t)Ptr);
|
|
||||||
WriteCMD(REG::RXDESCHI, 0);
|
|
||||||
|
|
||||||
WriteCMD(REG::RXDESCLEN, E1000_NUM_RX_DESC * 16);
|
|
||||||
|
|
||||||
WriteCMD(REG::RXDESCHEAD, 0);
|
|
||||||
WriteCMD(REG::RXDESCTAIL, E1000_NUM_RX_DESC - 1);
|
|
||||||
RXCurrent = 0;
|
|
||||||
WriteCMD(REG::RCTRL, RCTL::EN | RCTL::SBP | RCTL::UPE |
|
|
||||||
RCTL::MPE | RCTL::LBM_NONE |
|
|
||||||
RTCL::RDMTS_HALF | RCTL::BAM |
|
|
||||||
RCTL::SECRC | RCTL::BSIZE_8192);
|
|
||||||
}
|
|
||||||
|
|
||||||
void InitializeTX()
|
|
||||||
{
|
|
||||||
DebugLog("Initializing TX...");
|
|
||||||
uintptr_t Ptr = (uintptr_t)AllocateMemory(TO_PAGES(sizeof(TXDescriptor) *
|
|
||||||
E1000_NUM_RX_DESC +
|
|
||||||
AdditionalBytes));
|
|
||||||
|
|
||||||
for (short i = 0; i < E1000_NUM_TX_DESC; i++)
|
|
||||||
{
|
|
||||||
TX[i] = (TXDescriptor *)((uintptr_t)Ptr + i * 16);
|
|
||||||
TX[i]->Address = 0;
|
|
||||||
TX[i]->Command = 0;
|
|
||||||
TX[i]->Status = TSTA::DD;
|
|
||||||
}
|
|
||||||
|
|
||||||
WriteCMD(REG::TXDESCHI, (uint32_t)((uint64_t)Ptr >> 32));
|
|
||||||
WriteCMD(REG::TXDESCLO, (uint32_t)((uint64_t)Ptr & 0xFFFFFFFF));
|
|
||||||
|
|
||||||
WriteCMD(REG::TXDESCLEN, E1000_NUM_TX_DESC * 16);
|
|
||||||
|
|
||||||
WriteCMD(REG::TXDESCHEAD, 0);
|
|
||||||
WriteCMD(REG::TXDESCTAIL, 0);
|
|
||||||
TXCurrent = 0;
|
|
||||||
WriteCMD(REG::TCTRL, TCTL::EN_ | TCTL::PSP |
|
|
||||||
(15 << TCTL::CT_SHIFT) |
|
|
||||||
(64 << TCTL::COLD_SHIFT) |
|
|
||||||
TCTL::RTLC);
|
|
||||||
|
|
||||||
WriteCMD(REG::TCTRL, 0b0110000000000111111000011111010);
|
|
||||||
WriteCMD(REG::TIPG, 0x0060200A);
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
dev_t ID;
|
|
||||||
|
|
||||||
bool IsInitialized() { return Initialized; }
|
|
||||||
|
|
||||||
size_t write(uint8_t *Buffer, size_t Size)
|
|
||||||
{
|
|
||||||
TX[TXCurrent]->Address = (uint64_t)Buffer;
|
|
||||||
TX[TXCurrent]->Length = (uint16_t)Size;
|
|
||||||
TX[TXCurrent]->Command = CMD::EOP | CMD::IFCS | CMD::RS;
|
|
||||||
TX[TXCurrent]->Status = 0;
|
|
||||||
uint16_t OldTXCurrent = TXCurrent;
|
|
||||||
TXCurrent = (uint16_t)((TXCurrent + 1) % E1000_NUM_TX_DESC);
|
|
||||||
WriteCMD(REG::TXDESCTAIL, TXCurrent);
|
|
||||||
while (!(TX[OldTXCurrent]->Status & 0xFF))
|
|
||||||
Yield();
|
|
||||||
return Size;
|
|
||||||
}
|
|
||||||
|
|
||||||
MediaAccessControl GetMAC()
|
|
||||||
{
|
|
||||||
MediaAccessControl mac;
|
|
||||||
if (EEPROMAvailable)
|
|
||||||
{
|
|
||||||
uint32_t temp;
|
|
||||||
temp = ReadEEPROM(0);
|
|
||||||
mac.Address[0] = temp & 0xff;
|
|
||||||
mac.Address[1] = (uint8_t)(temp >> 8);
|
|
||||||
temp = ReadEEPROM(1);
|
|
||||||
mac.Address[2] = temp & 0xff;
|
|
||||||
mac.Address[3] = (uint8_t)(temp >> 8);
|
|
||||||
temp = ReadEEPROM(2);
|
|
||||||
mac.Address[4] = temp & 0xff;
|
|
||||||
mac.Address[5] = (uint8_t)(temp >> 8);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
uint8_t *BaseMac8 = (uint8_t *)(BAR.MemoryBase + 0x5400);
|
|
||||||
uint32_t *BaseMac32 = (uint32_t *)(BAR.MemoryBase + 0x5400);
|
|
||||||
if (BaseMac32[0] != 0)
|
|
||||||
for (int i = 0; i < 6; i++)
|
|
||||||
mac.Address[i] = BaseMac8[i];
|
|
||||||
else
|
|
||||||
{
|
|
||||||
KernelLog("No MAC address found.");
|
|
||||||
return MediaAccessControl();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return mac;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ioctl(NetIoctl req, void *arg)
|
|
||||||
{
|
|
||||||
switch (req)
|
|
||||||
{
|
|
||||||
case IOCTL_NET_GET_MAC:
|
|
||||||
{
|
|
||||||
MediaAccessControl mac = GetMAC();
|
|
||||||
*((uint48_t *)arg) = mac.ToHex(); /* UNTESTED */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnInterruptReceived(TrapFrame *)
|
|
||||||
{
|
|
||||||
WriteCMD(REG::IMASK, 0x1);
|
|
||||||
uint32_t status = ReadCMD(0xC0);
|
|
||||||
UNUSED(status);
|
|
||||||
|
|
||||||
while ((RX[RXCurrent]->Status & 0x1))
|
|
||||||
{
|
|
||||||
uint8_t *data = (uint8_t *)RX[RXCurrent]->Address;
|
|
||||||
uint16_t dataSz = RX[RXCurrent]->Length;
|
|
||||||
|
|
||||||
// ReportNetworkPacket(ID, data, dataSz);
|
|
||||||
/* FIXME: Implement */
|
|
||||||
KernelLog("FIXME: Received packet");
|
|
||||||
(void)data;
|
|
||||||
(void)dataSz;
|
|
||||||
|
|
||||||
RX[RXCurrent]->Status = 0;
|
|
||||||
uint16_t OldRXCurrent = RXCurrent;
|
|
||||||
RXCurrent = (uint16_t)((RXCurrent + 1) % E1000_NUM_RX_DESC);
|
|
||||||
WriteCMD(REG::RXDESCTAIL, OldRXCurrent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Panic()
|
|
||||||
{
|
|
||||||
WriteCMD(REG::IMASK, 0x00000000);
|
|
||||||
WriteCMD(REG::ITR, 0x00000000);
|
|
||||||
WriteCMD(REG::IAM, 0x00000000);
|
|
||||||
}
|
|
||||||
|
|
||||||
E1000Device(PCIHeader0 *_Header, uint16_t _DeviceID)
|
|
||||||
: Header(_Header),
|
|
||||||
DeviceID(_DeviceID)
|
|
||||||
{
|
|
||||||
uint32_t PCIBAR0 = Header->BAR0;
|
|
||||||
uint32_t PCIBAR1 = Header->BAR1;
|
|
||||||
BAR.Type = PCIBAR0 & 1;
|
|
||||||
BAR.IOBase = (uint16_t)(PCIBAR0 & (~3));
|
|
||||||
BAR.MemoryBase = PCIBAR1 & (~15);
|
|
||||||
|
|
||||||
switch (DeviceID)
|
|
||||||
{
|
|
||||||
case 0x100E:
|
|
||||||
{
|
|
||||||
KernelLog("Found Intel 82540EM Gigabit Ethernet Controller.");
|
|
||||||
|
|
||||||
/* Detect EEPROM */
|
|
||||||
WriteCMD(REG::EEPROM, 0x1);
|
|
||||||
for (int i = 0; i < 1000 && !EEPROMAvailable; i++)
|
|
||||||
if (ReadCMD(REG::EEPROM) & 0x10)
|
|
||||||
EEPROMAvailable = true;
|
|
||||||
else
|
|
||||||
EEPROMAvailable = false;
|
|
||||||
|
|
||||||
if (!GetMAC().Valid())
|
|
||||||
{
|
|
||||||
KernelLog("Failed to get MAC");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Start link */
|
|
||||||
uint32_t cmdret = ReadCMD(REG::CTRL);
|
|
||||||
WriteCMD(REG::CTRL, cmdret | ECTRL::SLU);
|
|
||||||
|
|
||||||
for (int i = 0; i < 0x80; i++)
|
|
||||||
WriteCMD((uint16_t)(0x5200 + i * 4), 0);
|
|
||||||
|
|
||||||
WriteCMD(REG::IMASK, 0x1F6DC);
|
|
||||||
WriteCMD(REG::IMASK, 0xFF & ~4);
|
|
||||||
ReadCMD(0xC0);
|
|
||||||
|
|
||||||
InitializeRX();
|
|
||||||
InitializeTX();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
KernelLog("Unimplemented E1000 device.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Initialized = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
~E1000Device()
|
|
||||||
{
|
|
||||||
if (!Initialized)
|
|
||||||
return;
|
|
||||||
|
|
||||||
switch (DeviceID)
|
|
||||||
{
|
|
||||||
case 0x100E:
|
|
||||||
{
|
|
||||||
// Clearing Enable bit in Receive Control Register
|
|
||||||
uint32_t cmdret = ReadCMD(REG::RCTRL);
|
|
||||||
WriteCMD(REG::RCTRL, cmdret & ~RCTL::EN);
|
|
||||||
|
|
||||||
// Masking Interrupt Mask, Interrupt Throttling Rate & Interrupt Auto-Mask
|
|
||||||
WriteCMD(REG::IMASK, 0x00000000);
|
|
||||||
WriteCMD(REG::ITR, 0x00000000);
|
|
||||||
WriteCMD(REG::IAM, 0x00000000);
|
|
||||||
|
|
||||||
// Clearing SLU bit in Device Control Register
|
|
||||||
cmdret = ReadCMD(REG::CTRL);
|
|
||||||
WriteCMD(REG::CTRL, cmdret & ~ECTRL::SLU);
|
|
||||||
|
|
||||||
// Clear the Interrupt Cause Read register by reading it
|
|
||||||
ReadCMD(REG::ICR);
|
|
||||||
|
|
||||||
// Powering down the device (?)
|
|
||||||
WriteCMD(REG::CTRL, PCTRL::POWER_DOWN);
|
|
||||||
/* TODO: Stop link; further testing required */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
KernelLog("Unimplemented E1000 device.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
E1000Device *Drivers[4] = {nullptr};
|
|
||||||
dev_t NetID[4] = {(dev_t)-1};
|
|
||||||
|
|
||||||
#define OIR(x) OIR_##x
|
|
||||||
#define CREATE_OIR(x) \
|
|
||||||
void OIR_##x(TrapFrame *f) { Drivers[x]->OnInterruptReceived(f); }
|
|
||||||
|
|
||||||
CREATE_OIR(0);
|
|
||||||
CREATE_OIR(1);
|
|
||||||
CREATE_OIR(2);
|
|
||||||
CREATE_OIR(3);
|
|
||||||
|
|
||||||
int __fs_Open(struct Inode *, int, mode_t) { return 0; }
|
|
||||||
int __fs_Close(struct Inode *) { return 0; }
|
|
||||||
ssize_t __fs_Read(struct Inode *, void *, size_t, off_t) { return 0; }
|
|
||||||
|
|
||||||
ssize_t __fs_Write(struct Inode *Node, const void *Buffer, size_t Size, off_t)
|
|
||||||
{
|
|
||||||
return Drivers[NetID[Node->GetMinor()]]->write((uint8_t *)Buffer, Size);
|
|
||||||
}
|
|
||||||
|
|
||||||
int __fs_Ioctl(struct Inode *Node, unsigned long Request, void *Argp)
|
|
||||||
{
|
|
||||||
return Drivers[NetID[Node->GetMinor()]]->ioctl((NetIoctl)Request, Argp);
|
|
||||||
}
|
|
||||||
|
|
||||||
const struct InodeOperations NetOps = {
|
|
||||||
.Lookup = nullptr,
|
|
||||||
.Create = nullptr,
|
|
||||||
.Remove = nullptr,
|
|
||||||
.Rename = nullptr,
|
|
||||||
.Read = __fs_Read,
|
|
||||||
.Write = __fs_Write,
|
|
||||||
.Truncate = nullptr,
|
|
||||||
.Open = __fs_Open,
|
|
||||||
.Close = __fs_Close,
|
|
||||||
.Ioctl = __fs_Ioctl,
|
|
||||||
.ReadDir = nullptr,
|
|
||||||
.MkDir = nullptr,
|
|
||||||
.RmDir = nullptr,
|
|
||||||
.SymLink = nullptr,
|
|
||||||
.ReadLink = nullptr,
|
|
||||||
.Seek = nullptr,
|
|
||||||
.Stat = nullptr,
|
|
||||||
};
|
|
||||||
|
|
||||||
PCIArray *Devices;
|
|
||||||
EXTERNC int cxx_Panic()
|
|
||||||
{
|
|
||||||
PCIArray *ctx = Devices;
|
|
||||||
short Count = 0;
|
|
||||||
while (ctx != nullptr)
|
|
||||||
{
|
|
||||||
if (Drivers[Count] != nullptr)
|
|
||||||
Drivers[Count]->Panic();
|
|
||||||
Count++;
|
|
||||||
ctx = (PCIArray *)ctx->Next;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
EXTERNC int cxx_Probe()
|
|
||||||
{
|
|
||||||
uint16_t VendorIDs[] = {0x8086, /* Intel */
|
|
||||||
PCI_END};
|
|
||||||
uint16_t DeviceIDs[] = {0x100E, /* 82540EM */
|
|
||||||
0x100F, /* 82545EM */
|
|
||||||
0x10D3, /* 82574L */
|
|
||||||
0x10EA, /* I217-LM */
|
|
||||||
0x153A, /* 82577LM */
|
|
||||||
PCI_END};
|
|
||||||
Devices = GetPCIDevices(VendorIDs, DeviceIDs);
|
|
||||||
if (Devices == nullptr)
|
|
||||||
{
|
|
||||||
KernelLog("No E1000 device found.");
|
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
EXTERNC int cxx_Initialize()
|
|
||||||
{
|
|
||||||
PCIArray *ctx = Devices;
|
|
||||||
size_t Count = 0;
|
|
||||||
while (ctx != nullptr)
|
|
||||||
{
|
|
||||||
if (Count > sizeof(Drivers) / sizeof(E1000Device *))
|
|
||||||
break;
|
|
||||||
|
|
||||||
InitializePCI(ctx->Device);
|
|
||||||
|
|
||||||
Drivers[Count] = new E1000Device((PCIHeader0 *)ctx->Device->Header,
|
|
||||||
ctx->Device->Header->DeviceID);
|
|
||||||
|
|
||||||
if (Drivers[Count]->IsInitialized())
|
|
||||||
{
|
|
||||||
dev_t ret = RegisterDevice(NETWORK_TYPE_ETHERNET, &NetOps);
|
|
||||||
NetID[Count] = ret;
|
|
||||||
Drivers[Count]->ID = ret;
|
|
||||||
|
|
||||||
/* FIXME: bad code */
|
|
||||||
switch (Count)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
RegisterInterruptHandler(iLine(ctx->Device), (void *)OIR(0));
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
RegisterInterruptHandler(iLine(ctx->Device), (void *)OIR(1));
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
RegisterInterruptHandler(iLine(ctx->Device), (void *)OIR(2));
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
RegisterInterruptHandler(iLine(ctx->Device), (void *)OIR(3));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
Count++;
|
|
||||||
}
|
|
||||||
ctx = (PCIArray *)ctx->Next;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Count == 0)
|
|
||||||
{
|
|
||||||
KernelLog("No valid E1000 device found.");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
EXTERNC int cxx_Finalize()
|
|
||||||
{
|
|
||||||
PCIArray *ctx = Devices;
|
|
||||||
size_t Count = 0;
|
|
||||||
while (ctx != nullptr)
|
|
||||||
{
|
|
||||||
if (Count++ > sizeof(Drivers) / sizeof(E1000Device *))
|
|
||||||
break;
|
|
||||||
|
|
||||||
delete Drivers[Count++];
|
|
||||||
ctx->Device->Header->Command |= PCI_COMMAND_INTX_DISABLE;
|
|
||||||
ctx = (PCIArray *)ctx->Next;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < sizeof(NetID) / sizeof(dev_t); i++)
|
|
||||||
{
|
|
||||||
if (NetID[i] != (dev_t)-1)
|
|
||||||
UnregisterDevice(NetID[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,31 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of Fennix Drivers.
|
|
||||||
|
|
||||||
Fennix Drivers is free software: you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU General Public License as
|
|
||||||
published by the Free Software Foundation, either version 3 of
|
|
||||||
the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
Fennix Drivers is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with Fennix Drivers. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <base.h>
|
|
||||||
|
|
||||||
#include "e1000.hpp"
|
|
||||||
|
|
||||||
int DriverEntry() { return cxx_Initialize(); }
|
|
||||||
int DriverFinal() { return cxx_Finalize(); }
|
|
||||||
int DriverPanic() { return cxx_Panic(); }
|
|
||||||
int DriverProbe() { return cxx_Probe(); }
|
|
||||||
|
|
||||||
DriverInfo("e1000",
|
|
||||||
"Intel(R) PRO/1000 Network Driver",
|
|
||||||
"EnderIce2",
|
|
||||||
0, 0, 1,
|
|
||||||
"GPLv3");
|
|
@ -1,35 +0,0 @@
|
|||||||
default:
|
|
||||||
$(error Do not run this Makefile directly!)
|
|
||||||
|
|
||||||
S_SOURCES = $(shell find ./ -type f -name '*.S')
|
|
||||||
C_SOURCES = $(shell find ./ -type f -name '*.c')
|
|
||||||
CXX_SOURCES = $(shell find ./ -type f -name '*.cpp')
|
|
||||||
HEADERS = $(sort $(dir $(wildcard ../../include/*)))
|
|
||||||
OBJ = $(C_SOURCES:.c=.o) $(CXX_SOURCES:.cpp=.o) $(S_SOURCES:.S=.o)
|
|
||||||
STACK_USAGE_OBJ = $(C_SOURCES:.c=.su) $(CXX_SOURCES:.cpp=.su)
|
|
||||||
|
|
||||||
FILENAME = $(notdir $(shell pwd)).drv
|
|
||||||
|
|
||||||
build: $(FILENAME)
|
|
||||||
mv $(FILENAME) $(OUTPUT_DIR)$(FILENAME)
|
|
||||||
|
|
||||||
$(FILENAME): $(OBJ)
|
|
||||||
$(info Linking $@)
|
|
||||||
$(CC) $(DRIVER_LDFLAGS) $(OBJ) $(OUTPUT_DIR)dcrt0.o -L$(OUTPUT_DIR) -lkernel -o $@
|
|
||||||
|
|
||||||
WARNCFLAG = -Wall -Wextra
|
|
||||||
|
|
||||||
%.o: %.c $(HEADERS)
|
|
||||||
$(info Compiling $<)
|
|
||||||
$(CC) $(DRIVER_CFLAGS) $(WARNCFLAG) -std=c17 -c $< -o $@
|
|
||||||
|
|
||||||
%.o: %.cpp $(HEADERS)
|
|
||||||
$(info Compiling $<)
|
|
||||||
$(CXX) $(DRIVER_CFLAGS) $(WARNCFLAG) -std=c++20 -fno-exceptions -fno-rtti -c $< -o $@
|
|
||||||
|
|
||||||
%.o: %.S
|
|
||||||
$(info Compiling $<)
|
|
||||||
$(AS) -o $@ $<
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -f file.map $(OBJ) $(STACK_USAGE_OBJ)
|
|
@ -1,31 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of Fennix Drivers.
|
|
||||||
|
|
||||||
Fennix Drivers is free software: you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU General Public License as
|
|
||||||
published by the Free Software Foundation, either version 3 of
|
|
||||||
the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
Fennix Drivers is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with Fennix Drivers. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <base.h>
|
|
||||||
|
|
||||||
#include "rtl8139.hpp"
|
|
||||||
|
|
||||||
int DriverEntry() { return cxx_Initialize(); }
|
|
||||||
int DriverFinal() { return cxx_Finalize(); }
|
|
||||||
int DriverPanic() { return cxx_Panic(); }
|
|
||||||
int DriverProbe() { return cxx_Probe(); }
|
|
||||||
|
|
||||||
DriverInfo("rtl8139",
|
|
||||||
"Realtek RTL8139 Network Driver",
|
|
||||||
"EnderIce2",
|
|
||||||
0, 0, 1,
|
|
||||||
"GPLv3");
|
|
@ -1,325 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of Fennix Kernel.
|
|
||||||
|
|
||||||
Fennix Kernel is free software: you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU General Public License as
|
|
||||||
published by the Free Software Foundation, either version 3 of
|
|
||||||
the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
Fennix Kernel is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <netools.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <regs.h>
|
|
||||||
#include <base.h>
|
|
||||||
#include <pci.h>
|
|
||||||
#include <network.h>
|
|
||||||
#include <io.h>
|
|
||||||
|
|
||||||
#include "rtl8139.hpp"
|
|
||||||
|
|
||||||
class RTL8139Device
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
PCIHeader0 *Header;
|
|
||||||
bool Initialized = false;
|
|
||||||
|
|
||||||
struct BARData
|
|
||||||
{
|
|
||||||
uint8_t Type;
|
|
||||||
uint16_t IOBase;
|
|
||||||
uint64_t MemoryBase;
|
|
||||||
} BAR;
|
|
||||||
|
|
||||||
const int BaseBufferSize = 8192;
|
|
||||||
const int WRAPBytes = 1500;
|
|
||||||
const int AdditionalBytes = 16;
|
|
||||||
const int BufferSize = BaseBufferSize +
|
|
||||||
WRAPBytes +
|
|
||||||
AdditionalBytes;
|
|
||||||
|
|
||||||
uint8_t *RXBuffer = nullptr;
|
|
||||||
int TXCurrent = 0;
|
|
||||||
uint16_t CurrentPacket = 0;
|
|
||||||
|
|
||||||
uint8_t TSAD[4] = {0x20, 0x24, 0x28, 0x2C};
|
|
||||||
uint8_t TSD[4] = {0x10, 0x14, 0x18, 0x1C};
|
|
||||||
|
|
||||||
public:
|
|
||||||
dev_t ID;
|
|
||||||
|
|
||||||
bool IsInitialized() { return Initialized; }
|
|
||||||
|
|
||||||
size_t write(uint8_t *Buffer, size_t Size)
|
|
||||||
{
|
|
||||||
outl(TSAD[TXCurrent], (uint32_t)(reinterpret_cast<uint64_t>(Buffer)));
|
|
||||||
outl(TSD[TXCurrent++], (uint32_t)Size);
|
|
||||||
if (TXCurrent > 3)
|
|
||||||
TXCurrent = 0;
|
|
||||||
return Size;
|
|
||||||
}
|
|
||||||
|
|
||||||
MediaAccessControl GetMAC()
|
|
||||||
{
|
|
||||||
return MediaAccessControl();
|
|
||||||
}
|
|
||||||
|
|
||||||
int ioctl(NetIoctl req, void *)
|
|
||||||
{
|
|
||||||
switch (req)
|
|
||||||
{
|
|
||||||
case IOCTL_NET_GET_MAC:
|
|
||||||
{
|
|
||||||
return -ENOSYS;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnInterruptReceived(TrapFrame *)
|
|
||||||
{
|
|
||||||
/* Acknowledge interrupt */
|
|
||||||
uint16_t status = inw(RegISR);
|
|
||||||
DebugLog("%#lx", status);
|
|
||||||
|
|
||||||
/* Read status */
|
|
||||||
if (status & RecOK)
|
|
||||||
{
|
|
||||||
/* Get the current packet */
|
|
||||||
uint16_t *data = (uint16_t *)(RXBuffer + CurrentPacket);
|
|
||||||
uint16_t dataSz = *(data + 1);
|
|
||||||
data += 2;
|
|
||||||
|
|
||||||
// ReportNetworkPacket(ID, data, dataSz);
|
|
||||||
/* FIXME: Implement */
|
|
||||||
KernelLog("FIXME: Received packet");
|
|
||||||
(void)data;
|
|
||||||
(void)dataSz;
|
|
||||||
|
|
||||||
/* Update CAPR */
|
|
||||||
#define RX_READ_PTR_MASK (~0x3)
|
|
||||||
CurrentPacket = (uint16_t)((CurrentPacket + dataSz + 4 + 3) & RX_READ_PTR_MASK);
|
|
||||||
if (CurrentPacket > BufferSize)
|
|
||||||
CurrentPacket -= uint16_t(BufferSize);
|
|
||||||
outw(RegCAPR, CurrentPacket - 0x10);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Clear interrupt */
|
|
||||||
outw(RegISR, (RecOK | RecBad | SendOK | SendBad));
|
|
||||||
}
|
|
||||||
|
|
||||||
void Panic()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
RTL8139Device(PCIHeader0 *_Header)
|
|
||||||
: Header(_Header)
|
|
||||||
{
|
|
||||||
uint32_t PCIBAR0 = Header->BAR0;
|
|
||||||
uint32_t PCIBAR1 = Header->BAR1;
|
|
||||||
BAR.Type = PCIBAR0 & 1;
|
|
||||||
BAR.IOBase = (uint16_t)(PCIBAR0 & (~3));
|
|
||||||
BAR.MemoryBase = PCIBAR1 & (~15);
|
|
||||||
|
|
||||||
RXBuffer = (uint8_t *)AllocateMemory(TO_PAGES(BufferSize));
|
|
||||||
|
|
||||||
/* Power on */
|
|
||||||
outb(RegCONFIG1, 0x0);
|
|
||||||
|
|
||||||
/* Software Reset */
|
|
||||||
outb(RegCMD, 0x10);
|
|
||||||
while (inb(RegCMD) & 0x10)
|
|
||||||
Yield();
|
|
||||||
|
|
||||||
/* Initialize receive buffer */
|
|
||||||
outl(RegRBSTART, (uint32_t)(reinterpret_cast<uintptr_t>(RXBuffer)));
|
|
||||||
|
|
||||||
/* Configure interrupt mask register */
|
|
||||||
outw(RegIMR, (RecOK | RecBad | SendOK | SendBad));
|
|
||||||
outl(regRCR, (RcAB | RcAM | RcAPM | RcAAP) | RcWRAP);
|
|
||||||
|
|
||||||
/* Enable receive and transmit */
|
|
||||||
outb(RegCMD, 0xC); /* 0xC = RE and TE bit */
|
|
||||||
|
|
||||||
uint32_t MAC1 = inl(RegMAC);
|
|
||||||
uint16_t MAC2 = inw(RegMAR);
|
|
||||||
MediaAccessControl mac = {
|
|
||||||
mac.Address[0] = (uint8_t)MAC1,
|
|
||||||
mac.Address[1] = (uint8_t)(MAC1 >> 8),
|
|
||||||
mac.Address[2] = (uint8_t)(MAC1 >> 16),
|
|
||||||
mac.Address[3] = (uint8_t)(MAC1 >> 24),
|
|
||||||
mac.Address[4] = (uint8_t)MAC2,
|
|
||||||
mac.Address[5] = (uint8_t)(MAC2 >> 8)};
|
|
||||||
|
|
||||||
Initialized = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
~RTL8139Device()
|
|
||||||
{
|
|
||||||
if (!Initialized)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* FIXME: Shutdown code */
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
RTL8139Device *Drivers[4] = {nullptr};
|
|
||||||
dev_t NetID[4] = {(dev_t)-1};
|
|
||||||
|
|
||||||
#define OIR(x) OIR_##x
|
|
||||||
#define CREATE_OIR(x) \
|
|
||||||
void OIR_##x(TrapFrame *f) { Drivers[x]->OnInterruptReceived(f); }
|
|
||||||
|
|
||||||
CREATE_OIR(0);
|
|
||||||
CREATE_OIR(1);
|
|
||||||
CREATE_OIR(2);
|
|
||||||
CREATE_OIR(3);
|
|
||||||
|
|
||||||
int __fs_Open(struct Inode *, int, mode_t) { return 0; }
|
|
||||||
int __fs_Close(struct Inode *) { return 0; }
|
|
||||||
ssize_t __fs_Read(struct Inode *, void *, size_t, off_t) { return 0; }
|
|
||||||
|
|
||||||
ssize_t __fs_Write(struct Inode *Node, const void *Buffer, size_t Size, off_t)
|
|
||||||
{
|
|
||||||
return Drivers[NetID[Node->GetMinor()]]->write((uint8_t *)Buffer, Size);
|
|
||||||
}
|
|
||||||
|
|
||||||
int __fs_Ioctl(struct Inode *Node, unsigned long Request, void *Argp)
|
|
||||||
{
|
|
||||||
return Drivers[NetID[Node->GetMinor()]]->ioctl((NetIoctl)Request, Argp);
|
|
||||||
}
|
|
||||||
|
|
||||||
const struct InodeOperations NetOps = {
|
|
||||||
.Lookup = nullptr,
|
|
||||||
.Create = nullptr,
|
|
||||||
.Remove = nullptr,
|
|
||||||
.Rename = nullptr,
|
|
||||||
.Read = __fs_Read,
|
|
||||||
.Write = __fs_Write,
|
|
||||||
.Truncate = nullptr,
|
|
||||||
.Open = __fs_Open,
|
|
||||||
.Close = __fs_Close,
|
|
||||||
.Ioctl = __fs_Ioctl,
|
|
||||||
.ReadDir = nullptr,
|
|
||||||
.MkDir = nullptr,
|
|
||||||
.RmDir = nullptr,
|
|
||||||
.SymLink = nullptr,
|
|
||||||
.ReadLink = nullptr,
|
|
||||||
.Seek = nullptr,
|
|
||||||
.Stat = nullptr,
|
|
||||||
};
|
|
||||||
|
|
||||||
PCIArray *Devices;
|
|
||||||
EXTERNC int cxx_Panic()
|
|
||||||
{
|
|
||||||
PCIArray *ctx = Devices;
|
|
||||||
short Count = 0;
|
|
||||||
while (ctx != nullptr)
|
|
||||||
{
|
|
||||||
if (Drivers[Count] != nullptr)
|
|
||||||
Drivers[Count]->Panic();
|
|
||||||
Count++;
|
|
||||||
ctx = (PCIArray *)ctx->Next;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
EXTERNC int cxx_Probe()
|
|
||||||
{
|
|
||||||
uint16_t VendorIDs[] = {0x10EC, /* Realtek */
|
|
||||||
PCI_END};
|
|
||||||
uint16_t DeviceIDs[] = {0x8139, /* RTL8139 */
|
|
||||||
PCI_END};
|
|
||||||
Devices = GetPCIDevices(VendorIDs, DeviceIDs);
|
|
||||||
if (Devices == nullptr)
|
|
||||||
{
|
|
||||||
KernelLog("No RTL8139 device found.");
|
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
EXTERNC int cxx_Initialize()
|
|
||||||
{
|
|
||||||
PCIArray *ctx = Devices;
|
|
||||||
size_t Count = 0;
|
|
||||||
while (ctx != nullptr)
|
|
||||||
{
|
|
||||||
if (Count > sizeof(Drivers) / sizeof(RTL8139Device *))
|
|
||||||
break;
|
|
||||||
|
|
||||||
InitializePCI(ctx->Device);
|
|
||||||
|
|
||||||
Drivers[Count] = new RTL8139Device((PCIHeader0 *)ctx->Device->Header);
|
|
||||||
|
|
||||||
if (Drivers[Count]->IsInitialized())
|
|
||||||
{
|
|
||||||
dev_t ret = RegisterDevice(NETWORK_TYPE_ETHERNET, &NetOps);
|
|
||||||
NetID[Count] = ret;
|
|
||||||
Drivers[Count]->ID = ret;
|
|
||||||
|
|
||||||
/* FIXME: bad code */
|
|
||||||
switch (Count)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
RegisterInterruptHandler(iLine(ctx->Device), (void *)OIR(0));
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
RegisterInterruptHandler(iLine(ctx->Device), (void *)OIR(1));
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
RegisterInterruptHandler(iLine(ctx->Device), (void *)OIR(2));
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
RegisterInterruptHandler(iLine(ctx->Device), (void *)OIR(3));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
Count++;
|
|
||||||
}
|
|
||||||
ctx = (PCIArray *)ctx->Next;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Count == 0)
|
|
||||||
{
|
|
||||||
KernelLog("No valid RTL8139 device found.");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
EXTERNC int cxx_Finalize()
|
|
||||||
{
|
|
||||||
PCIArray *ctx = Devices;
|
|
||||||
size_t Count = 0;
|
|
||||||
while (ctx != nullptr)
|
|
||||||
{
|
|
||||||
if (Count++ > sizeof(Drivers) / sizeof(RTL8139Device *))
|
|
||||||
break;
|
|
||||||
|
|
||||||
delete Drivers[Count++];
|
|
||||||
ctx->Device->Header->Command |= PCI_COMMAND_INTX_DISABLE;
|
|
||||||
ctx = (PCIArray *)ctx->Next;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < sizeof(NetID) / sizeof(dev_t); i++)
|
|
||||||
{
|
|
||||||
if (NetID[i] != (dev_t)-1)
|
|
||||||
UnregisterDevice(NetID[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,7 +1,9 @@
|
|||||||
build:
|
MAKE_TARGETS := build clean
|
||||||
make -C ahci build
|
DIRECTORIES := $(sort $(dir $(wildcard ./*/)))
|
||||||
make -C ata build
|
|
||||||
|
|
||||||
clean:
|
.PHONY: $(MAKE_TARGETS) $(DIRECTORIES)
|
||||||
make -C ahci clean
|
|
||||||
make -C ata clean
|
$(MAKE_TARGETS): $(DIRECTORIES)
|
||||||
|
|
||||||
|
$(DIRECTORIES):
|
||||||
|
$(MAKE) -C $@ $(MAKECMDGOALS)
|
||||||
|
@ -1,35 +0,0 @@
|
|||||||
default:
|
|
||||||
$(error Do not run this Makefile directly!)
|
|
||||||
|
|
||||||
S_SOURCES = $(shell find ./ -type f -name '*.S')
|
|
||||||
C_SOURCES = $(shell find ./ -type f -name '*.c')
|
|
||||||
CXX_SOURCES = $(shell find ./ -type f -name '*.cpp')
|
|
||||||
HEADERS = $(sort $(dir $(wildcard ../../include/*)))
|
|
||||||
OBJ = $(C_SOURCES:.c=.o) $(CXX_SOURCES:.cpp=.o) $(S_SOURCES:.S=.o)
|
|
||||||
STACK_USAGE_OBJ = $(C_SOURCES:.c=.su) $(CXX_SOURCES:.cpp=.su)
|
|
||||||
|
|
||||||
FILENAME = $(notdir $(shell pwd)).drv
|
|
||||||
|
|
||||||
build: $(FILENAME)
|
|
||||||
mv $(FILENAME) $(OUTPUT_DIR)$(FILENAME)
|
|
||||||
|
|
||||||
$(FILENAME): $(OBJ)
|
|
||||||
$(info Linking $@)
|
|
||||||
$(CC) $(DRIVER_LDFLAGS) $(OBJ) $(OUTPUT_DIR)dcrt0.o -L$(OUTPUT_DIR) -lkernel -o $@
|
|
||||||
|
|
||||||
WARNCFLAG = -Wall -Wextra
|
|
||||||
|
|
||||||
%.o: %.c $(HEADERS)
|
|
||||||
$(info Compiling $<)
|
|
||||||
$(CC) $(DRIVER_CFLAGS) $(WARNCFLAG) -std=c17 -c $< -o $@
|
|
||||||
|
|
||||||
%.o: %.cpp $(HEADERS)
|
|
||||||
$(info Compiling $<)
|
|
||||||
$(CXX) $(DRIVER_CFLAGS) $(WARNCFLAG) -std=c++20 -fno-exceptions -fno-rtti -c $< -o $@
|
|
||||||
|
|
||||||
%.o: %.S
|
|
||||||
$(info Compiling $<)
|
|
||||||
$(AS) -o $@ $<
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -f file.map $(OBJ) $(STACK_USAGE_OBJ)
|
|
File diff suppressed because it is too large
Load Diff
@ -1,31 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of Fennix Drivers.
|
|
||||||
|
|
||||||
Fennix Drivers is free software: you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU General Public License as
|
|
||||||
published by the Free Software Foundation, either version 3 of
|
|
||||||
the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
Fennix Drivers is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with Fennix Drivers. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <base.h>
|
|
||||||
|
|
||||||
#include "ahci.hpp"
|
|
||||||
|
|
||||||
int DriverEntry() { return cxx_Initialize(); }
|
|
||||||
int DriverFinal() { return cxx_Finalize(); }
|
|
||||||
int DriverPanic() { return cxx_Panic(); }
|
|
||||||
int DriverProbe() { return cxx_Probe(); }
|
|
||||||
|
|
||||||
DriverInfo("ahci",
|
|
||||||
"Advanced Host Controller Interface Driver",
|
|
||||||
"EnderIce2",
|
|
||||||
0, 0, 1,
|
|
||||||
"GPLv3");
|
|
@ -1,35 +0,0 @@
|
|||||||
default:
|
|
||||||
$(error Do not run this Makefile directly!)
|
|
||||||
|
|
||||||
S_SOURCES = $(shell find ./ -type f -name '*.S')
|
|
||||||
C_SOURCES = $(shell find ./ -type f -name '*.c')
|
|
||||||
CXX_SOURCES = $(shell find ./ -type f -name '*.cpp')
|
|
||||||
HEADERS = $(sort $(dir $(wildcard ../../include/*)))
|
|
||||||
OBJ = $(C_SOURCES:.c=.o) $(CXX_SOURCES:.cpp=.o) $(S_SOURCES:.S=.o)
|
|
||||||
STACK_USAGE_OBJ = $(C_SOURCES:.c=.su) $(CXX_SOURCES:.cpp=.su)
|
|
||||||
|
|
||||||
FILENAME = $(notdir $(shell pwd)).drv
|
|
||||||
|
|
||||||
build: $(FILENAME)
|
|
||||||
mv $(FILENAME) $(OUTPUT_DIR)$(FILENAME)
|
|
||||||
|
|
||||||
$(FILENAME): $(OBJ)
|
|
||||||
$(info Linking $@)
|
|
||||||
$(CC) $(DRIVER_LDFLAGS) $(OBJ) $(OUTPUT_DIR)dcrt0.o -L$(OUTPUT_DIR) -lkernel -o $@
|
|
||||||
|
|
||||||
WARNCFLAG = -Wall -Wextra
|
|
||||||
|
|
||||||
%.o: %.c $(HEADERS)
|
|
||||||
$(info Compiling $<)
|
|
||||||
$(CC) $(DRIVER_CFLAGS) $(WARNCFLAG) -std=c17 -c $< -o $@
|
|
||||||
|
|
||||||
%.o: %.cpp $(HEADERS)
|
|
||||||
$(info Compiling $<)
|
|
||||||
$(CXX) $(DRIVER_CFLAGS) $(WARNCFLAG) -std=c++20 -fno-exceptions -fno-rtti -c $< -o $@
|
|
||||||
|
|
||||||
%.o: %.S
|
|
||||||
$(info Compiling $<)
|
|
||||||
$(AS) -o $@ $<
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -f file.map $(OBJ) $(STACK_USAGE_OBJ)
|
|
@ -1,76 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of Fennix Drivers.
|
|
||||||
|
|
||||||
Fennix Drivers is free software: you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU General Public License as
|
|
||||||
published by the Free Software Foundation, either version 3 of
|
|
||||||
the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
Fennix Drivers is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with Fennix Drivers. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#include <regs.h>
|
|
||||||
#include <base.h>
|
|
||||||
#include <io.h>
|
|
||||||
|
|
||||||
bool IsATAPresent()
|
|
||||||
{
|
|
||||||
outb(0x1F0 + 2, 0);
|
|
||||||
outb(0x1F0 + 3, 0);
|
|
||||||
outb(0x1F0 + 4, 0);
|
|
||||||
outb(0x1F0 + 5, 0);
|
|
||||||
outb(0x1F0 + 7, 0xEC);
|
|
||||||
if (inb(0x1F0 + 7) == 0 || inb(0x1F0 + 1) != 0)
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MasterInterruptHandler(TrapFrame *)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void SlaveInterruptHandler(TrapFrame *)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
int DriverEntry()
|
|
||||||
{
|
|
||||||
RegisterInterruptHandler(14, MasterInterruptHandler);
|
|
||||||
RegisterInterruptHandler(15, SlaveInterruptHandler);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int DriverFinal()
|
|
||||||
{
|
|
||||||
UnregisterInterruptHandler(14, MasterInterruptHandler);
|
|
||||||
UnregisterInterruptHandler(15, SlaveInterruptHandler);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int DriverPanic()
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int DriverProbe()
|
|
||||||
{
|
|
||||||
if (!IsATAPresent())
|
|
||||||
return -ENODEV;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
DriverInfo("ata",
|
|
||||||
"Advanced Technology Attachment Driver",
|
|
||||||
"EnderIce2",
|
|
||||||
0, 0, 1,
|
|
||||||
"GPLv3");
|
|
14
Fennix Bootloader.code-workspace
Normal file
14
Fennix Bootloader.code-workspace
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"folders": [
|
||||||
|
{
|
||||||
|
"path": "./Bootloader"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"settings": {
|
||||||
|
"terminal.integrated.cwd": "../",
|
||||||
|
"debug.allowBreakpointsEverywhere": true,
|
||||||
|
"git.defaultBranchName": "master",
|
||||||
|
"git.openRepositoryInParentFolders": "always",
|
||||||
|
"C_Cpp.autoAddFileAssociations": false,
|
||||||
|
}
|
||||||
|
}
|
@ -7,9 +7,8 @@
|
|||||||
"settings": {
|
"settings": {
|
||||||
"terminal.integrated.cwd": "../",
|
"terminal.integrated.cwd": "../",
|
||||||
"debug.allowBreakpointsEverywhere": true,
|
"debug.allowBreakpointsEverywhere": true,
|
||||||
"git.alwaysSignOff": true,
|
|
||||||
"git.defaultBranchName": "master",
|
"git.defaultBranchName": "master",
|
||||||
"git.openRepositoryInParentFolders": "always",
|
"git.openRepositoryInParentFolders": "always",
|
||||||
"C_Cpp.autoAddFileAssociations": false
|
"C_Cpp.autoAddFileAssociations": false,
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -7,25 +7,25 @@
|
|||||||
"settings": {
|
"settings": {
|
||||||
"terminal.integrated.cwd": "../",
|
"terminal.integrated.cwd": "../",
|
||||||
"debug.allowBreakpointsEverywhere": true,
|
"debug.allowBreakpointsEverywhere": true,
|
||||||
"editor.tabCompletion": "on",
|
|
||||||
"diffEditor.codeLens": true,
|
|
||||||
"editor.quickSuggestionsDelay": 100,
|
|
||||||
"zenMode.hideLineNumbers": false,
|
|
||||||
"zenMode.hideActivityBar": false,
|
|
||||||
"zenMode.hideStatusBar": true,
|
|
||||||
"zenMode.centerLayout": true,
|
|
||||||
"zenMode.fullScreen": true,
|
|
||||||
"zenMode.restore": true,
|
|
||||||
"zenMode.silentNotifications": true,
|
|
||||||
"window.commandCenter": false,
|
|
||||||
"window.density.editorTabHeight": "default",
|
|
||||||
"editor.cursorBlinking": "blink",
|
|
||||||
"editor.cursorSmoothCaretAnimation": "on",
|
|
||||||
"editor.cursorStyle": "line",
|
|
||||||
"editor.cursorWidth": 2,
|
|
||||||
"git.alwaysSignOff": true,
|
|
||||||
"git.defaultBranchName": "master",
|
"git.defaultBranchName": "master",
|
||||||
"git.openRepositoryInParentFolders": "always",
|
"git.openRepositoryInParentFolders": "always",
|
||||||
"C_Cpp.autoAddFileAssociations": false
|
"C_Cpp.autoAddFileAssociations": false,
|
||||||
|
"conventionalCommits.scopes": [
|
||||||
|
"kernel/api",
|
||||||
|
"kernel/syscalls",
|
||||||
|
"vscode",
|
||||||
|
"kernel",
|
||||||
|
"kernel/pci",
|
||||||
|
"kernel/driver",
|
||||||
|
"kernel/drivers",
|
||||||
|
"kernel/elf",
|
||||||
|
"kernel/scheduler",
|
||||||
|
"kernel/tty",
|
||||||
|
"kernel/std",
|
||||||
|
"kernel/vfs",
|
||||||
|
"kernel/memory",
|
||||||
|
"kernel/efi",
|
||||||
|
"kernel/bootstrap"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -7,9 +7,20 @@
|
|||||||
"settings": {
|
"settings": {
|
||||||
"terminal.integrated.cwd": "../",
|
"terminal.integrated.cwd": "../",
|
||||||
"debug.allowBreakpointsEverywhere": true,
|
"debug.allowBreakpointsEverywhere": true,
|
||||||
"git.alwaysSignOff": true,
|
|
||||||
"git.defaultBranchName": "master",
|
"git.defaultBranchName": "master",
|
||||||
"git.openRepositoryInParentFolders": "always",
|
"git.openRepositoryInParentFolders": "always",
|
||||||
"C_Cpp.autoAddFileAssociations": false
|
"C_Cpp.autoAddFileAssociations": false,
|
||||||
|
"conventionalCommits.scopes": [
|
||||||
|
"userspace",
|
||||||
|
"userspace/libc",
|
||||||
|
"userspace/coreutils",
|
||||||
|
"userspace/apps",
|
||||||
|
"userspace/libs",
|
||||||
|
"userspace/apps/sys",
|
||||||
|
"userspace/apps/test",
|
||||||
|
"userspace/apps/usr",
|
||||||
|
"devcontainer",
|
||||||
|
"vscode"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -6,7 +6,6 @@
|
|||||||
],
|
],
|
||||||
"settings": {
|
"settings": {
|
||||||
"debug.allowBreakpointsEverywhere": true,
|
"debug.allowBreakpointsEverywhere": true,
|
||||||
"git.alwaysSignOff": true,
|
|
||||||
"git.defaultBranchName": "master",
|
"git.defaultBranchName": "master",
|
||||||
"git.openRepositoryInParentFolders": "always",
|
"git.openRepositoryInParentFolders": "always",
|
||||||
"C_Cpp.autoAddFileAssociations": false
|
"C_Cpp.autoAddFileAssociations": false
|
||||||
|
@ -6,9 +6,14 @@
|
|||||||
],
|
],
|
||||||
"settings": {
|
"settings": {
|
||||||
"debug.allowBreakpointsEverywhere": true,
|
"debug.allowBreakpointsEverywhere": true,
|
||||||
"git.alwaysSignOff": true,
|
|
||||||
"git.defaultBranchName": "master",
|
"git.defaultBranchName": "master",
|
||||||
"git.openRepositoryInParentFolders": "always",
|
"git.openRepositoryInParentFolders": "always",
|
||||||
"C_Cpp.autoAddFileAssociations": false
|
"C_Cpp.autoAddFileAssociations": false,
|
||||||
|
"conventionalCommits.scopes": [
|
||||||
|
"rootfs",
|
||||||
|
"tools",
|
||||||
|
"devcontainer",
|
||||||
|
"workspace"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
72
INSTALL.md
Normal file
72
INSTALL.md
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
# 🚀 Installation Guide
|
||||||
|
|
||||||
|
This guide will help you install Fennix on your system.
|
||||||
|
|
||||||
|
## 🛠️ Preparing the Environment
|
||||||
|
|
||||||
|
There are two ways to build the project:
|
||||||
|
|
||||||
|
1. **🐳 Use Dev Container (Recommended)**
|
||||||
|
* This is the easiest way to prepare the environment for building the project. But firstly, you need to install [Docker](https://docs.docker.com/get-docker/) and [Visual Studio Code](https://code.visualstudio.com/).
|
||||||
|
* After installing Docker and Visual Studio Code, you can open the project in Visual Studio Code and click on the "Reopen in Container" button.
|
||||||
|
* This will open the project in a Dev Container with all the required tools installed.
|
||||||
|
* If you encounter errors while the Dev Container is building, ensure the following are correctly configured:
|
||||||
|
* `/tmp/.X11-unix`
|
||||||
|
* Environment variable `XAUTHORITY`
|
||||||
|
* `/run/user/1000/pulse/native`
|
||||||
|
* **Note:** These configurations are only necessary if you plan to use QEMU inside the container.
|
||||||
|
2. **💻 Build the Project Locally**
|
||||||
|
* The instructions below will guide you through the process of building the project locally.
|
||||||
|
|
||||||
|
**NOTE:** You MUST have `autoconf 2.69` and `automake 1.15.1` versions installed on your system. A complete list of dependencies can be found in the [.devcontainer/Dockerfile](.devcontainer/Dockerfile) file.
|
||||||
|
|
||||||
|
Before building the project, you need to build the cross-compiler toolchain and QEMU.
|
||||||
|
You can do this by running the following command:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
make setup
|
||||||
|
```
|
||||||
|
|
||||||
|
This will clone, patch, and build the required tools for you.
|
||||||
|
|
||||||
|
Alternatively, if you wish to skip building QEMU, you can run `make setup-no-qemu`.
|
||||||
|
However, in this case, you will need to manually specify the path to the QEMU binary in the `config.mk` file.
|
||||||
|
|
||||||
|
## 🏗️ Building the Project
|
||||||
|
|
||||||
|
To build the project, run:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
make build
|
||||||
|
```
|
||||||
|
|
||||||
|
This will build the kernel, userspace, and drivers. The resulting ISO image will be `Fennix.iso`.
|
||||||
|
|
||||||
|
## 🚀 Running the OS
|
||||||
|
|
||||||
|
To run the OS, execute:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
make run
|
||||||
|
```
|
||||||
|
|
||||||
|
The `run` target will automatically build the project if it hasn't been built yet.
|
||||||
|
|
||||||
|
## ⚙️ Additional Configuration
|
||||||
|
|
||||||
|
You can customize the project by editing the `config.mk` file.
|
||||||
|
|
||||||
|
## 🧪 Debugging
|
||||||
|
|
||||||
|
If you use Visual Studio Code, you can press `F5` to start debugging the OS.
|
||||||
|
The configuration is already set up for you.
|
||||||
|
|
||||||
|
Alternatively, you can run the following command to start debugging:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
make debug
|
||||||
|
```
|
||||||
|
|
||||||
|
This will start QEMU in debug mode, allowing you to connect to it using GDB.
|
||||||
|
|
||||||
|
The GDB FIFO file is located at `/tmp/gdb-fennix`.
|
17
Kernel/.editorconfig
Normal file
17
Kernel/.editorconfig
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
# EditorConfig is awesome: https://editorconfig.org
|
||||||
|
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
end_of_line = lf
|
||||||
|
insert_final_newline = true
|
||||||
|
indent_style = tab
|
||||||
|
indent_size = 4
|
||||||
|
|
||||||
|
[*.py]
|
||||||
|
indent_size = 4
|
||||||
|
indent_style = space
|
||||||
|
|
||||||
|
[Makefile]
|
||||||
|
indent_style = tab
|
@ -1,91 +0,0 @@
|
|||||||
# Usage: add-symbol-file-all <filename> [<offset>]
|
|
||||||
# remove-symbol-file-all <filename> [<offset>]
|
|
||||||
#
|
|
||||||
# Credit: https://stackoverflow.com/a/33087762/9352057
|
|
||||||
# CC BY-SA 4.0
|
|
||||||
|
|
||||||
python
|
|
||||||
import subprocess
|
|
||||||
import re
|
|
||||||
|
|
||||||
def relocatesections(filename, addr):
|
|
||||||
p = subprocess.Popen(["readelf", "-S", filename], stdout = subprocess.PIPE)
|
|
||||||
|
|
||||||
sections = []
|
|
||||||
textaddr = '0'
|
|
||||||
for line in p.stdout.readlines():
|
|
||||||
line = line.decode("utf-8").strip()
|
|
||||||
if not line.startswith('[') or line.startswith('[Nr]'):
|
|
||||||
continue
|
|
||||||
|
|
||||||
line = re.sub(r' +', ' ', line)
|
|
||||||
line = re.sub(r'\[ *(\d+)\]', '\g<1>', line)
|
|
||||||
fieldsvalue = line.split(' ')
|
|
||||||
fieldsname = ['number', 'name', 'type', 'addr', 'offset', 'size', 'entsize', 'flags', 'link', 'info', 'addralign']
|
|
||||||
sec = dict(zip(fieldsname, fieldsvalue))
|
|
||||||
|
|
||||||
if sec['number'] == '0':
|
|
||||||
continue
|
|
||||||
|
|
||||||
sections.append(sec)
|
|
||||||
|
|
||||||
if sec['name'] == '.text':
|
|
||||||
textaddr = sec['addr']
|
|
||||||
|
|
||||||
return (textaddr, sections)
|
|
||||||
|
|
||||||
|
|
||||||
class AddSymbolFileAll(gdb.Command):
|
|
||||||
"""The right version for add-symbol-file"""
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
super(AddSymbolFileAll, self).__init__("add-symbol-file-all", gdb.COMMAND_USER)
|
|
||||||
self.dont_repeat()
|
|
||||||
|
|
||||||
def invoke(self, arg, from_tty):
|
|
||||||
argv = gdb.string_to_argv(arg)
|
|
||||||
filename = argv[0]
|
|
||||||
|
|
||||||
if len(argv) > 1:
|
|
||||||
offset = int(str(gdb.parse_and_eval(argv[1])), 0)
|
|
||||||
else:
|
|
||||||
offset = 0
|
|
||||||
|
|
||||||
(textaddr, sections) = relocatesections(filename, offset)
|
|
||||||
|
|
||||||
cmd = "add-symbol-file %s 0x%08x" % (filename, int(textaddr, 16) + offset)
|
|
||||||
|
|
||||||
for s in sections:
|
|
||||||
addr = int(s['addr'], 16)
|
|
||||||
if s['name'] == '.text' or addr == 0:
|
|
||||||
continue
|
|
||||||
|
|
||||||
cmd += " -s %s 0x%08x" % (s['name'], addr + offset)
|
|
||||||
|
|
||||||
gdb.execute(cmd)
|
|
||||||
|
|
||||||
class RemoveSymbolFileAll(gdb.Command):
|
|
||||||
"""The right version for remove-symbol-file"""
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
super(RemoveSymbolFileAll, self).__init__("remove-symbol-file-all", gdb.COMMAND_USER)
|
|
||||||
self.dont_repeat()
|
|
||||||
|
|
||||||
def invoke(self, arg, from_tty):
|
|
||||||
argv = gdb.string_to_argv(arg)
|
|
||||||
filename = argv[0]
|
|
||||||
|
|
||||||
if len(argv) > 1:
|
|
||||||
offset = int(str(gdb.parse_and_eval(argv[1])), 0)
|
|
||||||
else:
|
|
||||||
offset = 0
|
|
||||||
|
|
||||||
(textaddr, _) = relocatesections(filename, offset)
|
|
||||||
|
|
||||||
cmd = "remove-symbol-file -a 0x%08x" % (int(textaddr, 16) + offset)
|
|
||||||
gdb.execute(cmd)
|
|
||||||
|
|
||||||
|
|
||||||
AddSymbolFileAll()
|
|
||||||
RemoveSymbolFileAll()
|
|
||||||
end
|
|
59
Kernel/.vscode/c_cpp_properties.json
vendored
59
Kernel/.vscode/c_cpp_properties.json
vendored
@ -137,6 +137,33 @@
|
|||||||
"-nostdinc++"
|
"-nostdinc++"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "Fennix Arm (Linux, GCC, debug)",
|
||||||
|
"includePath": [
|
||||||
|
"${workspaceFolder}/include",
|
||||||
|
"${workspaceFolder}/include/**",
|
||||||
|
"${workspaceFolder}/include_std",
|
||||||
|
"${workspaceFolder}/include_std/**",
|
||||||
|
"${workspaceFolder}/arch/aarch64/include"
|
||||||
|
],
|
||||||
|
"forcedInclude": [
|
||||||
|
"${workspaceFolder}/.vscode/preinclude.h"
|
||||||
|
],
|
||||||
|
"defines": [
|
||||||
|
"DEBUG=\"1\""
|
||||||
|
],
|
||||||
|
"compilerPath": "${workspaceFolder}/../tools/cross/bin/arm-fennix-gcc",
|
||||||
|
"cStandard": "c17",
|
||||||
|
"cppStandard": "c++20",
|
||||||
|
"intelliSenseMode": "linux-gcc-arm",
|
||||||
|
"configurationProvider": "ms-vscode.makefile-tools",
|
||||||
|
"compilerArgs": [
|
||||||
|
// VSCode flags
|
||||||
|
"-ffreestanding",
|
||||||
|
"-nostdinc",
|
||||||
|
"-nostdinc++"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "Fennix Aarch64 (Linux, GCC, debug)",
|
"name": "Fennix Aarch64 (Linux, GCC, debug)",
|
||||||
"includePath": [
|
"includePath": [
|
||||||
@ -158,38 +185,6 @@
|
|||||||
"intelliSenseMode": "linux-gcc-arm64",
|
"intelliSenseMode": "linux-gcc-arm64",
|
||||||
"configurationProvider": "ms-vscode.makefile-tools",
|
"configurationProvider": "ms-vscode.makefile-tools",
|
||||||
"compilerArgs": [
|
"compilerArgs": [
|
||||||
// Compiler flags
|
|
||||||
"-pipe",
|
|
||||||
"-fno-builtin",
|
|
||||||
"-msoft-float",
|
|
||||||
"-fPIC",
|
|
||||||
"-Wstack-protector",
|
|
||||||
"-fcoroutines",
|
|
||||||
// Warnings
|
|
||||||
"-Wall",
|
|
||||||
"-Wextra",
|
|
||||||
"-Wfloat-equal",
|
|
||||||
"-Wpointer-arith",
|
|
||||||
"-Wcast-align",
|
|
||||||
"-Wredundant-decls",
|
|
||||||
"-Winit-self",
|
|
||||||
"-Wswitch-default",
|
|
||||||
"-Wstrict-overflow=5",
|
|
||||||
"-Wconversion",
|
|
||||||
// C++ flags
|
|
||||||
"-fno-rtti",
|
|
||||||
"-fno-exceptions",
|
|
||||||
// Linker flags
|
|
||||||
"-T${workspaceFolder}/arch/aarch64/linker.ld",
|
|
||||||
"-fPIC",
|
|
||||||
// Debug flags
|
|
||||||
"-ggdb3",
|
|
||||||
"-O0",
|
|
||||||
"-fdiagnostics-color=always",
|
|
||||||
"-fverbose-asm",
|
|
||||||
"-fstack-usage",
|
|
||||||
"-fstack-check",
|
|
||||||
"-fsanitize=undefined",
|
|
||||||
// VSCode flags
|
// VSCode flags
|
||||||
"-ffreestanding",
|
"-ffreestanding",
|
||||||
"-nostdinc",
|
"-nostdinc",
|
||||||
|
16
Kernel/.vscode/extensions.json
vendored
Normal file
16
Kernel/.vscode/extensions.json
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"recommendations": [
|
||||||
|
"ms-vscode.cpptools",
|
||||||
|
"maziac.asm-code-lens",
|
||||||
|
"editorconfig.editorconfig",
|
||||||
|
"vivaxy.vscode-conventional-commits",
|
||||||
|
"ms-vscode.hexeditor",
|
||||||
|
"webfreak.debug",
|
||||||
|
"ibm.output-colorizer",
|
||||||
|
"gruntfuggly.todo-tree",
|
||||||
|
"naumovs.color-highlight",
|
||||||
|
"seven1bit.vscode-ext-ansi-color-highlight",
|
||||||
|
"jeff-hykin.better-cpp-syntax",
|
||||||
|
"aaron-bond.better-comments"
|
||||||
|
]
|
||||||
|
}
|
2
Kernel/.vscode/preinclude.h
vendored
2
Kernel/.vscode/preinclude.h
vendored
@ -9,6 +9,6 @@
|
|||||||
#define __kernel__ 1
|
#define __kernel__ 1
|
||||||
#define KERNEL_NAME "Fennix"
|
#define KERNEL_NAME "Fennix"
|
||||||
#define KERNEL_ARCH "amd64"
|
#define KERNEL_ARCH "amd64"
|
||||||
#define KERNEL_VERSION "1.0"
|
#define KERNEL_VERSION "1.0.0"
|
||||||
#define GIT_COMMIT "0000000000000000000000000000000000000000"
|
#define GIT_COMMIT "0000000000000000000000000000000000000000"
|
||||||
#define GIT_COMMIT_SHORT "0000000"
|
#define GIT_COMMIT_SHORT "0000000"
|
||||||
|
@ -6,26 +6,18 @@ GIT_COMMIT_SHORT = $(shell git rev-parse --short HEAD)
|
|||||||
HEADERS := $(sort $(dir $(wildcard ./include/*))) $(sort $(dir $(wildcard ./include_std/*)))
|
HEADERS := $(sort $(dir $(wildcard ./include/*))) $(sort $(dir $(wildcard ./include_std/*)))
|
||||||
INCLUDE_DIR = -I./include -I./include_std
|
INCLUDE_DIR = -I./include -I./include_std
|
||||||
|
|
||||||
BMP_SOURCES := $(shell find ./ -type f -name '*.bmp')
|
define find-sources
|
||||||
PSF_SOURCES := $(shell find ./ -type f -name '*.psf')
|
$(shell find ./ -type f -name '$1' $(shell echo $(foreach arch,$(filter-out $(OSARCH),$(AVAILABLE_ARCHS)), -not -path \"./arch/$(arch)/*\")) -print0 | xargs -0)
|
||||||
ifeq ($(OSARCH), amd64)
|
endef
|
||||||
S_SOURCES := $(shell find ./ -type f -name '*.S' -not -path "./arch/i386/*" -not -path "./arch/aarch64/*")
|
|
||||||
s_SOURCES := $(shell find ./ -type f -name '*.s' -not -path "./arch/i386/*" -not -path "./arch/aarch64/*")
|
|
||||||
C_SOURCES := $(shell find ./ -type f -name '*.c' -not -path "./arch/i386/*" -not -path "./arch/aarch64/*")
|
|
||||||
CXX_SOURCES := $(shell find ./ -type f -name '*.cpp' -not -path "./arch/i386/*" -not -path "./arch/aarch64/*")
|
|
||||||
else ifeq ($(OSARCH), i386)
|
|
||||||
S_SOURCES := $(shell find ./ -type f -name '*.S' -not -path "./arch/amd64/*" -not -path "./arch/aarch64/*")
|
|
||||||
s_SOURCES := $(shell find ./ -type f -name '*.s' -not -path "./arch/amd64/*" -not -path "./arch/aarch64/*")
|
|
||||||
C_SOURCES := $(shell find ./ -type f -name '*.c' -not -path "./arch/amd64/*" -not -path "./arch/aarch64/*")
|
|
||||||
CXX_SOURCES := $(shell find ./ -type f -name '*.cpp' -not -path "./arch/amd64/*" -not -path "./arch/aarch64/*")
|
|
||||||
else ifeq ($(OSARCH), aarch64)
|
|
||||||
S_SOURCES := $(shell find ./ -type f -name '*.S' -not -path "./arch/amd64/*" -not -path "./arch/i386/*")
|
|
||||||
s_SOURCES := $(shell find ./ -type f -name '*.s' -not -path "./arch/amd64/*" -not -path "./arch/i386/*")
|
|
||||||
C_SOURCES := $(shell find ./ -type f -name '*.c' -not -path "./arch/amd64/*" -not -path "./arch/i386/*")
|
|
||||||
CXX_SOURCES := $(shell find ./ -type f -name '*.cpp' -not -path "./arch/amd64/*" -not -path "./arch/i386/*")
|
|
||||||
endif # OSARCH
|
|
||||||
|
|
||||||
OBJ = $(BMP_SOURCES:.bmp=.o) $(PSF_SOURCES:.psf=.o) $(s_SOURCES:.s=.o) $(S_SOURCES:.S=.o) $(C_SOURCES:.c=.o) $(CXX_SOURCES:.cpp=.o)
|
PNG_SOURCES := $(call find-sources,*.png)
|
||||||
|
PSF_SOURCES := $(call find-sources,*.psf)
|
||||||
|
S_SOURCES := $(call find-sources,*.S)
|
||||||
|
s_SOURCES := $(call find-sources,*.s)
|
||||||
|
C_SOURCES := $(call find-sources,*.c)
|
||||||
|
CXX_SOURCES := $(call find-sources,*.cpp)
|
||||||
|
|
||||||
|
OBJ = $(PNG_SOURCES:.png=.o) $(PSF_SOURCES:.psf=.o) $(s_SOURCES:.s=.o) $(S_SOURCES:.S=.o) $(C_SOURCES:.c=.o) $(CXX_SOURCES:.cpp=.o)
|
||||||
STACK_USAGE_OBJ = $(C_SOURCES:.c=.su) $(CXX_SOURCES:.cpp=.su)
|
STACK_USAGE_OBJ = $(C_SOURCES:.c=.su) $(CXX_SOURCES:.cpp=.su)
|
||||||
GCNO_OBJ = $(C_SOURCES:.c=.gcno) $(CXX_SOURCES:.cpp=.gcno)
|
GCNO_OBJ = $(C_SOURCES:.c=.gcno) $(CXX_SOURCES:.cpp=.gcno)
|
||||||
|
|
||||||
@ -40,7 +32,7 @@ WARNCFLAG = -Wall -Wextra \
|
|||||||
-Wfloat-equal -Wpointer-arith -Wcast-align \
|
-Wfloat-equal -Wpointer-arith -Wcast-align \
|
||||||
-Wredundant-decls -Winit-self -Wswitch-default \
|
-Wredundant-decls -Winit-self -Wswitch-default \
|
||||||
-Wstrict-overflow=5 -Wno-error=cpp -Werror \
|
-Wstrict-overflow=5 -Wno-error=cpp -Werror \
|
||||||
-Wno-unused-parameter
|
-Wno-unused-parameter -Wno-error=format
|
||||||
|
|
||||||
CFLAG_STACK_PROTECTOR := -fstack-protector-all
|
CFLAG_STACK_PROTECTOR := -fstack-protector-all
|
||||||
|
|
||||||
@ -53,16 +45,20 @@ CFLAGS := \
|
|||||||
-DKERNEL_VERSION='"$(KERNEL_VERSION)"' \
|
-DKERNEL_VERSION='"$(KERNEL_VERSION)"' \
|
||||||
-DGIT_COMMIT='"$(GIT_COMMIT)"' \
|
-DGIT_COMMIT='"$(GIT_COMMIT)"' \
|
||||||
-DGIT_COMMIT_SHORT='"$(GIT_COMMIT_SHORT)"' \
|
-DGIT_COMMIT_SHORT='"$(GIT_COMMIT_SHORT)"' \
|
||||||
-fno-pic -fno-pie -mno-red-zone -fno-builtin
|
-fno-pic -fno-pie -fno-builtin
|
||||||
|
|
||||||
ifeq ($(OSARCH), amd64)
|
ifeq ($(OSARCH), amd64)
|
||||||
CFLAGS += -march=core2 -mcmodel=kernel -m64
|
CFLAGS += -march=core2 -mcmodel=kernel -m64 -mno-red-zone
|
||||||
LDFLAGS += -Tarch/amd64/linker.ld
|
LDFLAGS += -Tarch/amd64/linker.ld
|
||||||
else ifeq ($(OSARCH), i386)
|
else ifeq ($(OSARCH), i386)
|
||||||
CFLAGS += -march=pentium -m32
|
CFLAGS += -march=pentium -m32 -mno-red-zone
|
||||||
LDFLAGS += -Tarch/i386/linker.ld
|
LDFLAGS += -Tarch/i386/linker.ld
|
||||||
|
else ifeq ($(OSARCH), arm)
|
||||||
|
CFLAGS += -march=armv7-a -mfloat-abi=softfp -ggdb3
|
||||||
|
LDFLAGS += -Tarch/arm/linker.ld
|
||||||
|
WARNCFLAG += -w
|
||||||
else ifeq ($(OSARCH), aarch64)
|
else ifeq ($(OSARCH), aarch64)
|
||||||
CFLAGS +=
|
CFLAGS += -march=armv9.4-a -mtune=cortex-a72 -mlittle-endian -mcmodel=large
|
||||||
LDFLAGS += -Tarch/aarch64/linker.ld
|
LDFLAGS += -Tarch/aarch64/linker.ld
|
||||||
endif # OSARCH
|
endif # OSARCH
|
||||||
|
|
||||||
@ -72,11 +68,15 @@ ifeq ($(DEBUG), 1)
|
|||||||
# CFLAGS += -pg
|
# CFLAGS += -pg
|
||||||
# CFLAGS += -finstrument-functions
|
# CFLAGS += -finstrument-functions
|
||||||
CFLAGS += -DDEBUG -ggdb3 -O0 -fdiagnostics-color=always -fstack-usage -fsanitize=undefined
|
CFLAGS += -DDEBUG -ggdb3 -O0 -fdiagnostics-color=always -fstack-usage -fsanitize=undefined
|
||||||
|
CXXFLAGS += -fdiagnostics-all-candidates
|
||||||
ifeq ($(OSARCH), amd64)
|
ifeq ($(OSARCH), amd64)
|
||||||
CFLAGS += -fverbose-asm
|
CFLAGS += -fverbose-asm
|
||||||
endif # amd64
|
endif # amd64
|
||||||
ifneq ($(OSARCH), aarch64)
|
ifeq ($(OSARCH), arm)
|
||||||
CFLAGS += -fstack-check
|
CFLAGS += -fstack-check -fverbose-asm
|
||||||
|
endif # arm
|
||||||
|
ifeq ($(OSARCH), aarch64)
|
||||||
|
CFLAGS += -fstack-check -fverbose-asm
|
||||||
endif # aarch64
|
endif # aarch64
|
||||||
LDFLAGS += -ggdb3 -O0
|
LDFLAGS += -ggdb3 -O0
|
||||||
ASFLAGS += -g --gstabs+ --gdwarf-5 -D
|
ASFLAGS += -g --gstabs+ --gdwarf-5 -D
|
||||||
@ -112,7 +112,7 @@ $(KERNEL_FILENAME): $(OBJ)
|
|||||||
# https://gcc.gnu.org/projects/cxx-status.html
|
# https://gcc.gnu.org/projects/cxx-status.html
|
||||||
%.o: %.cpp $(HEADERS)
|
%.o: %.cpp $(HEADERS)
|
||||||
$(info Compiling $<)
|
$(info Compiling $<)
|
||||||
$(__CONF_CXX) $(CFLAGS) -fcoroutines $(CFLAG_STACK_PROTECTOR) $(WARNCFLAG) -std=c++20 -c $< -o $@ -fno-rtti
|
$(__CONF_CXX) $(CFLAGS) $(CXXFLAGS) -fcoroutines $(CFLAG_STACK_PROTECTOR) $(WARNCFLAG) -std=c++20 -c $< -o $@ -fno-rtti
|
||||||
|
|
||||||
%.o: %.S
|
%.o: %.S
|
||||||
$(info Compiling $<)
|
$(info Compiling $<)
|
||||||
@ -127,16 +127,20 @@ ifeq ($(OSARCH), amd64)
|
|||||||
$(__CONF_OBJCOPY) -O elf64-x86-64 -I binary $< $@
|
$(__CONF_OBJCOPY) -O elf64-x86-64 -I binary $< $@
|
||||||
else ifeq ($(OSARCH), i386)
|
else ifeq ($(OSARCH), i386)
|
||||||
$(__CONF_OBJCOPY) -O elf32-i386 -I binary $< $@
|
$(__CONF_OBJCOPY) -O elf32-i386 -I binary $< $@
|
||||||
|
else ifeq ($(OSARCH), arm)
|
||||||
|
$(__CONF_OBJCOPY) -O elf32-littlearm -I binary $< $@
|
||||||
else ifeq ($(OSARCH), aarch64)
|
else ifeq ($(OSARCH), aarch64)
|
||||||
$(__CONF_OBJCOPY) -O elf64-littleaarch64 -I binary $< $@
|
$(__CONF_OBJCOPY) -O elf64-littleaarch64 -I binary $< $@
|
||||||
endif
|
endif
|
||||||
$(__CONF_NM) $@
|
$(__CONF_NM) $@
|
||||||
|
|
||||||
%.o: %.bmp
|
%.o: %.png
|
||||||
ifeq ($(OSARCH), amd64)
|
ifeq ($(OSARCH), amd64)
|
||||||
$(__CONF_OBJCOPY) -O elf64-x86-64 -I binary $< $@
|
$(__CONF_OBJCOPY) -O elf64-x86-64 -I binary $< $@
|
||||||
else ifeq ($(OSARCH), i386)
|
else ifeq ($(OSARCH), i386)
|
||||||
$(__CONF_OBJCOPY) -O elf32-i386 -I binary $< $@
|
$(__CONF_OBJCOPY) -O elf32-i386 -I binary $< $@
|
||||||
|
else ifeq ($(OSARCH), arm)
|
||||||
|
$(__CONF_OBJCOPY) -O elf32-littlearm -I binary $< $@
|
||||||
else ifeq ($(OSARCH), aarch64)
|
else ifeq ($(OSARCH), aarch64)
|
||||||
$(__CONF_OBJCOPY) -O elf64-littlearch64 -I binary $< $@
|
$(__CONF_OBJCOPY) -O elf64-littlearch64 -I binary $< $@
|
||||||
endif
|
endif
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
- [ ] ~~Do not map the entire memory. Map only the needed memory address at allocation time.~~ (we just copy the pages for userland, see `Fork()` inside [core/memory/page_table.cpp](core/memory/page_table.cpp))
|
- [ ] ~~Do not map the entire memory. Map only the needed memory address at allocation time.~~ (we just copy the pages for userland, see `Fork()` inside [core/memory/page_table.cpp](core/memory/page_table.cpp))
|
||||||
- [ ] Implementation of logging (beside serial) with log rotation.
|
- [ ] Implementation of logging (beside serial) with log rotation.
|
||||||
- [x] Implement a better task manager. (replace struct P/TCB with classes)
|
- [x] Implement a better task manager. (replace struct P/TCB with classes)
|
||||||
- [ ] Rewrite virtual file system.
|
- [x] Rewrite virtual file system.
|
||||||
- [ ] Colors in crash screen are not following the kernel color scheme.
|
- [ ] Colors in crash screen are not following the kernel color scheme.
|
||||||
- [x] ~~Find a way to add intrinsics.~~ (not feasible, use inline assembly)
|
- [x] ~~Find a way to add intrinsics.~~ (not feasible, use inline assembly)
|
||||||
- [ ] Rework PSF1 font loader.
|
- [ ] Rework PSF1 font loader.
|
||||||
|
@ -1,36 +0,0 @@
|
|||||||
/* Based on this tutorial:
|
|
||||||
https://github.com/s-matyukevich/raspberry-pi-os */
|
|
||||||
|
|
||||||
.section ".text.boot", "a"
|
|
||||||
|
|
||||||
.extern _bss_start
|
|
||||||
.extern _bss_end
|
|
||||||
|
|
||||||
.extern arm64Entry
|
|
||||||
memzero:
|
|
||||||
str xzr, [x0], #8
|
|
||||||
subs x1, x1, #8
|
|
||||||
b.gt memzero
|
|
||||||
ret
|
|
||||||
|
|
||||||
.global _start
|
|
||||||
_start:
|
|
||||||
mrs x0, mpidr_el1
|
|
||||||
and x0, x0, #0xFF
|
|
||||||
cbz x0, _start2
|
|
||||||
b CPU_Loop
|
|
||||||
|
|
||||||
_start2:
|
|
||||||
adr x0, _bss_start
|
|
||||||
adr x1, _bss_end
|
|
||||||
sub x1, x1, x0
|
|
||||||
bl memzero
|
|
||||||
mov sp, #0x200000
|
|
||||||
bl arm64Entry
|
|
||||||
|
|
||||||
Halt:
|
|
||||||
wfe
|
|
||||||
b Halt
|
|
||||||
|
|
||||||
CPU_Loop:
|
|
||||||
b CPU_Loop
|
|
49
Kernel/arch/aarch64/bootstrap/raspi/boot.S
Normal file
49
Kernel/arch/aarch64/bootstrap/raspi/boot.S
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Fennix Kernel.
|
||||||
|
|
||||||
|
Fennix Kernel is free software: you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation, either version 3 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
Fennix Kernel is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.section ".bootstrap.boot", "a"
|
||||||
|
|
||||||
|
.extern _kernel_bss_start
|
||||||
|
.extern _kernel_bss_end
|
||||||
|
.extern _kernel_bss_size
|
||||||
|
|
||||||
|
.global _start
|
||||||
|
_start:
|
||||||
|
/* Keep only the main core */
|
||||||
|
mrs x1, mpidr_el1
|
||||||
|
and x1, x1, #3
|
||||||
|
cbz x1, 2f
|
||||||
|
|
||||||
|
/* Halt */
|
||||||
|
1: wfe
|
||||||
|
b 1b
|
||||||
|
|
||||||
|
/* Initialize the stack */
|
||||||
|
2: ldr x1, =_start
|
||||||
|
mov sp, x1
|
||||||
|
|
||||||
|
/* Clear the BSS */
|
||||||
|
ldr x1, =_kernel_bss_start
|
||||||
|
ldr w2, =_kernel_bss_size
|
||||||
|
3: cbz w2, 4f
|
||||||
|
str xzr, [x1], #8
|
||||||
|
sub w2, w2, #1
|
||||||
|
cbnz w2, 3b
|
||||||
|
|
||||||
|
/* Start the kernel */
|
||||||
|
4: bl _aarch64_start
|
||||||
|
b 1b
|
44
Kernel/arch/aarch64/bootstrap/raspi/init.cpp
Normal file
44
Kernel/arch/aarch64/bootstrap/raspi/init.cpp
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Fennix Kernel.
|
||||||
|
|
||||||
|
Fennix Kernel is free software: you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation, either version 3 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
Fennix Kernel is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <types.h>
|
||||||
|
#include <cpu.hpp>
|
||||||
|
|
||||||
|
#include "../../../../kernel.h"
|
||||||
|
|
||||||
|
using namespace CPU::aarch64;
|
||||||
|
|
||||||
|
extern "C" __attribute__((section(".bootstrap.text"))) void _aarch64_start(uint64_t dtb_ptr32, uint64_t x1, uint64_t x2, uint64_t x3)
|
||||||
|
{
|
||||||
|
MIDR_EL1 reg;
|
||||||
|
asmv("mrs %x0, midr_el1" : "=r"(reg.raw));
|
||||||
|
|
||||||
|
switch (reg.PartNum)
|
||||||
|
{
|
||||||
|
case 0xB76: /* Raspberry Pi 1 */
|
||||||
|
case 0xC07: /* Raspberry Pi 2 */
|
||||||
|
default: /* Unknown */
|
||||||
|
CPU::Stop();
|
||||||
|
case 0xD03: /* Raspberry Pi 3 */
|
||||||
|
break;
|
||||||
|
case 0xD08: /* Raspberry Pi 4 */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
BootInfo *info = nullptr;
|
||||||
|
Entry(info);
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user