Compare commits

...

3 Commits

Author SHA1 Message Date
Nathan 81bf333455 update 2022-10-03 20:54:01 -05:00
Nathan 3e67522af5 Add mirror 'dinit-userservd' at '0745b20' 2022-10-03 20:53:10 -05:00
Nathan 8562840e64 Add mirror 'linux-xanmod-edge' at '8c1bf9b' 2022-10-03 20:52:23 -05:00
18 changed files with 2421 additions and 0 deletions

15
.braids.json Normal file
View File

@ -0,0 +1,15 @@
{
"config_version": 1,
"mirrors": {
"dinit-userservd": {
"url": "https://github.com/XynonWasTaken/dinit-userservd",
"branch": "master",
"revision": "0745b208d6a742e9b6e8e168a1dfea707f2c11be"
},
"linux-xanmod-edge": {
"url": "https://aur.archlinux.org/linux-xanmod-edge.git",
"branch": "master",
"revision": "8c1bf9b760240f91099a81172831a2b523fa4218"
}
}
}

6
dinit-services/dbus Normal file
View File

@ -0,0 +1,6 @@
type = process
load-options = sub-vars
logfile = $HOME/.local/share/dinit/dbus.log
command = $HOME/.local/share/dinit/scripts/dbus-session --print-address 3
smooth-recovery = true
ready-notification = pipefd:3

4
dinit-services/gamemoded Normal file
View File

@ -0,0 +1,4 @@
type = process
command = /usr/bin/gamemoded
smooth-recovery = true
logfile = $HOME/.local/share/dinit/gamemoded

7
dinit-services/pipewire Normal file
View File

@ -0,0 +1,7 @@
type = process
load-options = sub-vars
logfile = $HOME/.local/share/dinit/pipewire.log
command = pipewire
restart = true
depends-on = dbus

View File

@ -0,0 +1,6 @@
type = process
load-options = sub-vars
logfile = $HOME/.local/share/dinit/pipewire-pulse.log
command = pipewire-pulse
restart = true
depends-on = pipewire

View File

@ -0,0 +1,8 @@
type = process
load-options = sub-vars
logfile = $HOME/.local/share/dinit/wireplumber.log
command = wireplumber
restart = true
smooth-recovery = true
depends-on = pipewire
depends-on = pipewire-pulse

View File

@ -0,0 +1,22 @@
Copyright 2021 Daniel "q66" Kolesa
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

33
dinit-userservd/PKGBUILD Normal file
View File

@ -0,0 +1,33 @@
pkgname=dinit-userservd
pkgver=0.1.1
pkgrel=1
epoch=
pkgdesc="user dinit instance spawner + manager daemon."
arch=('any')
url="https://github.com/chimera-linux/dinit-userservd/"
license=('BSD')
groups=('dinit-system')
depends=('dinit' 'elogind')
makedepends=('meson')
optdepends=()
provides=('dinit-userservd')
conflicts=('dinit-userservd-git')
install='dinit-userservd.install'
changelog=
prepare() {
cd $startdir
rm -rf pkg
mkdir -p build
}
build() {
cd $startdir
meson --prefix=/usr --buildtype=plain ./ ./build
meson compile -C build
}
package() {
cd $startdir
meson install -C build --destdir "$pkgdir"
}

97
dinit-userservd/README.md Normal file
View File

@ -0,0 +1,97 @@
# Artix Specific Info
PKGBUILDs for dinit-userservd located at: https://github.com/XynonWasTaken/dinit-userservd-PKGBUILD
Artix services for dinit-userservd located at: https://github.com/XynonWasTaken/dinit-userservd-services
# dinit-userservd
This is a daemon and a PAM module to handle user services management with the
`dinit` init system and service manager (https://github.com/davmac314/dinit).
It was created for the needs of the Chimera Linux project. It is not expected
to work properly anywhere else by default (those use cases are unsupported),
and issues or feature requests specific to other environments will not be
addressed. Patches may be accepted, provided they are not disruptive or
introduce excessive complexity.
## How it works
The project consists of a daemon and a PAM module. The PAM module is enabled
for example by adding this in your login path:
```
session optional pam_dinit_userservd.so
```
The daemon must simply be running in some way. If it is not running, you will
still be able to log in with the above setup, but it will not do anything.
A recommended way to manage the daemon is using a `dinit` service that is
provided with the project.
The daemon opens a control socket. The PAM module will make connections to
it upon session start (and close it upon session end). When the daemon
receives a connection, it will negotiate a session with the PAM module
and upon first login of each user, spawn a user `dinit` instance.
This instance is supervised, if it fails in any way it gets automatically
restarted. It runs outside of the login itself, as only one instance must
exist per user (who can have multiple logins) and it only exists once the
last login has logged out. This means that environment variables of the
login do not exist within the user instance by default, and they must be
exported into it through other means.
It will register the following service directories:
* `~/.config/dinit.d`
* `/etc/dinit.d/user`
* `/usr/local/lib/dinit.d/user`
* `/usr/lib/dinit.d/user`
You do not need to provide a `boot` service (in fact, you should not).
By default, the following path is used for autostarted user services:
* `~/.config/dinit.d/boot.d`
Simply drop symlinks to whatever services you want in there and they will
get started with your login.
The login proceeds once the `dinit` instance has signaled readiness (which
is once it has started its autostart services). It does so via an internal
notification mechanism.
### XDG_RUNTIME_DIR handling
**NOTE:** This is problematic for now, so it's disabled at the moment.
Usually, `XDG_RUNTIME_DIR` is managed by another daemon, typically `elogind`
for Chimera. However, some people may not be running `elogind` or a similar
solution. The PAM module automatically detects this and makes the daemon
manage the runtime directory for you.
It takes care of both creation and cleanup automatically as sessions are
logged in and as they go away.
To prevent it from managing rundir, you simply have to have something else
manage it before; that means specifying that earlier in the PAM config file.
Or, if you want to force that off, you can pass the `norundir` extra PAM
argument.
### Dbus handling
The daemon also supports handling of D-Bus session bus. If the socket
`/run/user/UID/bus` exists by the time readiness has been signaled, the
variable `DBUS_SESSION_BUS_ADDRESS` will automatically be exported into
the login environment.
That way it is possible to manage the session bus as a user service without
having to spawn it on-demand.
User services making use of the bus need to ensure that the variable is
exported in their launch environment in some way, as the service manager
runs outside of the user's login session.
## TODO
* Do not hardcode things to make it easier to use for other projects.

View File

@ -0,0 +1,7 @@
# dinit-userservd service
type = process
command = /usr/bin/dinit-userservd
depends-on = elogind
smooth-recovery = true
logfile = /var/log/dinit-userservd.log

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,15 @@
post_upgrade() {
echo """
POST INSTALL INSTRUCTIONS
---------------------------------
you must add: session optional pam_dinit_userservd.so
to your /etc/pam.d/login or this package WILL NOT WORK
---------------------------------
please install user service files to one of these locations (symlink to boot.d in config dir to enable):
~/.config/dinit.d/
/etc/dinit/user/
/usr/lib/dinit.d/user/
/usr/local/lib/dinit.d/user/
---------------------------------
"""
}

View File

@ -0,0 +1,37 @@
project(
'dinit-userservd',
['cpp'],
version: '0.1.0',
default_options: [
'cpp_std=c++17', 'warning_level=3', 'buildtype=debugoptimized',
'cpp_eh=none', 'cpp_rtti=false',
],
license: 'BSD-2-Clause'
)
cpp = meson.get_compiler('cpp')
pam_dep = dependency('pam', required: true)
rt_dep = cpp.find_library('rt', required: false)
daemon = executable(
'dinit-userservd', 'dinit-userservd.cc',
install: true,
dependencies: [rt_dep],
gnu_symbol_visibility: 'hidden'
)
pam_mod = shared_module(
'pam_dinit_userservd', 'pam_dinit_userservd.cc',
install: true,
install_dir: join_paths(get_option('libdir'), 'security'),
name_prefix: '',
dependencies: [pam_dep],
gnu_symbol_visibility: 'hidden'
)
install_data(
'dinit-userservd',
install_dir: join_paths(get_option('sysconfdir'), 'dinit.d'),
install_mode: 'rw-r--r--'
)

View File

@ -0,0 +1,365 @@
/* pam_dinit_userservd: the client part of dinit-userservd
*
* it connects to its socket and requests logins/logouts,
* communicating over a rudimentary protocol
*
* the PAM session opens a persistent connection, which also
* takes care of tracking when a session needs ending on the
* daemon side (once all connections are gone)
*
* Copyright 2021 Daniel "q66" Kolesa <q66@chimera-linux.org>
* License: BSD-2-Clause
*/
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <pwd.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <security/pam_modules.h>
#include <security/pam_misc.h>
#include "protocol.hh"
#define PAMAPI __attribute__((visibility ("default")))
static void free_sock(pam_handle_t *, void *data, int) {
int sock = *static_cast<int *>(data);
if (sock != -1) {
close(sock);
}
free(data);
}
static bool open_session(
pam_handle_t *pamh, unsigned int &uid, int argc, char const **argv,
unsigned int &orlen, char *orbuf, bool &set_rundir
) {
int *sock = static_cast<int *>(std::malloc(sizeof(int)));
if (!sock) {
return false;
}
#if 0
/* FIXME: this is problematic with gdm somehow, figure out why */
bool do_rundir = true;
/* overrides */
for (int i = 0; i < argc; ++i) {
if (!std::strcmp(argv[i], "norundir")) {
do_rundir = false;
}
}
#else
bool do_rundir = false;
#endif
/* blocking socket and a simple protocol */
*sock = socket(AF_UNIX, SOCK_SEQPACKET, 0);
if (*sock == -1) {
return false;
}
/* associate the socket with the session */
if (pam_set_data(
pamh, "pam_dinit_session", sock, free_sock
) != PAM_SUCCESS) {
return false;
}
sockaddr_un saddr;
std::memset(&saddr, 0, sizeof(saddr));
saddr.sun_family = AF_UNIX;
std::memcpy(saddr.sun_path, DAEMON_SOCK, sizeof(DAEMON_SOCK));
char const *puser;
char const *hdir;
char const *rdir;
passwd *pwd;
int ret, hlen, rlen;
auto send_msg = [sock](unsigned int msg) {
if (write(*sock, &msg, sizeof(msg)) < 0) {
return false;
}
return true;
};
if (pam_get_user(pamh, &puser, nullptr) != PAM_SUCCESS) {
goto err;
}
pwd = getpwnam(puser);
if (!pwd) {
goto err;
}
uid = pwd->pw_uid;
hdir = pam_getenv(pamh, "HOME");
if (!hdir || !hdir[0]) {
hdir = pwd->pw_dir;
}
if (!hdir || !hdir[0]) {
goto err;
}
hlen = strlen(hdir);
if (hlen > DIRLEN_MAX) {
goto err;
}
/* this is verified serverside too but bail out early if needed */
if (struct stat s; stat(hdir, &s) || !S_ISDIR(s.st_mode)) {
goto err;
}
/* the other runtime dir manager is expected to ensure that the
* rundir actually exists by this point (logind does ensure it)
*/
rdir = pam_getenv(pamh, "XDG_RUNTIME_DIR");
if (!rdir) {
rdir = "";
}
rlen = strlen(rdir);
if (rlen > DIRLEN_MAX) {
goto err;
} else if (rlen == 0) {
set_rundir = do_rundir;
}
if (connect(
*sock, reinterpret_cast<sockaddr const *>(&saddr), sizeof(saddr)
) < 0) {
goto err;
}
if (!send_msg(MSG_START)) {
goto err;
}
/* main message loop */
{
unsigned int msg;
unsigned int state = 0;
bool sent_uid = false;
bool sent_gid = false;
bool sent_hlen = false;
bool sent_rlen = false;
bool got_rlen = false;
char *rbuf = orbuf;
auto send_strpkt = [&send_msg](char const *&sdir, int &slen) {
unsigned int pkt = 0;
auto psize = MSG_SBYTES(slen);
std::memcpy(&pkt, sdir, psize);
pkt <<= MSG_TYPE_BITS;
pkt |= MSG_DATA;
if (!send_msg(pkt)) {
return false;
}
sdir += psize;
slen -= psize;
return true;
};
for (;;) {
ret = read(*sock, &msg, sizeof(msg));
if (ret < 0) {
goto err;
}
switch (state) {
case 0:
/* session not established yet */
if (msg != MSG_OK) {
goto err;
}
/* send uid */
if (!sent_uid) {
if (!send_msg(MSG_ENCODE(pwd->pw_uid))) {
goto err;
}
sent_uid = true;
break;
}
/* send gid */
if (!sent_gid) {
if (!send_msg(MSG_ENCODE(pwd->pw_gid))) {
goto err;
}
sent_gid = true;
break;
}
/* send homedir len */
if (!sent_hlen) {
if (!send_msg(MSG_ENCODE(hlen))) {
goto err;
}
sent_hlen = true;
break;
}
/* send a piece of homedir */
if (hlen) {
if (!send_strpkt(hdir, hlen)) {
goto err;
}
break;
}
/* send rundir len */
if (!sent_rlen) {
auto srlen = rlen;
if (!srlen && !do_rundir) {
srlen = DIRLEN_MAX + 1;
}
if (!send_msg(MSG_ENCODE(srlen))) {
goto err;
}
sent_rlen = true;
break;
}
/* send a piece of rundir */
if (rlen) {
if (!send_strpkt(rdir, rlen)) {
goto err;
}
break;
}
/* send clientside OK */
state = msg;
if (!send_msg(MSG_OK)) {
goto err;
}
break;
case MSG_OK:
/* if started, get the rundir back; else block */
if ((msg == MSG_OK_DONE) || (msg == MSG_OK_WAIT)) {
state = msg;
if ((msg == MSG_OK_DONE) && !send_msg(MSG_REQ_RLEN)) {
goto err;
}
continue;
}
/* bad message */
goto err;
case MSG_OK_WAIT:
/* if we previously waited and now got another message,
* it means either an error or that the system is now
* fully ready
*/
if (msg == MSG_OK_DONE) {
state = msg;
if (!send_msg(MSG_REQ_RLEN)) {
goto err;
}
continue;
}
/* bad message */
goto err;
case MSG_OK_DONE: {
if ((msg & MSG_TYPE_MASK) != MSG_DATA) {
goto err;
}
/* after MSG_OK_DONE, we should receive the runtime dir
* length first; if zero, it means we are completely done
*/
msg >>= MSG_TYPE_BITS;
if (!got_rlen) {
if (msg == 0) {
orlen = 0;
return true;
} else if (msg > DIRLEN_MAX) {
goto err;
}
got_rlen = true;
rlen = int(msg);
orlen = msg;
if (!send_msg(MSG_ENCODE_AUX(rlen, MSG_REQ_RDATA))) {
goto err;
}
continue;
}
/* we are receiving the string... */
int pkts = MSG_SBYTES(rlen);
std::memcpy(rbuf, &msg, pkts);
rbuf += pkts;
rlen -= pkts;
if (rlen == 0) {
/* we have received the whole thing, terminate */
*rbuf = '\0';
return true;
}
if (!send_msg(MSG_ENCODE_AUX(rlen, MSG_REQ_RDATA))) {
goto err;
}
/* keep receiving pieces */
continue;
}
default:
goto err;
}
}
}
return true;
err:
close(*sock);
*sock = -1;
return false;
}
extern "C" PAMAPI int pam_sm_open_session(
pam_handle_t *pamh, int, int argc, char const **argv
) {
unsigned int uid, rlen = 0;
bool set_rundir = false;
/* potential rundir we are managing */
char rdir[DIRLEN_MAX + 1];
if (!open_session(pamh, uid, argc, argv, rlen, rdir, set_rundir)) {
return PAM_SESSION_ERR;
}
if (rlen) {
char const dpfx[] = "DBUS_SESSION_BUS_ADDRESS=unix:path=";
char buf[sizeof(rdir) + sizeof(dpfx) + 4];
/* try exporting a dbus session bus variable */
std::snprintf(buf, sizeof(buf), "%s%s/bus", dpfx, rdir);
struct stat sbuf;
if (!lstat(strchr(buf, '/'), &sbuf) && S_ISSOCK(sbuf.st_mode)) {
if (pam_putenv(pamh, buf) != PAM_SUCCESS) {
return PAM_SESSION_ERR;
}
}
if (!set_rundir) {
return PAM_SUCCESS;
}
/* set rundir too if needed */
if (pam_misc_setenv(pamh, "XDG_RUNTIME_DIR", rdir, 1) != PAM_SUCCESS) {
return PAM_SESSION_ERR;
}
}
return PAM_SUCCESS;
}
extern "C" PAMAPI int pam_sm_close_session(
pam_handle_t *pamh, int, int, char const **
) {
void const *data;
/* there is nothing we can do here */
if (pam_get_data(pamh, "pam_dinit_session", &data) != PAM_SUCCESS) {
return PAM_SUCCESS;
}
int sock = *static_cast<int const *>(data);
if (sock < 0) {
return PAM_SUCCESS;
}
/* close the session */
close(sock);
return PAM_SUCCESS;
}

100
dinit-userservd/protocol.hh Normal file
View File

@ -0,0 +1,100 @@
/* defines the simple protocol between the daemon and the PAM module
*
* Copyright 2021 Daniel "q66" Kolesa <q66@chimera-linux.org>
* License: BSD-2-Clause
*/
#ifndef DINIT_USERSERVD_PROTOCOL_HH
#define DINIT_USERSERVD_PROTOCOL_HH
#include <sys/un.h>
#define RUNDIR_PATH "/run/user/%u"
#define SOCK_PATH "/run/dinit-userservd"
#define DAEMON_SOCK SOCK_PATH"/control.sock"
#define USER_PATH SOCK_PATH"/%u"
#define USER_FIFO USER_PATH"/dinit.fifo"
#define USER_DIR USER_PATH"/dinit.XXXXXX"
/* sanity check */
static_assert(
sizeof(DAEMON_SOCK) > sizeof(decltype(sockaddr_un{}.sun_family))
);
/* maximum length of a directory path we can receive */
#define DIRLEN_MAX 1024
/* protocol messages
*
* this is a simple protocol consisting of uint-sized messages; each
* message carries the type (4 bits) and optionally auxiliary data
* (only some messages; MSG_DATA and MSG_REQ_RDATA)
*
* dinit-userservd is the server; the pam module is the client
*
* the client connects to DAEMON_SOCK (seqpacket sockets are used)
*
* from there, the following sequence happens:
*
* CLIENT: sends MSG_START and enters a message loop (state machine)
* SERVER: receives it and adds the session into pending connections,
* then responds MSG_OK
* CLIENT: consumes MSG_OK, sends MSG_DATA with user id attached
* SERVER: responds MSG_OK
* CLIENT: consumes MSG_OK, sends MSG_DATA with group id attached
* SERVER: responds MSG_OK
* CLIENT: consumes MSG_OK, sends MSG_DATA with homedir length attached
* SERVER: validates, allocates a data buffer and responds MSG_OK
* loop:
* CLIENT: consumes MSG_OK, if there is any of homedir left unsent,
* it sends it; otherwise loop ends
* SERVER: adds to buffer, responds MSG_OK
* CLIENT: consumes MSG_OK, sends MSG_DATA with rundir length attached;
* if no rundir is set clientside, sends 0 instead and the server
* will make its own; if rundir handling is intentionally skipped,
* DIRLEN_MAX+1 is sent instead and the server will disregard it
* loop: same as above, but for rundir (nothing is sent for 0 length);
* at the end, server acknowledges the session and replies MSG_OK
* CLIENT: sends MSG_OK to confirm everything is ready on its side
* SERVER: if service manager for the user is already running, responds
* with MSG_OK_DONE; else initiates startup and responds with
* MSG_OK_WAIT
* CLIENT: if MSG_OK_WAIT was received, waits for a message
* SERVER: once service manager starts, MSG_OK_DONE is sent
* CLIENT: sends MSG_REQ_RLEN
* SERVER: responds with MSG_DATA with rundir length (0 if not known)
* loop:
* CLIENT: sends MSG_REQ_RDATA with number of remaining bytes of rundir
* that are yet to be received
* SERVER: responds with a MSG_DATA packet until none is left
* CLIENT: finishes startup, exports XDG_RUNTIME_DIR if needed as well
* as DBUS_SESSION_BUS_ADDRESS, and everything is done
*/
/* this is a regular unsigned int */
enum {
/* sent by the server as an acknowledgement of a message, and by
* the client once it has sent all the session info
*/
MSG_OK = 0x1,
MSG_OK_WAIT, /* login, wait */
MSG_OK_DONE, /* ready, proceed */
MSG_REQ_RLEN, /* rundir length request */
MSG_REQ_RDATA, /* rundir string request + how much is left */
MSG_DATA,
MSG_START,
/* sent by server on errors */
MSG_ERR,
MSG_TYPE_BITS = 4,
MSG_TYPE_MASK = 0xF,
MSG_DATA_BYTES = sizeof(unsigned int) - 1
};
#define MSG_ENCODE_AUX(v, tp) \
(tp | (static_cast<unsigned int>(v) << MSG_TYPE_BITS))
#define MSG_ENCODE(v) MSG_ENCODE_AUX(v, MSG_DATA)
#define MSG_SBYTES(len) std::min(int(MSG_DATA_BYTES), int(len))
#endif

View File

@ -0,0 +1,41 @@
pkgbase = linux-xanmod-edge
pkgdesc = Linux Xanmod - Latest Mainline (EDGE)
pkgver = 5.19.12
pkgrel = 1
url = http://www.xanmod.org/
arch = x86_64
license = GPL2
makedepends = bc
makedepends = cpio
makedepends = kmod
makedepends = libelf
makedepends = perl
makedepends = tar
makedepends = xz
options = !strip
source = https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.19.tar.xz
source = https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.19.tar.sign
source = https://github.com/xanmod/linux/releases/download/5.19.12-xanmod1/patch-5.19.12-xanmod1.xz
source = choose-gcc-optimization.sh
validpgpkeys = ABAF11C65A2970B130ABE3C479BE3E4300411886
validpgpkeys = 647F28654894E3BD457199BE38DBBDC86092693E
sha256sums = ff240c579b9ee1affc318917de07394fc1c3bb49dac25ec1287370c2e15005a8
sha256sums = SKIP
sha256sums = adb2a2e0e8cb1c8caf184712f486e4631324dda8a5686dde27dee253af4b0a13
sha256sums = dda2e928f3b02c28e71d4e99f90b499b4c99a265d30fceec7dc1dd7082afc285
pkgname = linux-xanmod-edge
pkgdesc = The Linux kernel and modules with Xanmod patches
depends = coreutils
depends = kmod
depends = initramfs
optdepends = crda: to set the correct wireless channels of your country
optdepends = linux-firmware: firmware images needed for some devices
provides = VIRTUALBOX-GUEST-MODULES
provides = WIREGUARD-MODULE
provides = KSMBD-MODULE
provides = NTFS3-MODULE
pkgname = linux-xanmod-edge-headers
pkgdesc = Headers and scripts for building modules for the Linux Xanmod - Latest Mainline (EDGE) kernel
depends = pahole

349
linux-xanmod-edge/PKGBUILD Normal file
View File

@ -0,0 +1,349 @@
# Maintainer: Joan Figueras <ffigue at gmail dot com>
# Contributor: Torge Matthies <openglfreak at googlemail dot com>
# Contributor: Jan Alexander Steffens (heftig) <jan.steffens@gmail.com>
##
## The following variables can be customized at build time. Use env or export to change at your wish
##
## Example: env _microarchitecture=98 use_numa=n use_tracers=n makepkg -sc
##
## Look inside 'choose-gcc-optimization.sh' to choose your microarchitecture
## Valid numbers between: 0 to 99
## Default is: 0 => generic
## Good option if your package is for one machine: 98 (Intel native) or 99 (AMD native)
if [ -z ${_microarchitecture+x} ]; then
_microarchitecture=0
fi
## Disable NUMA since most users do not have multiple processors. Breaks CUDA/NvEnc.
## Archlinux and Xanmod enable it by default.
## Set variable "use_numa" to: n to disable (possibly increase performance)
## y to enable (stock default)
if [ -z ${use_numa+x} ]; then
use_numa=y
fi
## For performance you can disable FUNCTION_TRACER/GRAPH_TRACER. Limits debugging and analyzing of the kernel.
## Stock Archlinux and Xanmod have this enabled.
## Set variable "use_tracers" to: n to disable (possibly increase performance)
## y to enable (stock default)
if [ -z ${use_tracers+x} ]; then
use_tracers=y
fi
## NOTICE: clang config is not ready yet in 5.17.x
## Choose between GCC and CLANG config (default is GCC)
if [ -z ${_compiler+x} ] || [ "$_compiler" = "clang" ]; then
_compiler=gcc
fi
# Choose between the 3 main configs for EDGE branch. Default x86-64-v2 which use CONFIG_GENERIC_CPU2:
# Possible values: config_x86-64 / config_x86-64-v2 (default) / config_x86-64-v3
# This will be overwritten by selecting any option in microarchitecture script
# Source files: https://github.com/xanmod/linux/tree/5.17/CONFIGS/xanmod/gcc
if [ -z ${_config+x} ]; then
_config=config_x86-64-v2
fi
# Compress modules with ZSTD (to save disk space)
if [ -z ${_compress_modules+x} ]; then
_compress_modules=n
fi
# Compile ONLY used modules to VASTLY reduce the number of modules built
# and the build time.
#
# To keep track of which modules are needed for your specific system/hardware,
# give module_db script a try: https://aur.archlinux.org/packages/modprobed-db
# This PKGBUILD read the database kept if it exists
#
# More at this wiki page ---> https://wiki.archlinux.org/index.php/Modprobed-db
if [ -z ${_localmodcfg} ]; then
_localmodcfg=n
fi
# Tweak kernel options prior to a build via nconfig
if [ -z ${_makenconfig} ]; then
_makenconfig=n
fi
### IMPORTANT: Do no edit below this line unless you know what you're doing
pkgbase=linux-xanmod-edge
_major=5.19
pkgver=${_major}.12
_branch=5.x
xanmod=1
pkgrel=${xanmod}
pkgdesc='Linux Xanmod - Latest Mainline (EDGE)'
url="http://www.xanmod.org/"
arch=(x86_64)
license=(GPL2)
makedepends=(
bc cpio kmod libelf perl tar xz
)
if [ "${_compiler}" = "clang" ]; then
makedepends+=(clang llvm lld python)
fi
options=('!strip')
_srcname="linux-${pkgver}-xanmod${xanmod}"
source=("https://cdn.kernel.org/pub/linux/kernel/v${_branch}/linux-${_major}.tar."{xz,sign}
"https://github.com/xanmod/linux/releases/download/${pkgver}-xanmod${xanmod}/patch-${pkgver}-xanmod${xanmod}.xz"
choose-gcc-optimization.sh)
#"patch-${pkgver}-xanmod${xanmod}.xz::https://sourceforge.net/projects/xanmod/files/releases/stable/${pkgver}-xanmod${xanmod}/patch-${pkgver}-xanmod${xanmod}.xz/download"
validpgpkeys=(
'ABAF11C65A2970B130ABE3C479BE3E4300411886' # Linux Torvalds
'647F28654894E3BD457199BE38DBBDC86092693E' # Greg Kroah-Hartman
)
# Archlinux patches
_commit="ec9e9a4219fe221dec93fa16fddbe44a34933d8d"
_patches=()
for _patch in ${_patches[@]}; do
#source+=("${_patch}::https://git.archlinux.org/svntogit/packages.git/plain/trunk/${_patch}?h=packages/linux&id=${_commit}")
source+=("${_patch}::https://raw.githubusercontent.com/archlinux/svntogit-packages/${_commit}/trunk/${_patch}")
done
sha256sums=('ff240c579b9ee1affc318917de07394fc1c3bb49dac25ec1287370c2e15005a8'
'SKIP'
'adb2a2e0e8cb1c8caf184712f486e4631324dda8a5686dde27dee253af4b0a13'
'dda2e928f3b02c28e71d4e99f90b499b4c99a265d30fceec7dc1dd7082afc285')
export KBUILD_BUILD_HOST=${KBUILD_BUILD_HOST:-archlinux}
export KBUILD_BUILD_USER=${KBUILD_BUILD_USER:-makepkg}
export KBUILD_BUILD_TIMESTAMP=${KBUILD_BUILD_TIMESTAMP:-$(date -Ru${SOURCE_DATE_EPOCH:+d @$SOURCE_DATE_EPOCH})}
prepare() {
cd linux-${_major}
# Apply Xanmod patch
patch -Np1 -i ../patch-${pkgver}-xanmod${xanmod}
msg2 "Setting version..."
scripts/setlocalversion --save-scmversion
echo "-$pkgrel" > localversion.10-pkgrel
echo "${pkgbase#linux-xanmod-edge}" > localversion.20-pkgname
# Archlinux patches
local src
for src in "${source[@]}"; do
src="${src%%::*}"
src="${src##*/}"
[[ $src = *.patch ]] || continue
msg2 "Applying patch $src..."
patch -Np1 < "../$src"
done
# Applying configuration
cp -vf CONFIGS/xanmod/${_compiler}/${_config} .config
# enable LTO_CLANG_THIN
if [ "${_compiler}" = "clang" ]; then
scripts/config --disable LTO_CLANG_FULL
scripts/config --enable LTO_CLANG_THIN
_LLVM=1
fi
# CONFIG_STACK_VALIDATION gives better stack traces. Also is enabled in all official kernel packages by Archlinux team
scripts/config --enable CONFIG_STACK_VALIDATION
# Enable IKCONFIG following Arch's philosophy
scripts/config --enable CONFIG_IKCONFIG \
--enable CONFIG_IKCONFIG_PROC
# User set. See at the top of this file
if [ "$use_tracers" = "n" ]; then
msg2 "Disabling FUNCTION_TRACER/GRAPH_TRACER only if we are not compiling with clang..."
if [ "${_compiler}" = "gcc" ]; then
scripts/config --disable CONFIG_FUNCTION_TRACER \
--disable CONFIG_STACK_TRACER
fi
fi
if [ "$use_numa" = "n" ]; then
msg2 "Disabling NUMA..."
scripts/config --disable CONFIG_NUMA
fi
# Compress modules by default (following Arch's kernel)
if [ "$_compress_modules" = "y" ]; then
scripts/config --enable CONFIG_MODULE_COMPRESS_ZSTD
fi
# Let's user choose microarchitecture optimization in GCC
# Use default microarchitecture only if we have not choosen another microarchitecture
if [ "$_microarchitecture" -ne "0" ]; then
../choose-gcc-optimization.sh $_microarchitecture
fi
# This is intended for the people that want to build this package with their own config
# Put the file "myconfig" at the package folder (this will take preference) or "${XDG_CONFIG_HOME}/linux-xanmod/myconfig"
# If we detect partial file with scripts/config commands, we execute as a script
# If not, it's a full config, will be replaced
for _myconfig in "${SRCDEST}/myconfig" "${HOME}/.config/linux-xanmod/myconfig" "${XDG_CONFIG_HOME}/linux-xanmod/myconfig" ; do
if [ -f "${_myconfig}" ] && [ "$(wc -l <"${_myconfig}")" -gt "0" ]; then
if grep -q 'scripts/config' "${_myconfig}"; then
# myconfig is a partial file. Executing as a script
msg2 "Applying myconfig..."
bash -x "${_myconfig}"
else
# myconfig is a full config file. Replacing default .config
msg2 "Using user CUSTOM config..."
cp -f "${_myconfig}" .config
fi
echo
break
fi
done
### Optionally load needed modules for the make localmodconfig
# See https://aur.archlinux.org/packages/modprobed-db
if [ "$_localmodcfg" = "y" ]; then
if [ -f $HOME/.config/modprobed.db ]; then
msg2 "Running Steven Rostedt's make localmodconfig now"
make LLVM=$_LLVM LLVM_IAS=$_LLVM LSMOD=$HOME/.config/modprobed.db localmodconfig
else
msg2 "No modprobed.db data found"
exit 1
fi
fi
make LLVM=$_LLVM LLVM_IAS=$_LLVM olddefconfig
make -s kernelrelease > version
msg2 "Prepared %s version %s" "$pkgbase" "$(<version)"
if [ "$_makenconfig" = "y" ]; then
make LLVM=$_LLVM LLVM_IAS=$_LLVM nconfig
fi
# save configuration for later reuse
cat .config > "${SRCDEST}/config.last"
}
build() {
cd linux-${_major}
make LLVM=$_LLVM LLVM_IAS=$_LLVM all
}
_package() {
pkgdesc="The Linux kernel and modules with Xanmod patches"
depends=(coreutils kmod initramfs)
optdepends=('crda: to set the correct wireless channels of your country'
'linux-firmware: firmware images needed for some devices')
provides=(VIRTUALBOX-GUEST-MODULES
WIREGUARD-MODULE
KSMBD-MODULE
NTFS3-MODULE)
cd linux-${_major}
local kernver="$(<version)"
local modulesdir="$pkgdir/usr/lib/modules/$kernver"
msg2 "Installing boot image..."
# systemd expects to find the kernel here to allow hibernation
# https://github.com/systemd/systemd/commit/edda44605f06a41fb86b7ab8128dcf99161d2344
install -Dm644 "$(make -s image_name)" "$modulesdir/vmlinuz"
# Used by mkinitcpio to name the kernel
echo "$pkgbase" | install -Dm644 /dev/stdin "$modulesdir/pkgbase"
msg2 "Installing modules..."
make INSTALL_MOD_PATH="$pkgdir/usr" INSTALL_MOD_STRIP=1 modules_install
# remove build and source links
rm "$modulesdir"/{source,build}
}
_package-headers() {
pkgdesc="Headers and scripts for building modules for the $pkgdesc kernel"
depends=(pahole)
cd linux-${_major}
local builddir="$pkgdir/usr/lib/modules/$(<version)/build"
msg2 "Installing build files..."
install -Dt "$builddir" -m644 .config Makefile Module.symvers System.map \
localversion.* version vmlinux
install -Dt "$builddir/kernel" -m644 kernel/Makefile
install -Dt "$builddir/arch/x86" -m644 arch/x86/Makefile
cp -t "$builddir" -a scripts
# required when STACK_VALIDATION is enabled
install -Dt "$builddir/tools/objtool" tools/objtool/objtool
# required when DEBUG_INFO_BTF_MODULES is enabled
if [ -f "$builddir/tools/bpf/resolve_btfids" ]; then install -Dt "$builddir/tools/bpf/resolve_btfids" tools/bpf/resolve_btfids/resolve_btfids ; fi
msg2 "Installing headers..."
cp -t "$builddir" -a include
cp -t "$builddir/arch/x86" -a arch/x86/include
install -Dt "$builddir/arch/x86/kernel" -m644 arch/x86/kernel/asm-offsets.s
install -Dt "$builddir/drivers/md" -m644 drivers/md/*.h
install -Dt "$builddir/net/mac80211" -m644 net/mac80211/*.h
# https://bugs.archlinux.org/task/13146
install -Dt "$builddir/drivers/media/i2c" -m644 drivers/media/i2c/msp3400-driver.h
# https://bugs.archlinux.org/task/20402
install -Dt "$builddir/drivers/media/usb/dvb-usb" -m644 drivers/media/usb/dvb-usb/*.h
install -Dt "$builddir/drivers/media/dvb-frontends" -m644 drivers/media/dvb-frontends/*.h
install -Dt "$builddir/drivers/media/tuners" -m644 drivers/media/tuners/*.h
# https://bugs.archlinux.org/task/71392
install -Dt "$builddir/drivers/iio/common/hid-sensors" -m644 drivers/iio/common/hid-sensors/*.h
echo "Installing KConfig files..."
find . -name 'Kconfig*' -exec install -Dm644 {} "$builddir/{}" \;
msg2 "Removing unneeded architectures..."
local arch
for arch in "$builddir"/arch/*/; do
[[ $arch = */x86/ ]] && continue
echo "Removing $(basename "$arch")"
rm -r "$arch"
done
msg2 "Removing documentation..."
rm -r "$builddir/Documentation"
msg2 "Removing broken symlinks..."
find -L "$builddir" -type l -printf 'Removing %P\n' -delete
msg2 "Removing loose objects..."
find "$builddir" -type f -name '*.o' -printf 'Removing %P\n' -delete
msg2 "Stripping build tools..."
local file
while read -rd '' file; do
case "$(file -bi "$file")" in
application/x-sharedlib\;*) # Libraries (.so)
strip -v $STRIP_SHARED "$file" ;;
application/x-archive\;*) # Libraries (.a)
strip -v $STRIP_STATIC "$file" ;;
application/x-executable\;*) # Binaries
strip -v $STRIP_BINARIES "$file" ;;
application/x-pie-executable\;*) # Relocatable binaries
strip -v $STRIP_SHARED "$file" ;;
esac
done < <(find "$builddir" -type f -perm -u+x ! -name vmlinux -print0)
msg2 "Stripping vmlinux..."
strip -v $STRIP_STATIC "$builddir/vmlinux"
msg2 "Adding symlink..."
mkdir -p "$pkgdir/usr/src"
ln -sr "$builddir" "$pkgdir/usr/src/$pkgbase"
}
pkgname=("${pkgbase}" "${pkgbase}-headers")
for _p in "${pkgname[@]}"; do
eval "package_$_p() {
$(declare -f "_package${_p#$pkgbase}")
_package${_p#$pkgbase}
}"
done
# vim:set ts=8 sts=2 sw=2 et:

View File

@ -0,0 +1,148 @@
#!/usr/bin/env bash
. /usr/share/makepkg/util/message.sh
colorize
Detect_CPU=$(gcc -c -Q -march=native --help=target | grep march | awk '{print $2}' | head -1)
msg "Detected CPU architecture: $Detect_CPU"
cat << EOF
Available CPU microarchitectures:
1) AMD K6/K6-II/K6-III
2) AMD Athlon/Duron/K7
3) AMD Opteron/Athlon64/Hammer/K8
4) AMD Opteron/Athlon64/Hammer/K8 with SSE3
5) AMD 61xx/7x50/PhenomX3/X4/II/K10
6) AMD Family 10h (Barcelona)
7) AMD Family 14h (Bobcat)
8) AMD Family 16h (Jaguar)
9) AMD Family 15h (Bulldozer)
10) AMD Family 15h (Piledriver)
11) AMD Family 15h (Steamroller)
12) AMD Family 15h (Excavator)
13) AMD Family 17h (Zen)
14) AMD Family 17h (Zen 2)
15) AMD Family 19h Zen 3 processors (Zen 3)
16) Transmeta Crusoe
17) Transmeta Efficeon
18) IDT Winchip C6
19) Winchip-2/Winchip-2A/Winchip-3
20) AMD Elan
21) Geode GX1 (Cyrix MediaGX)
22) AMD Geode GX and LX
23) Cyrix III or C3
24) VIA C3 "Nehemiah"
25) VIA C7
26) Intel Pentium 4, Pentium D and older Nocona/Dempsey Xeon CPUs with Intel 64bit
27) Intel Atom
28) Intel Core 2 and newer Core 2 Xeons (Xeon 51xx and 53xx)
29) Intel 1st Gen Core i3/i5/i7-family (Nehalem)
30) Intel 1.5 Gen Core i3/i5/i7-family (Westmere)
31) Intel Silvermont
32) Intel Goldmont (Apollo Lake and Denverton)
33) Intel Goldmont Plus (Gemini Lake)
34) Intel 2nd Gen Core i3/i5/i7-family (Sandybridge)
35) Intel 3rd Gen Core i3/i5/i7-family (Ivybridge)
36) Intel 4th Gen Core i3/i5/i7-family (Haswell)
37) Intel 5th Gen Core i3/i5/i7-family (Broadwell)
38) Intel 6th Gen Core i3/i5/i7-family (Skylake)
39) Intel 6th Gen Core i7/i9-family (Skylake X)
40) Intel 8th Gen Core i3/i5/i7-family (Cannon Lake)
41) Intel 8th Gen Core i7/i9-family (Ice Lake)
42) Xeon processors in the Cascade Lake family
43) Intel Xeon (Cooper Lake)
44) Intel 3rd Gen 10nm++ i3/i5/i7/i9-family (Tiger Lake)
45) Intel Sapphire Rapids
46) Intel Rocket Lake
47) Intel Alder Lake
92) Generic-x86-64-v2 (Nehalem and newer)
93) Generic-x86-64-v3 (Haswell and newer)
94) Generic-x86-64-v4 (AVX512 CPUs)
98) Intel-Native optimizations autodetected by GCC
99) AMD-Native optimizations autodetected by GCC
0) Generic x64-v2 (default)
EOF
sleep 1
answer=$1
case $answer in
1) Microarchitecture=CONFIG_MK6 ;;
2) Microarchitecture=CONFIG_MK7 ;;
3) Microarchitecture=CONFIG_MK8 ;;
4) Microarchitecture=CONFIG_MK8SSE3 ;;
5) Microarchitecture=CONFIG_MK10 ;;
6) Microarchitecture=CONFIG_MBARCELONA ;;
7) Microarchitecture=CONFIG_MBOBCAT ;;
8) Microarchitecture=CONFIG_MJAGUAR ;;
9) Microarchitecture=CONFIG_MBULLDOZER ;;
10) Microarchitecture=CONFIG_MPILEDRIVER ;;
11) Microarchitecture=CONFIG_MSTEAMROLLER ;;
12) Microarchitecture=CONFIG_MEXCAVATOR ;;
13) Microarchitecture=CONFIG_MZEN ;;
14) Microarchitecture=CONFIG_MZEN2 ;;
15) Microarchitecture=CONFIG_MZEN3 ;;
16) Microarchitecture=CONFIG_MCRUSOE ;;
17) Microarchitecture=CONFIG_MEFFICEON ;;
18) Microarchitecture=CONFIG_MWINCHIPC6 ;;
19) Microarchitecture=CONFIG_MWINCHIP3D ;;
20) Microarchitecture=CONFIG_MELAN ;;
21) Microarchitecture=CONFIG_MGEODEGX1 ;;
22) Microarchitecture=CONFIG_MGEODE_LX ;;
23) Microarchitecture=CONFIG_MCYRIXIII ;;
24) Microarchitecture=CONFIG_MVIAC3_2 ;;
25) Microarchitecture=CONFIG_MVIAC7 ;;
26) Microarchitecture=CONFIG_MPSC ;;
27) Microarchitecture=CONFIG_MATOM ;;
28) Microarchitecture=CONFIG_MCORE2 ;;
29) Microarchitecture=CONFIG_MNEHALEM ;;
30) Microarchitecture=CONFIG_MWESTMERE ;;
31) Microarchitecture=CONFIG_MSILVERMONT ;;
32) Microarchitecture=CONFIG_MGOLDMONT ;;
33) Microarchitecture=CONFIG_MGOLDMONTPLUS ;;
34) Microarchitecture=CONFIG_MSANDYBRIDGE ;;
35) Microarchitecture=CONFIG_MIVYBRIDGE ;;
36) Microarchitecture=CONFIG_MHASWELL ;;
37) Microarchitecture=CONFIG_MBROADWELL ;;
38) Microarchitecture=CONFIG_MSKYLAKE ;;
39) Microarchitecture=CONFIG_MSKYLAKEX ;;
40) Microarchitecture=CONFIG_MCANNONLAKE ;;
41) Microarchitecture=CONFIG_MICELAKE ;;
42) Microarchitecture=CONFIG_MCASCADELAKE ;;
43) Microarchitecture=CONFIG_MCOOPERLAKE ;;
44) Microarchitecture=CONFIG_MTIGERLAKE ;;
45) Microarchitecture=CONFIG_MSAPPHIRERAPIDS ;;
46) Microarchitecture=CONFIG_MROCKETLAKE ;;
47) Microarchitecture=CONFIG_MALDERLAKE ;;
92) Microarchitecture=CONFIG_GENERIC_CPU2 ;;
93) Microarchitecture=CONFIG_GENERIC_CPU3 ;;
94) Microarchitecture=CONFIG_GENERIC_CPU4 ;;
98) Microarchitecture=CONFIG_MNATIVE_INTEL ;;
99) Microarchitecture=CONFIG_MNATIVE_AMD ;;
*) default=CONFIG_GENERIC_CPU2 ;;
esac
warning "According to PKGBUILD variable _microarchitecture, your choice is $answer"
msg "Building this package for microarchitecture: $Microarchitecture$default"
sleep 5
_defaultmicro=$(grep ^CONFIG_LOCALVERSION .config)
if [ -z "${default}" ]; then
_localversion=$(echo ${Microarchitecture,,} | sed -e 's/config_m/-/g' -e 's/config_generic_cpu/-x64v/g')
sed -e "s|^$_defaultmicro|CONFIG_LOCALVERSION=\"$_localversion\"|g" -i .config
fi
sed -e 's|^CONFIG_GENERIC_CPU=y|# CONFIG_GENERIC_CPU is not set|g' -i .config
sed -e 's|^CONFIG_GENERIC_CPU2=y|# CONFIG_GENERIC_CPU2 is not set|g' -i .config
sed -e 's|^CONFIG_GENERIC_CPU3=y|# CONFIG_GENERIC_CPU3 is not set|g' -i .config
sed -e 's|^CONFIG_GENERIC_CPU4=y|# CONFIG_GENERIC_CPU4 is not set|g' -i .config
sed -e "s|^# $Microarchitecture is not set|$Microarchitecture=y|g" -i .config
echo