mirror of
https://github.com/EnderIce2/Fennix.git
synced 2025-07-01 02:19:15 +00:00
Compare commits
412 Commits
04edfd46bb
...
master
Author | SHA1 | Date | |
---|---|---|---|
a047edc97d
|
|||
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
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Cache cross Folder
|
||||
id: cache-cross
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: tools/cross
|
||||
key: ${{ runner.os }}-cross-${{ hashFiles('tools/Makefile') }}
|
||||
|
||||
- name: Update System
|
||||
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'
|
||||
- name: Prepare Environment for Dev Container
|
||||
run: |
|
||||
if [ "$(autoconf --version | head -n 1 | awk '{print $NF}')" != "2.69" ]; then
|
||||
echo "Autoconf version is not 2.69, performing additional steps..."
|
||||
wget https://launchpad.net/ubuntu/+archive/primary/+files/autoconf_2.69-11.1_all.deb
|
||||
sudo dpkg --force-all -i ./autoconf_2.69-11.1_all.deb
|
||||
sudo mkdir -p /tmp/.X11-unix
|
||||
sudo mkdir -p /run/user/1000/pulse
|
||||
sudo touch /run/user/1000/pulse/native
|
||||
|
||||
- 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
|
||||
|
||||
- name: Check automake
|
||||
if: steps.cache-cross.outputs.cache-hit != 'true'
|
||||
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
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
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: |
|
||||
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 Drivers prepare
|
||||
make --quiet -C Userspace prepare
|
||||
make --quiet -C Kernel prepare
|
||||
make --quiet prepare
|
||||
|
||||
- name: Cache cross Folder
|
||||
- name: Cache cross
|
||||
id: cache-cross
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: tools/cross
|
||||
key: ${{ runner.os }}-cross-${{ hashFiles('tools/Makefile') }}
|
||||
|
||||
- name: Configure config.mk
|
||||
run: sed -i 's/.*OSARCH = .*/OSARCH = amd64/' ./config.mk && cat config.mk | grep OSARCH
|
||||
|
||||
- name: Compile Debug and Release ISO
|
||||
- name: Build OS
|
||||
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
|
||||
make build_userspace
|
||||
make build_drivers
|
||||
make build_kernel
|
||||
make build_userspace
|
||||
|
||||
- name: Upload Artifact (Fennix-debug.iso)
|
||||
uses: actions/upload-artifact@v3
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v3
|
||||
with:
|
||||
name: Fennix-amd64-debug
|
||||
path: Fennix-debug.iso
|
||||
category: "/language:${{matrix.language}}"
|
||||
|
||||
- name: Upload Artifact (Fennix-release.iso)
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: Fennix-amd64-release
|
||||
path: Fennix-release.iso
|
||||
|
||||
compile32:
|
||||
name: Build i386
|
||||
compile:
|
||||
name: Build OS
|
||||
runs-on: ubuntu-latest
|
||||
needs: [buildcompiler]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- 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
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Cache cross Folder
|
||||
id: cache-cross
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: tools/cross
|
||||
key: ${{ runner.os }}-cross-${{ hashFiles('tools/Makefile') }}
|
||||
|
||||
- name: Configure config.mk
|
||||
run: sed -i 's/.*OSARCH = .*/OSARCH = i386/' ./config.mk && cat config.mk | grep OSARCH
|
||||
|
||||
- name: Compile Debug and Release ISO
|
||||
- name: Prepare Environment for Dev Container
|
||||
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
|
||||
sudo mkdir -p /tmp/.X11-unix
|
||||
sudo mkdir -p /run/user/1000/pulse
|
||||
sudo touch /run/user/1000/pulse/native
|
||||
|
||||
- name: Upload Artifact (Fennix-debug.iso)
|
||||
uses: actions/upload-artifact@v3
|
||||
- name: Build AMD64 Debug
|
||||
if: always()
|
||||
uses: devcontainers/ci@v0.3
|
||||
with:
|
||||
name: Fennix-i386-debug
|
||||
path: Fennix-debug.iso
|
||||
push: never
|
||||
runCmd: /usr/bin/make __ci-amd64-debug
|
||||
|
||||
- name: Upload Artifact (Fennix-release.iso)
|
||||
uses: actions/upload-artifact@v3
|
||||
- name: Build AMD64 Release
|
||||
if: always()
|
||||
uses: devcontainers/ci@v0.3
|
||||
with:
|
||||
name: Fennix-i386-release
|
||||
path: Fennix-release.iso
|
||||
push: never
|
||||
runCmd: /usr/bin/make __ci-amd64-release
|
||||
|
||||
compilearm64:
|
||||
name: Build aarch64
|
||||
- name: Build i386 Debug
|
||||
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
|
||||
needs: [buildcompiler]
|
||||
needs: [compile]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
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: Download All Builds
|
||||
uses: actions/download-artifact@v4
|
||||
|
||||
- name: Cache cross Folder
|
||||
id: cache-cross
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: tools/cross
|
||||
key: ${{ runner.os }}-cross-${{ hashFiles('tools/Makefile') }}
|
||||
- name: Update Nightly
|
||||
run: gh release upload nightly artifacts/* -R ${{github.repository}} --clobber
|
||||
|
||||
- name: Configure config.mk
|
||||
run: sed -i 's/.*OSARCH = .*/OSARCH = aarch64/' ./config.mk && cat config.mk | grep OSARCH
|
||||
|
||||
- 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
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
|
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
|
||||
initrd_tmp_data
|
||||
initrd/usr/include/*
|
||||
!initrd/usr/include/.gitkeep
|
||||
tools/*
|
||||
!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
|
||||
artifacts
|
||||
tmp_rootfs
|
||||
rootfs/usr/include/*
|
||||
!rootfs/usr/include/.gitkeep
|
||||
doxygen-doc
|
||||
initrd.tar
|
||||
rootfs.tar.gz
|
||||
.dccache
|
||||
*.log
|
||||
*.log.*
|
||||
|
130
.vscode/launch.json
vendored
130
.vscode/launch.json
vendored
@ -2,55 +2,141 @@
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Launch QEMU & debug the kernel",
|
||||
"name": "Debug Kernel (x64)",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/../Kernel/fennix.elf",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"args": [],
|
||||
"targetArchitecture": "x64",
|
||||
"MIMode": "gdb",
|
||||
"miDebuggerServerAddress": "/tmp/gdb-fennix",
|
||||
"miDebuggerPath": "${workspaceFolder}/../tools/cross/bin/x86_64-fennix-gdb",
|
||||
"miDebuggerArgs": "",
|
||||
"externalConsole": false,
|
||||
"additionalSOLibSearchPath": "${workspaceFolder}",
|
||||
"internalConsoleOptions": "neverOpen",
|
||||
"customLaunchSetupCommands": [
|
||||
// {
|
||||
// "text": "target remote localhost:1234",
|
||||
// "description": "Connect to QEMU remote debugger"
|
||||
// }
|
||||
],
|
||||
"setupCommands": [
|
||||
{
|
||||
"description": "Enable pretty-printing for gdb",
|
||||
"text": "-enable-pretty-printing",
|
||||
"ignoreFailures": true
|
||||
},
|
||||
{
|
||||
"text": "set breakpoint pending on",
|
||||
"description": "Make breakpoint pending on future shared library load."
|
||||
},
|
||||
{
|
||||
"text": "file ${workspaceFolder}/../Kernel/fennix.elf",
|
||||
"description": "Load binary"
|
||||
"text": "add-symbol-file ${workspaceFolder}/../tmp_rootfs/bin/utest",
|
||||
"description": "/bin/utest (0x00400000)",
|
||||
"ignoreFailures": true
|
||||
},
|
||||
{
|
||||
"text": "add-symbol-file ${workspaceFolder}/../initrd_tmp_data/bin/utest",
|
||||
"description": "Load /bin/utest",
|
||||
"text": "add-symbol-file ${workspaceFolder}/../tmp_rootfs/bin/libc_test",
|
||||
"description": "/bin/libc_test (0x00600000)",
|
||||
"ignoreFailures": true
|
||||
},
|
||||
{
|
||||
"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",
|
||||
"request": "attach",
|
||||
"name": "Launch QEMU & attach to gdbserver",
|
||||
"name": "Launch QEMU & attach to gdbserver (x64)",
|
||||
"executable": "${workspaceFolder}/../Kernel/fennix.elf",
|
||||
"target": "/tmp/gdb-fennix",
|
||||
"remote": true,
|
||||
@ -63,7 +149,7 @@
|
||||
],
|
||||
"internalConsoleOptions": "neverOpen",
|
||||
"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/cross/**": 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",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "launch-qemu",
|
||||
"label": "Clean",
|
||||
"type": "shell",
|
||||
"command": "make -C ../ build && make -C ../ vscode_debug_only",
|
||||
"isBackground": true,
|
||||
"problemMatcher": [],
|
||||
"command": "make clean",
|
||||
"isBackground": false,
|
||||
"hide": false,
|
||||
"group": {
|
||||
"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
|
||||
},
|
||||
"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
|
||||
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,
|
||||
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 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();
|
||||
EXTERNC int cxx_Probe();
|
||||
EXTERNC int cxx_Initialize();
|
||||
EXTERNC int cxx_Finalize();
|
||||
typedef int bool;
|
||||
#define true 1
|
||||
#define false 0
|
||||
|
||||
#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 local variable names with a lowercase letter.
|
||||
- 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.
|
||||
|
||||
|
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](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
|
||||
- [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)
|
||||
@ -120,6 +123,18 @@ License information can be found in the [LICENSES.md](LICENSES.md) file.
|
||||
## UART
|
||||
- [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!
|
||||
|
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",
|
||||
"-msoft-float",
|
||||
"-fno-builtin",
|
||||
|
||||
// C++ flags
|
||||
"-fexceptions",
|
||||
|
||||
// Linker flags
|
||||
"-fPIC",
|
||||
"-fPIE",
|
||||
@ -50,7 +48,6 @@
|
||||
"-nolibc",
|
||||
"-zmax-page-size=0x1000",
|
||||
"-static",
|
||||
|
||||
// VSCode flags
|
||||
"-ffreestanding",
|
||||
"-nostdinc",
|
||||
@ -91,10 +88,8 @@
|
||||
"-ffunction-sections",
|
||||
"-msoft-float",
|
||||
"-fno-builtin",
|
||||
|
||||
// C++ flags
|
||||
"-fexceptions",
|
||||
|
||||
// Linker flags
|
||||
"-fPIC",
|
||||
"-fPIE",
|
||||
@ -106,12 +101,36 @@
|
||||
"-nolibc",
|
||||
"-zmax-page-size=0x1000",
|
||||
"-static",
|
||||
|
||||
// VSCode flags
|
||||
"-ffreestanding",
|
||||
"-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
|
||||
|
@ -43,26 +43,47 @@ endif
|
||||
export DRIVER_LDFLAGS
|
||||
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:
|
||||
cp -rf ../Kernel/include/interface/* include/
|
||||
mkdir -p out
|
||||
make -C library build
|
||||
make -C audio build
|
||||
make -C input build
|
||||
make -C misc build
|
||||
make -C network build
|
||||
make -C storage build
|
||||
make -C filesystem build
|
||||
$(MAKE) -C library build
|
||||
ifneq ($(filter amd64 i386,$(OSARCH)),)
|
||||
$(MAKE) -C audio build
|
||||
$(MAKE) -C input build
|
||||
$(MAKE) -C misc build
|
||||
$(MAKE) -C network build
|
||||
$(MAKE) -C storage build
|
||||
$(MAKE) -C filesystem build
|
||||
endif
|
||||
$(MAKE) copy_driver_signatures
|
||||
|
||||
prepare:
|
||||
$(info Nothing to prepare)
|
||||
|
||||
clean:
|
||||
rm -rf out
|
||||
make -C library clean
|
||||
make -C audio clean
|
||||
make -C input clean
|
||||
make -C misc clean
|
||||
make -C network clean
|
||||
make -C storage clean
|
||||
make -C filesystem clean
|
||||
$(MAKE) -C library clean
|
||||
ifneq ($(filter amd64 i386,$(OSARCH)),)
|
||||
$(MAKE) -C audio clean
|
||||
$(MAKE) -C input clean
|
||||
$(MAKE) -C misc clean
|
||||
$(MAKE) -C network 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;
|
||||
} PS2_OUTPUT_PORT;
|
||||
|
||||
#ifndef __kernel__
|
||||
void PIC_EOI(uint8_t IRQ);
|
||||
void IRQ_MASK(uint8_t IRQ);
|
||||
void IRQ_UNMASK(uint8_t IRQ);
|
||||
@ -114,11 +115,11 @@ uint8_t PS2ReadStatus();
|
||||
uint8_t PS2ReadAfterACK();
|
||||
void PS2ClearOutputBuffer();
|
||||
int PS2ACKTimeout();
|
||||
#endif // !__kernel__
|
||||
|
||||
#define WaitOutput PS2Wait(DriverID, true)
|
||||
#define WaitInput PS2Wait(DriverID, false)
|
||||
|
||||
|
||||
#define PS2_KBD_CMD_SET_LEDS 0xED
|
||||
#define PS2_KBD_CMD_ECHO 0xEE
|
||||
#define PS2_KBD_CMD_SCAN_CODE_SET 0xF0
|
||||
@ -189,7 +190,6 @@ typedef union
|
||||
uint8_t Raw;
|
||||
} PS2_KBD_TYPEMATIC;
|
||||
|
||||
|
||||
#define PS2_MOUSE_CMD_SET_SCALING_1_1 0xE6
|
||||
#define PS2_MOUSE_CMD_SET_SCALING_2_1 0xE7
|
||||
#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,
|
||||
} 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 int UnregisterDevice(dev_t Device);
|
||||
#endif // !__kernel__
|
||||
|
||||
#endif // !__FENNIX_API_DEVICE_H__
|
||||
|
@ -25,14 +25,13 @@
|
||||
* Full list:
|
||||
* https://pubs.opengroup.org/onlinepubs/9699919799.2018edition/basedefs/errno.h.html
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
/**
|
||||
|
||||
/**
|
||||
* No Error
|
||||
*/
|
||||
EOK = 0,
|
||||
#define EOK 0
|
||||
|
||||
/**
|
||||
/**
|
||||
* 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
|
||||
* than the system-imposed limit of {ARG_MAX} bytes.
|
||||
@ -41,52 +40,52 @@ typedef enum
|
||||
* or:
|
||||
* 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
|
||||
* forbidden by its file access permissions.
|
||||
*/
|
||||
EACCES = 2,
|
||||
#define EACCES 2
|
||||
|
||||
/**
|
||||
/**
|
||||
* Address in use. The specified address is in use.
|
||||
*/
|
||||
EADDRINUSE = 3,
|
||||
#define EADDRINUSE 3
|
||||
|
||||
/**
|
||||
/**
|
||||
* Address not available. The specified address is not available from
|
||||
* the local system.
|
||||
*/
|
||||
EADDRNOTAVAIL = 4,
|
||||
#define EADDRNOTAVAIL 4
|
||||
|
||||
/**
|
||||
/**
|
||||
* Address family not supported. The implementation does not support
|
||||
* the specified address family, or the specified address is not a
|
||||
* valid address for the address family of the specified socket.
|
||||
*/
|
||||
EAFNOSUPPORT = 5,
|
||||
#define EAFNOSUPPORT 5
|
||||
|
||||
/**
|
||||
/**
|
||||
* Resource temporarily unavailable. This is a temporary condition
|
||||
* 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
|
||||
* progress for the specified socket.
|
||||
*/
|
||||
EALREADY = 7,
|
||||
#define EALREADY 7
|
||||
|
||||
/**
|
||||
/**
|
||||
* 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
|
||||
* file that is only open for writing (reading).
|
||||
*/
|
||||
EBADF = 8,
|
||||
#define EBADF 8
|
||||
|
||||
/**
|
||||
/**
|
||||
* Bad message. During a read(), getmsg(), getpmsg(), or ioctl()
|
||||
* I_RECVFD request to a STREAMS device, a message arrived at the
|
||||
* 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
|
||||
* descriptor when I_RECVFD was specified.
|
||||
*/
|
||||
EBADMSG = 9,
|
||||
#define EBADMSG 9
|
||||
|
||||
/**
|
||||
/**
|
||||
* Resource busy. An attempt was made to make use of a system
|
||||
* resource that is not currently available, as it is being
|
||||
* used by another process in a manner that would have
|
||||
* conflicted with the request being made by this process.
|
||||
*/
|
||||
EBUSY = 10,
|
||||
#define EBUSY 10
|
||||
|
||||
/**
|
||||
/**
|
||||
* Operation canceled. The associated asynchronous operation was
|
||||
* canceled before completion.
|
||||
*/
|
||||
ECANCELED = 11,
|
||||
#define ECANCELED 11
|
||||
|
||||
/**
|
||||
/**
|
||||
* No child process. A wait(), waitid(), or waitpid() function was
|
||||
* executed by a process that had no existing or unwaited-for
|
||||
* child process.
|
||||
*/
|
||||
ECHILD = 12,
|
||||
#define ECHILD 12
|
||||
|
||||
/**
|
||||
/**
|
||||
* Connection aborted. The connection has been aborted.
|
||||
*/
|
||||
ECONNABORTED = 13,
|
||||
#define ECONNABORTED 13
|
||||
|
||||
/**
|
||||
/**
|
||||
* Connection refused. An attempt to connect to a socket was refused
|
||||
* because there was no process listening or because the queue of
|
||||
* connection requests was full and the underlying protocol does not
|
||||
* support retransmissions.
|
||||
*/
|
||||
ECONNREFUSED = 14,
|
||||
#define ECONNREFUSED 14
|
||||
|
||||
/**
|
||||
/**
|
||||
* 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 that would have resulted in a deadlock situation.
|
||||
*/
|
||||
EDEADLK = 16,
|
||||
#define EDEADLK 16
|
||||
|
||||
/**
|
||||
/**
|
||||
* 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
|
||||
* mathematical function (defined in the ISO C standard).
|
||||
*/
|
||||
EDOM = 18,
|
||||
#define EDOM 18
|
||||
|
||||
/**
|
||||
/**
|
||||
* Reserved.
|
||||
*/
|
||||
EDQUOT = 19,
|
||||
#define EDQUOT 19
|
||||
|
||||
/**
|
||||
/**
|
||||
* File exists. An existing file was mentioned in an inappropriate
|
||||
* 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
|
||||
* to use an argument of a call. The reliable detection of this error
|
||||
* cannot be guaranteed, and when not detected may result in the
|
||||
* generation of a signal, indicating an address violation, which is
|
||||
* sent to the process.
|
||||
*/
|
||||
EFAULT = 21,
|
||||
#define EFAULT 21
|
||||
|
||||
/**
|
||||
/**
|
||||
* File too large. The size of a file would exceed the maximum file
|
||||
* size of an implementation or offset maximum established in the
|
||||
* corresponding file description.
|
||||
*/
|
||||
EFBIG = 22,
|
||||
#define EFBIG 22
|
||||
|
||||
/**
|
||||
/**
|
||||
* Host is unreachable. The destination host cannot be reached
|
||||
* (probably because the host is down or a remote router cannot
|
||||
* reach it).
|
||||
*/
|
||||
EHOSTUNREACH = 23,
|
||||
#define EHOSTUNREACH 23
|
||||
|
||||
/**
|
||||
/**
|
||||
* Identifier removed. Returned during XSI interprocess communication
|
||||
* 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
|
||||
* 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).
|
||||
*/
|
||||
EILSEQ = 25,
|
||||
#define EILSEQ 25
|
||||
|
||||
/**
|
||||
/**
|
||||
* Operation in progress. This code is used to indicate that an
|
||||
* asynchronous operation has not yet completed.
|
||||
* or:
|
||||
* O_NONBLOCK is set for the socket file descriptor and the connection
|
||||
* cannot be immediately established.
|
||||
*/
|
||||
EINPROGRESS = 26,
|
||||
#define EINPROGRESS 26
|
||||
|
||||
/**
|
||||
/**
|
||||
* Interrupted function call. An asynchronous signal was caught by the
|
||||
* process during the execution of an interruptible function. If the
|
||||
* signal handler performs a normal return, the interrupted function
|
||||
* call may return this condition (see the Base Definitions volume
|
||||
* of POSIX.1-2017, <signal.h>).
|
||||
*/
|
||||
EINTR = 27,
|
||||
#define EINTR 27
|
||||
|
||||
/**
|
||||
/**
|
||||
* Invalid argument. Some invalid argument was supplied; for example,
|
||||
* specifying an undefined signal in a signal() function or a
|
||||
* kill() function.
|
||||
*/
|
||||
EINVAL = 28,
|
||||
#define EINVAL 28
|
||||
|
||||
/**
|
||||
/**
|
||||
* Input/output error. Some physical input or output error has occurred.
|
||||
* This error may be reported on a subsequent operation on the same
|
||||
* file descriptor. Any other error-causing operation on the same file
|
||||
* descriptor may cause the [EIO] error indication to be lost.
|
||||
*/
|
||||
EIO = 29,
|
||||
#define EIO 29
|
||||
|
||||
/**
|
||||
/**
|
||||
* 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
|
||||
* mode specified.
|
||||
*/
|
||||
EISDIR = 31,
|
||||
#define EISDIR 31
|
||||
|
||||
/**
|
||||
/**
|
||||
* Symbolic link loop. A loop exists in symbolic links encountered
|
||||
* during pathname resolution. This error may also be returned if
|
||||
* more than {SYMLOOP_MAX} symbolic links are encountered during
|
||||
* pathname resolution.
|
||||
*/
|
||||
ELOOP = 32,
|
||||
#define ELOOP 32
|
||||
|
||||
/**
|
||||
/**
|
||||
* File descriptor value too large or too many open streams. An
|
||||
* 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 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
|
||||
* single file exceed {LINK_MAX}.
|
||||
*/
|
||||
EMLINK = 34,
|
||||
#define EMLINK 34
|
||||
|
||||
/**
|
||||
/**
|
||||
* Message too large. A message sent on a transport provider was
|
||||
* larger than an internal message buffer or some other network limit.
|
||||
* or:
|
||||
* Inappropriate message buffer length.
|
||||
*/
|
||||
EMSGSIZE = 35,
|
||||
#define EMSGSIZE 35
|
||||
|
||||
/**
|
||||
/**
|
||||
* Reserved.
|
||||
*/
|
||||
EMULTIHOP = 36,
|
||||
#define EMULTIHOP 36
|
||||
|
||||
/**
|
||||
/**
|
||||
* Filename too long. The length of a pathname exceeds {PATH_MAX} and
|
||||
* the implementation considers this to be an error, or a pathname
|
||||
* 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
|
||||
* string the size of which exceeds {PATH_MAX}.
|
||||
*/
|
||||
ENAMETOOLONG = 37,
|
||||
#define ENAMETOOLONG 37
|
||||
|
||||
/**
|
||||
/**
|
||||
* Network is down. The local network interface used to reach the
|
||||
* destination is down.
|
||||
*/
|
||||
ENETDOWN = 38,
|
||||
#define ENETDOWN 38
|
||||
|
||||
/**
|
||||
/**
|
||||
* The connection was aborted by the network.
|
||||
*/
|
||||
ENETRESET = 39,
|
||||
#define ENETRESET 39
|
||||
|
||||
/**
|
||||
/**
|
||||
* 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
|
||||
* in the system. The system has reached its predefined limit for
|
||||
* simultaneously open files and temporarily cannot accept requests
|
||||
* to open another one.
|
||||
*/
|
||||
ENFILE = 41,
|
||||
#define ENFILE 41
|
||||
|
||||
/**
|
||||
/**
|
||||
* No buffer space available. Insufficient buffer resources were
|
||||
* 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
|
||||
* read queue.
|
||||
*/
|
||||
ENODATA = 43,
|
||||
#define ENODATA 43
|
||||
|
||||
/**
|
||||
/**
|
||||
* No such device. An attempt was made to apply an inappropriate
|
||||
* function to a device; for example, trying to read a write-only
|
||||
* device such as a printer.
|
||||
*/
|
||||
ENODEV = 44,
|
||||
#define ENODEV 44
|
||||
|
||||
/**
|
||||
/**
|
||||
* No such file or directory. A component of a specified pathname
|
||||
* 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
|
||||
* that, although it has appropriate privileges, is not in the
|
||||
* format required by the implementation for executable files.
|
||||
*/
|
||||
ENOEXEC = 46,
|
||||
#define ENOEXEC 46
|
||||
|
||||
/**
|
||||
/**
|
||||
* No locks available. A system-imposed limit on the number of
|
||||
* simultaneous file and record locks has been reached and no more
|
||||
* are currently available.
|
||||
*/
|
||||
ENOLCK = 47,
|
||||
#define ENOLCK 47
|
||||
|
||||
/**
|
||||
/**
|
||||
* Reserved.
|
||||
*/
|
||||
ENOLINK = 48,
|
||||
#define ENOLINK 48
|
||||
|
||||
/**
|
||||
/**
|
||||
* Not enough space. The new process image requires more memory than
|
||||
* is allowed by the hardware or system-imposed memory management
|
||||
* constraints.
|
||||
*/
|
||||
ENOMEM = 49,
|
||||
#define ENOMEM 49
|
||||
|
||||
/**
|
||||
/**
|
||||
* No message of the desired type. The message queue does not contain
|
||||
* a message of the required type during XSI interprocess communication.
|
||||
*/
|
||||
ENOMSG = 50,
|
||||
#define ENOMSG 50
|
||||
|
||||
/**
|
||||
/**
|
||||
* Protocol not available. The protocol option specified to
|
||||
* setsockopt() is not supported by the implementation.
|
||||
*/
|
||||
ENOPROTOOPT = 51,
|
||||
#define ENOPROTOOPT 51
|
||||
|
||||
/**
|
||||
/**
|
||||
* No space left on a device. During the write() function on a
|
||||
* regular file or when extending a directory, there is no free
|
||||
* space left on the device.
|
||||
*/
|
||||
ENOSPC = 52,
|
||||
#define ENOSPC 52
|
||||
|
||||
/**
|
||||
/**
|
||||
* No STREAM resources. Insufficient STREAMS memory resources are
|
||||
* available to perform a STREAMS-related function. This is a
|
||||
* temporary condition; it may be recovered from if other
|
||||
* processes release resources.
|
||||
*/
|
||||
ENOSR = 53,
|
||||
#define ENOSR 53
|
||||
|
||||
/**
|
||||
/**
|
||||
* Not a STREAM. A STREAM function was attempted on a file descriptor
|
||||
* that was not associated with a STREAMS device.
|
||||
*/
|
||||
ENOSTR = 54,
|
||||
#define ENOSTR 54
|
||||
|
||||
/**
|
||||
/**
|
||||
* Functionality not supported. An attempt was made to use optional
|
||||
* functionality that is not supported in this implementation.
|
||||
*/
|
||||
ENOSYS = 55,
|
||||
#define ENOSYS 55
|
||||
|
||||
/**
|
||||
/**
|
||||
* Socket not connected. The socket is not connected.
|
||||
*/
|
||||
ENOTCONN = 56,
|
||||
#define ENOTCONN 56
|
||||
|
||||
/**
|
||||
/**
|
||||
* Not a directory. A component of the specified pathname exists, but
|
||||
* it is not a directory, when a directory was expected; or an
|
||||
* attempt was made to create a non-directory file, and the specified
|
||||
* pathname contains at least one non- \<slash\> character and ends
|
||||
* with one or more trailing \<slash\> characters.
|
||||
*/
|
||||
ENOTDIR = 57,
|
||||
#define ENOTDIR 57
|
||||
|
||||
/**
|
||||
/**
|
||||
* Directory not empty. A directory other than an empty directory
|
||||
* was supplied when an empty directory was expected.
|
||||
*/
|
||||
ENOTEMPTY = 58,
|
||||
#define ENOTEMPTY 58
|
||||
|
||||
/**
|
||||
/**
|
||||
* State not recoverable. The state protected by a robust mutex
|
||||
* is not recoverable.
|
||||
*/
|
||||
ENOTRECOVERABLE = 59,
|
||||
#define ENOTRECOVERABLE 59
|
||||
|
||||
/**
|
||||
/**
|
||||
* 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
|
||||
* feature or value.
|
||||
*/
|
||||
ENOTSUP = 61,
|
||||
#define ENOTSUP 61
|
||||
|
||||
/**
|
||||
/**
|
||||
* Inappropriate I/O control operation. A control function has been
|
||||
* attempted for a file or special file for which the operation
|
||||
* is inappropriate.
|
||||
*/
|
||||
ENOTTY = 62,
|
||||
#define ENOTTY 62
|
||||
|
||||
/**
|
||||
/**
|
||||
* No such device or address. Input or output on a special file
|
||||
* refers to a device that does not exist, or makes a request
|
||||
* beyond the capabilities of the device. It may also occur when,
|
||||
* for example, a tape drive is not on-line.
|
||||
*/
|
||||
ENXIO = 63,
|
||||
#define ENXIO 63
|
||||
|
||||
/**
|
||||
/**
|
||||
* Operation not supported on socket. The type of socket (address
|
||||
* 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
|
||||
* attempted which would generate a value that is outside the
|
||||
* range of values that can be represented in the relevant data
|
||||
* 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
|
||||
* while holding the mutex lock.
|
||||
*/
|
||||
EOWNERDEAD = 66,
|
||||
#define EOWNERDEAD 66
|
||||
|
||||
/**
|
||||
/**
|
||||
* Operation not permitted. An attempt was made to perform an
|
||||
* operation limited to processes with appropriate privileges or
|
||||
* 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
|
||||
* for which there is no process to read the data.
|
||||
*/
|
||||
EPIPE = 68,
|
||||
#define EPIPE 68
|
||||
|
||||
/**
|
||||
/**
|
||||
* Protocol error. Some protocol error occurred. This error is
|
||||
* device-specific, but is generally not related to a
|
||||
* hardware failure.
|
||||
*/
|
||||
EPROTO = 69,
|
||||
#define EPROTO 69
|
||||
|
||||
/**
|
||||
/**
|
||||
* Protocol not supported. The protocol is not supported by the
|
||||
* address family, or the protocol is not supported by
|
||||
* the implementation.
|
||||
*/
|
||||
EPROTONOSUPPORT = 70,
|
||||
#define EPROTONOSUPPORT 70
|
||||
|
||||
/**
|
||||
/**
|
||||
* Protocol wrong type for socket. The socket type is not
|
||||
* supported by the protocol.
|
||||
*/
|
||||
EPROTOTYPE = 71,
|
||||
#define EPROTOTYPE 71
|
||||
|
||||
/**
|
||||
/**
|
||||
* Result too large or too small. The result of the function
|
||||
* is too large (overflow) or too small (underflow) to be
|
||||
* represented in the available space.
|
||||
*/
|
||||
ERANGE = 72,
|
||||
#define ERANGE 72
|
||||
|
||||
/**
|
||||
/**
|
||||
* Read-only file system. An attempt was made to modify a file
|
||||
* 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
|
||||
* associated with a pipe or FIFO.
|
||||
*/
|
||||
ESPIPE = 74,
|
||||
#define ESPIPE 74
|
||||
|
||||
/**
|
||||
/**
|
||||
* No such process. No process can be found corresponding to that
|
||||
* specified by the given process ID.
|
||||
*/
|
||||
ESRCH = 75,
|
||||
#define ESRCH 75
|
||||
|
||||
/**
|
||||
/**
|
||||
* Reserved.
|
||||
*/
|
||||
ESTALE = 76,
|
||||
#define ESTALE 76
|
||||
|
||||
/**
|
||||
/**
|
||||
* STREAM ioctl() timeout. The timer set for a STREAMS ioctl() call
|
||||
* has expired. The cause of this error is device-specific and could
|
||||
* indicate either a hardware or software failure, or a timeout
|
||||
* value that is too short for the specific operation. The status
|
||||
* of the ioctl() operation is unspecified.
|
||||
*/
|
||||
ETIME = 77,
|
||||
#define ETIME 77
|
||||
|
||||
/**
|
||||
/**
|
||||
* Connection timed out. The connection to a remote machine has
|
||||
* timed out.
|
||||
* 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
|
||||
* was exceeded before the operation completed.
|
||||
*/
|
||||
ETIMEDOUT = 78,
|
||||
#define ETIMEDOUT 78
|
||||
|
||||
/**
|
||||
/**
|
||||
* Text file busy. An attempt was made to execute a pure-procedure
|
||||
* program that is currently open for writing, or an attempt has
|
||||
* been made to open for writing a pure-procedure program that
|
||||
* is being executed.
|
||||
*/
|
||||
ETXTBSY = 79,
|
||||
#define ETXTBSY 79
|
||||
|
||||
/**
|
||||
/**
|
||||
* Operation would block. An operation on a socket marked as
|
||||
* non-blocking has encountered a situation such as no data available
|
||||
* 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.
|
||||
*/
|
||||
EXDEV = 81,
|
||||
#define EXDEV 81
|
||||
|
||||
__ERRNO_MAX
|
||||
} KernelErrors;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#ifdef __kernel__
|
||||
#define __ERRNO_MAX 82
|
||||
#endif
|
||||
|
||||
int *__errno_location(void) __attribute__((const));
|
||||
char *strerror(int errnum);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#define errno (*__errno_location())
|
||||
|
||||
#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 */
|
||||
#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_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR)
|
||||
#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
|
||||
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(mode_t) == 2, "mode_t must be 16 bits");
|
||||
static_assert(sizeof(nlink_t) == 2, "nlink_t must be 16 bits");
|
||||
static_assert(sizeof(uid_t) == 2, "uid_t must be 16 bits");
|
||||
static_assert(sizeof(gid_t) == 2, "gid_t must be 16 bits");
|
||||
static_assert(sizeof(mode_t) == 4, "mode_t must be 32 bits");
|
||||
static_assert(sizeof(nlink_t) == 4, "nlink_t must be 32 bits");
|
||||
static_assert(sizeof(uid_t) == 4, "uid_t must be 32 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(time_t) == 4, "time_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);
|
||||
} __attribute__((packed));
|
||||
|
||||
#define I_FLAG_ROOT 0x1
|
||||
#define I_FLAG_MOUNTPOINT 0x2
|
||||
#define I_FLAG_CACHE_KEEP 0x4
|
||||
|
||||
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
|
||||
{
|
||||
int (*AllocateInode)(struct FileSystemInfo *Info, struct Inode **Result);
|
||||
@ -347,8 +355,8 @@ struct SuperBlockOperations
|
||||
*
|
||||
* Write all pending changes to the disk.
|
||||
*
|
||||
* @param Info Inode to synchronize. If NULL, synchronize all inodes.
|
||||
* @param Node Inode to synchronize.
|
||||
* @param Info Inode to synchronize.
|
||||
* @param Node Inode to synchronize. If NULL, synchronize all inodes.
|
||||
*
|
||||
* @return Zero on success, otherwise an error code.
|
||||
*/
|
||||
@ -364,20 +372,62 @@ struct SuperBlockOperations
|
||||
* @return Zero on success, otherwise an error code.
|
||||
*/
|
||||
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));
|
||||
|
||||
struct FileSystemInfo
|
||||
{
|
||||
const char *Name;
|
||||
const char *RootName;
|
||||
|
||||
int Flags;
|
||||
int Capabilities;
|
||||
|
||||
struct SuperBlockOperations SuperOps;
|
||||
struct InodeOperations Ops;
|
||||
|
||||
void *PrivateData;
|
||||
} __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);
|
||||
int UnregisterFileSystem(dev_t Device);
|
||||
#endif // !__kernel__
|
||||
|
||||
#endif // !__FENNIX_API_FILESYSTEM_H__
|
||||
|
@ -239,6 +239,8 @@ typedef struct
|
||||
};
|
||||
} InputReport;
|
||||
|
||||
#ifndef __kernel__
|
||||
EXTERNC int ReportInputEvent(InputReport *Report);
|
||||
#endif // !__kernel__
|
||||
|
||||
#endif // !__FENNIX_API_INPUT_H__
|
||||
|
@ -75,7 +75,7 @@ extern "C"
|
||||
: "dN"(Port), "a"(Data));
|
||||
}
|
||||
|
||||
static inline uint8_t mmioin8(uint64_t Address)
|
||||
static inline uint8_t mmioin8(uintptr_t Address)
|
||||
{
|
||||
__asm__ volatile("" ::
|
||||
: "memory");
|
||||
@ -85,7 +85,7 @@ extern "C"
|
||||
return Result;
|
||||
}
|
||||
|
||||
static inline uint16_t mmioin16(uint64_t Address)
|
||||
static inline uint16_t mmioin16(uintptr_t Address)
|
||||
{
|
||||
__asm__ volatile("" ::
|
||||
: "memory");
|
||||
@ -95,7 +95,7 @@ extern "C"
|
||||
return Result;
|
||||
}
|
||||
|
||||
static inline uint32_t mmioin32(uint64_t Address)
|
||||
static inline uint32_t mmioin32(uintptr_t Address)
|
||||
{
|
||||
__asm__ volatile("" ::
|
||||
: "memory");
|
||||
@ -105,17 +105,17 @@ extern "C"
|
||||
return Result;
|
||||
}
|
||||
|
||||
static inline uint64_t mmioin64(uint64_t Address)
|
||||
static inline uintptr_t mmioin64(uintptr_t Address)
|
||||
{
|
||||
__asm__ volatile("" ::
|
||||
: "memory");
|
||||
uint64_t Result = *(volatile uint64_t *)Address;
|
||||
uintptr_t Result = *(volatile uintptr_t *)Address;
|
||||
__asm__ volatile("" ::
|
||||
: "memory");
|
||||
return Result;
|
||||
}
|
||||
|
||||
static inline void mmioout8(uint64_t Address, uint8_t Data)
|
||||
static inline void mmioout8(uintptr_t Address, uint8_t Data)
|
||||
{
|
||||
__asm__ volatile("" ::
|
||||
: "memory");
|
||||
@ -124,7 +124,7 @@ extern "C"
|
||||
: "memory");
|
||||
}
|
||||
|
||||
static inline void mmioout16(uint64_t Address, uint16_t Data)
|
||||
static inline void mmioout16(uintptr_t Address, uint16_t Data)
|
||||
{
|
||||
__asm__ volatile("" ::
|
||||
: "memory");
|
||||
@ -133,7 +133,7 @@ extern "C"
|
||||
: "memory");
|
||||
}
|
||||
|
||||
static inline void mmioout32(uint64_t Address, uint32_t Data)
|
||||
static inline void mmioout32(uintptr_t Address, uint32_t Data)
|
||||
{
|
||||
__asm__ volatile("" ::
|
||||
: "memory");
|
||||
@ -142,11 +142,11 @@ extern "C"
|
||||
: "memory");
|
||||
}
|
||||
|
||||
static inline void mmioout64(uint64_t Address, uint64_t Data)
|
||||
static inline void mmioout64(uintptr_t Address, uintptr_t Data)
|
||||
{
|
||||
__asm__ volatile("" ::
|
||||
: "memory");
|
||||
*(volatile uint64_t *)Address = Data;
|
||||
*(volatile uintptr_t *)Address = Data;
|
||||
__asm__ volatile("" ::
|
||||
: "memory");
|
||||
}
|
||||
@ -175,10 +175,10 @@ extern "C"
|
||||
: "memory");
|
||||
}
|
||||
|
||||
static inline void mmoutq(void *Address, uint64_t Value)
|
||||
static inline void mmoutq(void *Address, uintptr_t Value)
|
||||
{
|
||||
__asm__ volatile("mov %1, %0"
|
||||
: "=m"((*(uint64_t *)(Address)))
|
||||
: "=m"((*(uintptr_t *)(Address)))
|
||||
: "r"(Value)
|
||||
: "memory");
|
||||
}
|
||||
@ -213,12 +213,12 @@ extern "C"
|
||||
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"
|
||||
: "=r"(Result)
|
||||
: "m"((*(uint64_t *)(Address)))
|
||||
: "m"((*(uintptr_t *)(Address)))
|
||||
: "memory");
|
||||
return Result;
|
||||
}
|
||||
|
@ -171,11 +171,13 @@ extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#ifndef __kernel__
|
||||
PCIArray *GetPCIDevices(uint16_t Vendors[], uint16_t Devices[]);
|
||||
void InitializePCI(PCIDevice *Device);
|
||||
uint32_t GetBAR(uint8_t Index, PCIDevice *Device);
|
||||
uint8_t iLine(PCIDevice *Device);
|
||||
uint8_t iPin(PCIDevice *Device);
|
||||
#endif // !__kernel__
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -15,13 +15,44 @@
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __FENNIX_API_SYSCALLS_LIST_H__
|
||||
#define __FENNIX_API_SYSCALLS_LIST_H__
|
||||
#ifndef __FENNIX_API_SYSTEM_CALLS_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
|
||||
|
||||
#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
|
||||
*
|
||||
@ -33,10 +64,30 @@
|
||||
static inline scarg syscall0(scarg syscall)
|
||||
{
|
||||
scarg ret;
|
||||
#if defined(__amd64__)
|
||||
__asm__ __volatile__("syscall"
|
||||
: "=a"(ret)
|
||||
: "a"(syscall)
|
||||
: "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;
|
||||
}
|
||||
|
||||
@ -52,10 +103,30 @@ static inline scarg syscall0(scarg syscall)
|
||||
static inline scarg syscall1(scarg syscall, scarg arg1)
|
||||
{
|
||||
scarg ret;
|
||||
#if defined(__amd64__)
|
||||
__asm__ __volatile__("syscall"
|
||||
: "=a"(ret)
|
||||
: "a"(syscall), "D"(arg1)
|
||||
: "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;
|
||||
}
|
||||
|
||||
@ -72,10 +143,32 @@ static inline scarg syscall1(scarg syscall, scarg arg1)
|
||||
static inline scarg syscall2(scarg syscall, scarg arg1, scarg arg2)
|
||||
{
|
||||
scarg ret;
|
||||
#if defined(__amd64__)
|
||||
__asm__ __volatile__("syscall"
|
||||
: "=a"(ret)
|
||||
: "a"(syscall), "D"(arg1), "S"(arg2)
|
||||
: "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;
|
||||
}
|
||||
|
||||
@ -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)
|
||||
{
|
||||
scarg ret;
|
||||
#if defined(__amd64__)
|
||||
__asm__ __volatile__("syscall"
|
||||
: "=a"(ret)
|
||||
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3)
|
||||
: "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;
|
||||
}
|
||||
|
||||
@ -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)
|
||||
{
|
||||
scarg ret;
|
||||
#if defined(__amd64__)
|
||||
register scarg r10 __asm__("r10") = arg4;
|
||||
__asm__ __volatile__("syscall"
|
||||
: "=a"(ret)
|
||||
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10)
|
||||
: "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;
|
||||
}
|
||||
|
||||
@ -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)
|
||||
{
|
||||
scarg ret;
|
||||
#if defined(__amd64__)
|
||||
register scarg r10 __asm__("r10") = arg4;
|
||||
register scarg r8 __asm__("r8") = arg5;
|
||||
__asm__ __volatile__("syscall"
|
||||
: "=a"(ret)
|
||||
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10), "r"(r8)
|
||||
: "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;
|
||||
}
|
||||
|
||||
@ -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)
|
||||
{
|
||||
scarg ret;
|
||||
#if defined(__amd64__)
|
||||
register scarg r10 __asm__("r10") = arg4;
|
||||
register scarg r8 __asm__("r8") = arg5;
|
||||
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"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10), "r"(r8), "r"(r9)
|
||||
: "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;
|
||||
}
|
||||
|
||||
@ -202,18 +403,18 @@ typedef enum
|
||||
|
||||
typedef enum
|
||||
{
|
||||
__SYS_O_RDONLY = 0x1,
|
||||
__SYS_O_WRONLY = 0x2,
|
||||
__SYS_O_RDWR = 0x3,
|
||||
__SYS_O_APPEND = 0x4,
|
||||
__SYS_O_CREAT = 0x8,
|
||||
__SYS_O_DSYNC = 0x10,
|
||||
__SYS_O_EXCL = 0x20,
|
||||
__SYS_O_NOCTTY = 0x40,
|
||||
__SYS_O_NONBLOCK = 0x80,
|
||||
__SYS_O_RSYNC = 0x100,
|
||||
__SYS_O_SYNC = 0x200,
|
||||
__SYS_O_TRUNC = 0x400
|
||||
__SYS_O_RDONLY = O_RDONLY,
|
||||
__SYS_O_WRONLY = O_WRONLY,
|
||||
__SYS_O_RDWR = O_RDWR,
|
||||
__SYS_O_APPEND = O_APPEND,
|
||||
__SYS_O_CREAT = O_CREAT,
|
||||
__SYS_O_DSYNC = O_DSYNC,
|
||||
__SYS_O_EXCL = O_EXCL,
|
||||
__SYS_O_NOCTTY = O_NOCTTY,
|
||||
__SYS_O_NONBLOCK = O_NONBLOCK,
|
||||
__SYS_O_RSYNC = O_RSYNC,
|
||||
__SYS_O_SYNC = O_SYNC,
|
||||
__SYS_O_TRUNC = O_TRUNC
|
||||
} syscall_open_flags_t;
|
||||
|
||||
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 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
|
||||
*
|
||||
@ -443,6 +674,8 @@ typedef enum
|
||||
*/
|
||||
SYS_API_VERSION = 0,
|
||||
|
||||
SYS_DEBUG_REPORT = 1,
|
||||
|
||||
/* I/O */
|
||||
|
||||
/**
|
||||
@ -599,6 +832,25 @@ typedef enum
|
||||
* - #EINVAL if the request is invalid
|
||||
*/
|
||||
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 */
|
||||
|
||||
@ -1388,6 +1640,22 @@ typedef enum
|
||||
* - #EACCES if permission is denied
|
||||
*/
|
||||
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
|
||||
@ -1431,6 +1699,9 @@ typedef enum
|
||||
/** @copydoc SYS_IOCTL */
|
||||
#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 */
|
||||
|
||||
/** @copydoc SYS_STAT */
|
||||
@ -1538,7 +1809,7 @@ typedef enum
|
||||
/* 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 */
|
||||
#define call_clock_gettime(clockid, tp) syscall2(SYS_CLOCK_GETTIME, (scarg)clockid, (scarg)tp)
|
||||
@ -1569,4 +1840,7 @@ typedef enum
|
||||
/** @copydoc SYS_RENAME */
|
||||
#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 int64_t clock_t;
|
||||
typedef int32_t pid_t;
|
||||
#elif defined(__LP32__)
|
||||
#else
|
||||
typedef int32_t off_t;
|
||||
typedef long long off64_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
|
||||
|
||||
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)
|
||||
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_start(args, format);
|
||||
#if defined(__amd64__) || defined(__i386__)
|
||||
__KernelPrint(DriverID, (long)format, (long)args);
|
||||
#elif defined(__aarch64__)
|
||||
__KernelPrint(DriverID, (long)format, (long)__builtin_va_arg(args, void *));
|
||||
#endif
|
||||
__builtin_va_end(args);
|
||||
}
|
||||
|
||||
@ -81,7 +85,11 @@ DefineFunction(void, KernelLog, const char *format, ...)
|
||||
{
|
||||
__builtin_va_list args;
|
||||
__builtin_va_start(args, format);
|
||||
#if defined(__amd64__) || defined(__i386__)
|
||||
__KernelLog(DriverID, (long)format, (long)args);
|
||||
#elif defined(__aarch64__)
|
||||
__KernelLog(DriverID, (long)format, (long)__builtin_va_arg(args, void *));
|
||||
#endif
|
||||
__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 -C ahci build
|
||||
make -C ata build
|
||||
MAKE_TARGETS := build clean
|
||||
DIRECTORIES := $(sort $(dir $(wildcard ./*/)))
|
||||
|
||||
clean:
|
||||
make -C ahci clean
|
||||
make -C ata clean
|
||||
.PHONY: $(MAKE_TARGETS) $(DIRECTORIES)
|
||||
|
||||
$(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": {
|
||||
"terminal.integrated.cwd": "../",
|
||||
"debug.allowBreakpointsEverywhere": true,
|
||||
"git.alwaysSignOff": true,
|
||||
"git.defaultBranchName": "master",
|
||||
"git.openRepositoryInParentFolders": "always",
|
||||
"C_Cpp.autoAddFileAssociations": false
|
||||
"C_Cpp.autoAddFileAssociations": false,
|
||||
}
|
||||
}
|
@ -7,25 +7,25 @@
|
||||
"settings": {
|
||||
"terminal.integrated.cwd": "../",
|
||||
"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.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": {
|
||||
"terminal.integrated.cwd": "../",
|
||||
"debug.allowBreakpointsEverywhere": true,
|
||||
"git.alwaysSignOff": true,
|
||||
"git.defaultBranchName": "master",
|
||||
"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": {
|
||||
"debug.allowBreakpointsEverywhere": true,
|
||||
"git.alwaysSignOff": true,
|
||||
"git.defaultBranchName": "master",
|
||||
"git.openRepositoryInParentFolders": "always",
|
||||
"C_Cpp.autoAddFileAssociations": false
|
||||
|
@ -6,9 +6,14 @@
|
||||
],
|
||||
"settings": {
|
||||
"debug.allowBreakpointsEverywhere": true,
|
||||
"git.alwaysSignOff": true,
|
||||
"git.defaultBranchName": "master",
|
||||
"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++"
|
||||
]
|
||||
},
|
||||
{
|
||||
"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)",
|
||||
"includePath": [
|
||||
@ -158,38 +185,6 @@
|
||||
"intelliSenseMode": "linux-gcc-arm64",
|
||||
"configurationProvider": "ms-vscode.makefile-tools",
|
||||
"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
|
||||
"-ffreestanding",
|
||||
"-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_NAME "Fennix"
|
||||
#define KERNEL_ARCH "amd64"
|
||||
#define KERNEL_VERSION "1.0"
|
||||
#define KERNEL_VERSION "1.0.0"
|
||||
#define GIT_COMMIT "0000000000000000000000000000000000000000"
|
||||
#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/*)))
|
||||
INCLUDE_DIR = -I./include -I./include_std
|
||||
|
||||
BMP_SOURCES := $(shell find ./ -type f -name '*.bmp')
|
||||
PSF_SOURCES := $(shell find ./ -type f -name '*.psf')
|
||||
ifeq ($(OSARCH), amd64)
|
||||
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
|
||||
define find-sources
|
||||
$(shell find ./ -type f -name '$1' $(shell echo $(foreach arch,$(filter-out $(OSARCH),$(AVAILABLE_ARCHS)), -not -path \"./arch/$(arch)/*\")) -print0 | xargs -0)
|
||||
endef
|
||||
|
||||
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)
|
||||
GCNO_OBJ = $(C_SOURCES:.c=.gcno) $(CXX_SOURCES:.cpp=.gcno)
|
||||
|
||||
@ -40,7 +32,7 @@ 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-unused-parameter -Wno-error=format
|
||||
|
||||
CFLAG_STACK_PROTECTOR := -fstack-protector-all
|
||||
|
||||
@ -53,16 +45,20 @@ CFLAGS := \
|
||||
-DKERNEL_VERSION='"$(KERNEL_VERSION)"' \
|
||||
-DGIT_COMMIT='"$(GIT_COMMIT)"' \
|
||||
-DGIT_COMMIT_SHORT='"$(GIT_COMMIT_SHORT)"' \
|
||||
-fno-pic -fno-pie -mno-red-zone -fno-builtin
|
||||
-fno-pic -fno-pie -fno-builtin
|
||||
|
||||
ifeq ($(OSARCH), amd64)
|
||||
CFLAGS += -march=core2 -mcmodel=kernel -m64
|
||||
CFLAGS += -march=core2 -mcmodel=kernel -m64 -mno-red-zone
|
||||
LDFLAGS += -Tarch/amd64/linker.ld
|
||||
else ifeq ($(OSARCH), i386)
|
||||
CFLAGS += -march=pentium -m32
|
||||
CFLAGS += -march=pentium -m32 -mno-red-zone
|
||||
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)
|
||||
CFLAGS +=
|
||||
CFLAGS += -march=armv9.4-a -mtune=cortex-a72 -mlittle-endian -mcmodel=large
|
||||
LDFLAGS += -Tarch/aarch64/linker.ld
|
||||
endif # OSARCH
|
||||
|
||||
@ -72,11 +68,15 @@ ifeq ($(DEBUG), 1)
|
||||
# CFLAGS += -pg
|
||||
# CFLAGS += -finstrument-functions
|
||||
CFLAGS += -DDEBUG -ggdb3 -O0 -fdiagnostics-color=always -fstack-usage -fsanitize=undefined
|
||||
CXXFLAGS += -fdiagnostics-all-candidates
|
||||
ifeq ($(OSARCH), amd64)
|
||||
CFLAGS += -fverbose-asm
|
||||
endif # amd64
|
||||
ifneq ($(OSARCH), aarch64)
|
||||
CFLAGS += -fstack-check
|
||||
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
|
||||
@ -112,7 +112,7 @@ $(KERNEL_FILENAME): $(OBJ)
|
||||
# https://gcc.gnu.org/projects/cxx-status.html
|
||||
%.o: %.cpp $(HEADERS)
|
||||
$(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
|
||||
$(info Compiling $<)
|
||||
@ -127,16 +127,20 @@ ifeq ($(OSARCH), amd64)
|
||||
$(__CONF_OBJCOPY) -O elf64-x86-64 -I binary $< $@
|
||||
else ifeq ($(OSARCH), i386)
|
||||
$(__CONF_OBJCOPY) -O elf32-i386 -I binary $< $@
|
||||
else ifeq ($(OSARCH), arm)
|
||||
$(__CONF_OBJCOPY) -O elf32-littlearm -I binary $< $@
|
||||
else ifeq ($(OSARCH), aarch64)
|
||||
$(__CONF_OBJCOPY) -O elf64-littleaarch64 -I binary $< $@
|
||||
endif
|
||||
$(__CONF_NM) $@
|
||||
|
||||
%.o: %.bmp
|
||||
%.o: %.png
|
||||
ifeq ($(OSARCH), amd64)
|
||||
$(__CONF_OBJCOPY) -O elf64-x86-64 -I binary $< $@
|
||||
else ifeq ($(OSARCH), i386)
|
||||
$(__CONF_OBJCOPY) -O elf32-i386 -I binary $< $@
|
||||
else ifeq ($(OSARCH), arm)
|
||||
$(__CONF_OBJCOPY) -O elf32-littlearm -I binary $< $@
|
||||
else ifeq ($(OSARCH), aarch64)
|
||||
$(__CONF_OBJCOPY) -O elf64-littlearch64 -I binary $< $@
|
||||
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))
|
||||
- [ ] Implementation of logging (beside serial) with log rotation.
|
||||
- [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.
|
||||
- [x] ~~Find a way to add intrinsics.~~ (not feasible, use inline assembly)
|
||||
- [ ] 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